Update the design of HTML report

This commit is contained in:
Matthieu MOREL 2021-05-25 10:10:42 +02:00 committed by GitHub
parent e72f54ed40
commit 91dae7fdce
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -20,30 +20,26 @@ const templateContent = `
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>Golang Security Checker</title> <title>Golang Security Checker</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.1/css/bulma.min.css" integrity="sha256-DRcOKg8NK1KkSkcymcGmxOtS/lAn0lHWJXRa15gMHHk=" crossorigin="anonymous"/> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.2/css/bulma.min.css" integrity="sha512-byErQdWdTqREz6DLAA9pCnLbdoGGhXfU6gm1c8bkf7F51JVmUBlayGe2A31VpXWQP+eiJ3ilTAZHCR3vmMyybA==" crossorigin="anonymous"/>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/styles/default.min.css" integrity="sha512-kZqGbhf9JTB4bVJ0G8HCkqmaPcRgo88F0dneK30yku5Y/dep7CZfCnNml2Je/sY4lBoqoksXz4PtVXS4GHSUzQ==" crossorigin="anonymous"/>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/highlight.min.js" integrity="sha512-s+tOYYcC3Jybgr9mVsdAxsRYlGNq4mlAurOrfNuGMQ/SCofNPu92tjE7YRZCsdEtWL1yGkqk15fU/ark206YTg==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.7.2/languages/go.min.js" integrity="sha512-+UYV2NyyynWEQcZ4sMTKmeppyV331gqvMOGZ61/dqc89Tn1H40lF05ACd03RSD9EWwGutNwKj256mIR8waEJBQ==" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js" integrity="sha256-cLWs9L+cjZg8CjGHMpJqUgKKouPlmoMP/0wIdPtaPGs=" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react.min.js" integrity="sha256-cLWs9L+cjZg8CjGHMpJqUgKKouPlmoMP/0wIdPtaPGs=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js" integrity="sha256-JIW8lNqN2EtqC6ggNZYnAdKMJXRQfkPMvdRt+b0/Jxc=" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.2/react-dom.min.js" integrity="sha256-JIW8lNqN2EtqC6ggNZYnAdKMJXRQfkPMvdRt+b0/Jxc=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.17.0/babel.min.js" integrity="sha256-1IWWLlCKFGFj/cjryvC7GDF5wRYnf9tSvNVVEj8Bm+o=" crossorigin="anonymous"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.17.0/babel.min.js" integrity="sha256-1IWWLlCKFGFj/cjryvC7GDF5wRYnf9tSvNVVEj8Bm+o=" crossorigin="anonymous"></script>
<style> <style>
div.issue div.tag, div.panel-block input[type="checkbox"] { .field-label {
margin-right: 0.5em; min-width: 80px;
} }
.break-word {
label.disabled { word-wrap: break-word;
text-decoration: line-through; }
} .help {
white-space: pre-wrap;
nav.panel select { }
width: 100%; .tag {
} width: 80px;
}
.break-word {
word-wrap: break-word;
}
.help {
white-space: pre-wrap;
}
</style> </style>
</head> </head>
<body> <body>
@ -58,49 +54,63 @@ const templateContent = `
<script type="text/babel"> <script type="text/babel">
var IssueTag = React.createClass({ var IssueTag = React.createClass({
render: function() { render: function() {
var level = "tag " var level = "tag"
if (this.props.level === "HIGH") { if (this.props.level === "HIGH") {
level += "is-danger"; level += " is-danger";
} else if (this.props.level === "MEDIUM") { } else if (this.props.level === "MEDIUM") {
level += "is-warning"; level += " is-warning";
} else if (this.props.level === "LOW") {
level += " is-info";
} }
level +=" is-rounded";
return ( return (
<div className={ level }> <div className="control">
{ this.props.label }: { this.props.level } <div className="tags has-addons">
<span className="tag is-dark is-rounded">{ this.props.label }</span>
<span className={ level }>{ this.props.level }</span>
</div>
</div> </div>
); );
} }
}); });
var Highlight = React.createClass({
componentDidMount: function(){
var current = ReactDOM.findDOMNode(this);
hljs.highlightElement(current);
},
render: function() {
return (
<pre className="go"><code >{ this.props.code }</code></pre>
);
}
});
var Issue = React.createClass({ var Issue = React.createClass({
render: function() { render: function() {
return ( return (
<div className="issue box"> <div className="issue box">
<div className="is-pulled-right"> <div className="columns">
<IssueTag label="Severity" level={ this.props.data.severity }/> <div className="column is-three-quarters">
<IssueTag label="Confidence" level={ this.props.data.confidence }/> <strong className="break-word">{ this.props.data.file } (line { this.props.data.line })</strong>
<p>{ this.props.data.details }</p>
</div>
<div className="column is-one-quarter">
<div className="field is-grouped is-grouped-multiline">
<IssueTag label="Severity" level={ this.props.data.severity }/>
<IssueTag label="Confidence" level={ this.props.data.confidence }/>
</div>
</div>
</div>
<div className="highlight">
<Highlight code={ this.props.data.code }/>
</div> </div>
<p>
<strong className="break-word">
{ this.props.data.file } (line { this.props.data.line })
</strong>
<br/>
{ this.props.data.details }
</p>
<figure className="highlight">
<pre>
<code className="go">{ this.props.data.code }</code>
</pre>
</figure>
</div> </div>
); );
} }
}); });
var Stats = React.createClass({ var Stats = React.createClass({
render: function() { render: function() {
return ( return (
<p className="help"> <p className="help is-pulled-right">
Gosec {this.props.data.GosecVersion} scanned { this.props.data.Stats.files.toLocaleString() } files Gosec {this.props.data.GosecVersion} scanned { this.props.data.Stats.files.toLocaleString() } files
with { this.props.data.Stats.lines.toLocaleString() } lines of code. with { this.props.data.Stats.lines.toLocaleString() } lines of code.
{ this.props.data.Stats.nosec ? '\n' + this.props.data.Stats.nosec.toLocaleString() + ' false positives (nosec) have been waived.' : ''} { this.props.data.Stats.nosec ? '\n' + this.props.data.Stats.nosec.toLocaleString() + ' false positives (nosec) have been waived.' : ''}
@ -108,7 +118,6 @@ const templateContent = `
); );
} }
}); });
var Issues = React.createClass({ var Issues = React.createClass({
render: function() { render: function() {
if (this.props.data.Stats.files === 0) { if (this.props.data.Stats.files === 0) {
@ -118,7 +127,6 @@ const templateContent = `
</div> </div>
); );
} }
if (this.props.data.Issues.length === 0) { if (this.props.data.Issues.length === 0) {
return ( return (
<div> <div>
@ -129,7 +137,6 @@ const templateContent = `
</div> </div>
); );
} }
var issues = this.props.data.Issues var issues = this.props.data.Issues
.filter(function(issue) { .filter(function(issue) {
return this.props.severity.includes(issue.severity); return this.props.severity.includes(issue.severity);
@ -147,7 +154,6 @@ const templateContent = `
.map(function(issue) { .map(function(issue) {
return (<Issue data={issue} />); return (<Issue data={issue} />);
}.bind(this)); }.bind(this));
if (issues.length === 0) { if (issues.length === 0) {
return ( return (
<div> <div>
@ -159,7 +165,6 @@ const templateContent = `
</div> </div>
); );
} }
return ( return (
<div className="issues"> <div className="issues">
{ issues } { issues }
@ -184,38 +189,36 @@ const templateContent = `
var highDisabled = !this.props.available.includes(HIGH); var highDisabled = !this.props.available.includes(HIGH);
var mediumDisabled = !this.props.available.includes(MEDIUM); var mediumDisabled = !this.props.available.includes(MEDIUM);
var lowDisabled = !this.props.available.includes(LOW); var lowDisabled = !this.props.available.includes(LOW);
var on = "", off = "disabled";
var baseClassName = "label checkbox ";
var highClassName = baseClassName + (highDisabled ? off : on);
var mediumClassName = baseClassName + (mediumDisabled ? off : on);
var lowClassName = baseClassName + (lowDisabled ? off : on);
return ( return (
<span> <div className="field">
<label className={ highClassName }> <div className="control">
<input <label className="checkbox" disabled={ highDisabled }>
type="checkbox" <input
checked={ this.props.selected.includes(HIGH) } type="checkbox"
disabled={ highDisabled } checked={ this.props.selected.includes(HIGH) }
onChange={ this.handleChange(HIGH) }/> disabled={ highDisabled }
High onChange={ this.handleChange(HIGH) }/> High
</label> </label>
<label className={mediumClassName}> </div>
<input <div className="control">
type="checkbox" <label className="checkbox" disabled={ mediumDisabled }>
checked={ this.props.selected.includes(MEDIUM) } <input
disabled={ mediumDisabled } type="checkbox"
onChange={ this.handleChange(MEDIUM) }/> checked={ this.props.selected.includes(MEDIUM) }
Medium disabled={ mediumDisabled }
</label> onChange={ this.handleChange(MEDIUM) }/> Medium
<label className={lowClassName}> </label>
<input </div>
type="checkbox" <div className="control">
checked={ this.props.selected.includes(LOW) } <label className="checkbox" disabled={ lowDisabled }>
disabled={ lowDisabled } <input
onChange={ this.handleChange(LOW) }/> type="checkbox"
Low checked={ this.props.selected.includes(LOW) }
</label> disabled={ lowDisabled }
</span> onChange={ this.handleChange(LOW) }/> Low
</label>
</div>
</div>
); );
} }
}); });
@ -245,44 +248,46 @@ const templateContent = `
}.bind(this)); }.bind(this));
return ( return (
<nav className="panel"> <nav className="panel">
<div className="panel-heading"> <div className="panel-heading">Filters</div>
Filters <div className="panel-block">
<div className="field is-horizontal">
<div className="field-label is-normal">
<label className="label is-pulled-left">Severity</label>
</div>
<div className="field-body">
<LevelSelector selected={ this.props.severity } available={ this.props.allSeverities } onChange={ this.updateSeverity } />
</div>
</div>
</div> </div>
<div className="panel-block"> <div className="panel-block">
<strong> <div className="field is-horizontal">
Severity <div className="field-label is-normal">
</strong> <label className="label is-pulled-left">Confidence</label>
</div>
<div className="field-body">
<LevelSelector selected={ this.props.confidence } available={ this.props.allConfidences } onChange={ this.updateConfidence } />
</div>
</div>
</div> </div>
<div className="panel-block"> <div className="panel-block">
<LevelSelector <div className="field is-horizontal">
selected={ this.props.severity } <div className="field-label is-normal">
available={ this.props.allSeverities } <label className="label is-pulled-left">Issue type</label>
onChange={ this.updateSeverity } /> </div>
</div> <div className="field-body">
<div className="panel-block"> <div className="field">
<strong> <div className="control">
Confidence <div className="select is-fullwidth">
</strong> <select onChange={ this.updateIssueType }>
</div> <option value="all" selected={ !this.props.issueType }>
<div className="panel-block"> (all)
<LevelSelector </option>
selected={ this.props.confidence } { issueTypes }
available={ this.props.allConfidences } </select>
onChange={ this.updateConfidence } /> </div>
</div> </div>
<div className="panel-block"> </div>
<strong> </div>
Issue Type
</strong>
</div>
<div className="panel-block">
<div className="select">
<select onChange={ this.updateIssueType }>
<option value="all" selected={ !this.props.issueType }>
(all)
</option>
{ issueTypes }
</select>
</div> </div>
</div> </div>
</nav> </nav>
@ -390,7 +395,6 @@ const templateContent = `
); );
} }
}); });
ReactDOM.render( ReactDOM.render(
<IssueBrowser data={ data } />, <IssueBrowser data={ data } />,
document.getElementById("content") document.getElementById("content")