gopkg.in/alecthomas/gometalinter.v3@v3.0.0/_linters/src/github.com/securego/gosec/output/template.go (about) 1 // (c) Copyright 2016 Hewlett Packard Enterprise Development LP 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package output 16 17 const html = ` 18 <!doctype html> 19 <html lang="en"> 20 <head> 21 <meta charset="utf-8"> 22 <title>Go AST Scanner</title> 23 <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.2.1/css/bulma.min.css" integrity="sha256-DRcOKg8NK1KkSkcymcGmxOtS/lAn0lHWJXRa15gMHHk=" crossorigin="anonymous"/> 24 <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> 25 <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> 26 <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> 27 <style> 28 div.issue div.tag, div.panel-block input[type="checkbox"] { 29 margin-right: 0.5em; 30 } 31 32 label.disabled { 33 text-decoration: line-through; 34 } 35 36 nav.panel select { 37 width: 100%; 38 } 39 40 .break-word { 41 word-wrap: break-word; 42 } 43 </style> 44 </head> 45 <body> 46 <section class="section"> 47 <div class="container"> 48 <div id="content"></div> 49 </div> 50 </section> 51 <script> 52 var data = {{ . }}; 53 </script> 54 <script type="text/babel"> 55 var IssueTag = React.createClass({ 56 render: function() { 57 var level = "" 58 if (this.props.level === "HIGH") { 59 level = "is-danger"; 60 } 61 if (this.props.level === "MEDIUM") { 62 level = "is-warning"; 63 } 64 return ( 65 <div className={ "tag " + level }> 66 { this.props.label }: { this.props.level } 67 </div> 68 ); 69 } 70 }); 71 72 var Issue = React.createClass({ 73 render: function() { 74 return ( 75 <div className="issue box"> 76 <div className="is-pulled-right"> 77 <IssueTag label="Severity" level={ this.props.data.severity }/> 78 <IssueTag label="Confidence" level={ this.props.data.confidence }/> 79 </div> 80 <p> 81 <strong className="break-word"> 82 { this.props.data.file } (line { this.props.data.line }) 83 </strong> 84 <br/> 85 { this.props.data.details } 86 </p> 87 <figure className="highlight"> 88 <pre> 89 <code className="golang hljs"> 90 { this.props.data.code } 91 </code> 92 </pre> 93 </figure> 94 </div> 95 ); 96 } 97 }); 98 99 var Stats = React.createClass({ 100 render: function() { 101 return ( 102 <p className="help"> 103 Scanned { this.props.data.metrics.files.toLocaleString() } files 104 with { this.props.data.metrics.lines.toLocaleString() } lines of code. 105 </p> 106 ); 107 } 108 }); 109 110 var Issues = React.createClass({ 111 render: function() { 112 if (this.props.data.metrics.files === 0) { 113 return ( 114 <div className="notification"> 115 No source files found. Do you even Go? 116 </div> 117 ); 118 } 119 120 if (this.props.data.issues.length === 0) { 121 return ( 122 <div> 123 <div className="notification"> 124 Awesome! No issues found! 125 </div> 126 <Stats data={ this.props.data } /> 127 </div> 128 ); 129 } 130 131 var issues = this.props.data.issues 132 .filter(function(issue) { 133 return this.props.severity.includes(issue.severity); 134 }.bind(this)) 135 .filter(function(issue) { 136 return this.props.confidence.includes(issue.confidence); 137 }.bind(this)) 138 .filter(function(issue) { 139 if (this.props.issueType) { 140 return issue.details.toLowerCase().startsWith(this.props.issueType.toLowerCase()); 141 } else { 142 return true 143 } 144 }.bind(this)) 145 .map(function(issue) { 146 return (<Issue data={issue} />); 147 }.bind(this)); 148 149 if (issues.length === 0) { 150 return ( 151 <div> 152 <div className="notification"> 153 No issues matched given filters 154 (of total { this.props.data.issues.length } issues). 155 </div> 156 <Stats data={ this.props.data } /> 157 </div> 158 ); 159 } 160 161 return ( 162 <div className="issues"> 163 { issues } 164 <Stats data={ this.props.data } /> 165 </div> 166 ); 167 } 168 }); 169 170 var LevelSelector = React.createClass({ 171 handleChange: function(level) { 172 return function(e) { 173 var updated = this.props.selected 174 .filter(function(item) { return item != level; }); 175 if (e.target.checked) { 176 updated.push(level); 177 } 178 this.props.onChange(updated); 179 }.bind(this); 180 }, 181 render: function() { 182 var highDisabled = !this.props.available.includes("HIGH"); 183 var mediumDisabled = !this.props.available.includes("MEDIUM"); 184 var lowDisabled = !this.props.available.includes("LOW"); 185 186 return ( 187 <span> 188 <label className={"label checkbox " + (highDisabled ? "disabled" : "") }> 189 <input 190 type="checkbox" 191 checked={ this.props.selected.includes("HIGH") } 192 disabled={ highDisabled } 193 onChange={ this.handleChange("HIGH") }/> 194 High 195 </label> 196 <label className={"label checkbox " + (mediumDisabled ? "disabled" : "") }> 197 <input 198 type="checkbox" 199 checked={ this.props.selected.includes("MEDIUM") } 200 disabled={ mediumDisabled } 201 onChange={ this.handleChange("MEDIUM") }/> 202 Medium 203 </label> 204 <label className={"label checkbox " + (lowDisabled ? "disabled" : "") }> 205 <input 206 type="checkbox" 207 checked={ this.props.selected.includes("LOW") } 208 disabled={ lowDisabled } 209 onChange={ this.handleChange("LOW") }/> 210 Low 211 </label> 212 </span> 213 ); 214 } 215 }); 216 217 var Navigation = React.createClass({ 218 updateSeverity: function(vals) { 219 this.props.onSeverity(vals); 220 }, 221 updateConfidence: function(vals) { 222 this.props.onConfidence(vals); 223 }, 224 updateIssueType: function(e) { 225 if (e.target.value == "all") { 226 this.props.onIssueType(null); 227 } else { 228 this.props.onIssueType(e.target.value); 229 } 230 }, 231 render: function() { 232 var issueTypes = this.props.allIssueTypes 233 .map(function(it) { 234 return ( 235 <option value={ it } selected={ this.props.issueType == it }> 236 { it } 237 </option> 238 ); 239 }.bind(this)); 240 241 return ( 242 <nav className="panel"> 243 <div className="panel-heading"> 244 Filters 245 </div> 246 <div className="panel-block"> 247 <strong> 248 Severity 249 </strong> 250 </div> 251 <div className="panel-block"> 252 <LevelSelector 253 selected={ this.props.severity } 254 available={ this.props.allSeverities } 255 onChange={ this.updateSeverity } /> 256 </div> 257 <div className="panel-block"> 258 <strong> 259 Confidence 260 </strong> 261 </div> 262 <div className="panel-block"> 263 <LevelSelector 264 selected={ this.props.confidence } 265 available={ this.props.allConfidences } 266 onChange={ this.updateConfidence } /> 267 </div> 268 <div className="panel-block"> 269 <strong> 270 Issue Type 271 </strong> 272 </div> 273 <div className="panel-block"> 274 <select onChange={ this.updateIssueType }> 275 <option value="all" selected={ !this.props.issueType }> 276 (all) 277 </option> 278 { issueTypes } 279 </select> 280 </div> 281 </nav> 282 ); 283 } 284 }); 285 286 var IssueBrowser = React.createClass({ 287 getInitialState: function() { 288 return {}; 289 }, 290 componentWillMount: function() { 291 this.updateIssues(this.props.data); 292 }, 293 handleSeverity: function(val) { 294 this.updateIssueTypes(this.props.data.issues, val, this.state.confidence); 295 this.setState({severity: val}); 296 }, 297 handleConfidence: function(val) { 298 this.updateIssueTypes(this.props.data.issues, this.state.severity, val); 299 this.setState({confidence: val}); 300 }, 301 handleIssueType: function(val) { 302 this.setState({issueType: val}); 303 }, 304 updateIssues: function(data) { 305 if (!data) { 306 this.setState({data: data}); 307 return; 308 } 309 310 var allSeverities = data.issues 311 .map(function(issue) { 312 return issue.severity 313 }) 314 .sort() 315 .filter(function(item, pos, ary) { 316 return !pos || item != ary[pos - 1]; 317 }); 318 319 var allConfidences = data.issues 320 .map(function(issue) { 321 return issue.confidence 322 }) 323 .sort() 324 .filter(function(item, pos, ary) { 325 return !pos || item != ary[pos - 1]; 326 }); 327 328 var selectedSeverities = allSeverities; 329 var selectedConfidences = allConfidences; 330 331 this.updateIssueTypes(data.issues, selectedSeverities, selectedConfidences); 332 333 this.setState({ 334 data: data, 335 severity: selectedSeverities, 336 allSeverities: allSeverities, 337 confidence: selectedConfidences, 338 allConfidences: allConfidences, 339 issueType: null 340 }); 341 }, 342 updateIssueTypes: function(issues, severities, confidences) { 343 var allTypes = issues 344 .filter(function(issue) { 345 return severities.includes(issue.severity); 346 }) 347 .filter(function(issue) { 348 return confidences.includes(issue.confidence); 349 }) 350 .map(function(issue) { 351 return issue.details; 352 }) 353 .sort() 354 .filter(function(item, pos, ary) { 355 return !pos || item != ary[pos - 1]; 356 }); 357 358 if (this.state.issueType && !allTypes.includes(this.state.issueType)) { 359 this.setState({issueType: null}); 360 } 361 362 this.setState({allIssueTypes: allTypes}); 363 }, 364 render: function() { 365 return ( 366 <div className="content"> 367 <div className="columns"> 368 <div className="column is-one-quarter"> 369 <Navigation 370 severity={ this.state.severity } 371 confidence={ this.state.confidence } 372 issueType={ this.state.issueType } 373 allSeverities={ this.state.allSeverities } 374 allConfidences={ this.state.allConfidences } 375 allIssueTypes={ this.state.allIssueTypes } 376 onSeverity={ this.handleSeverity } 377 onConfidence={ this.handleConfidence } 378 onIssueType={ this.handleIssueType } 379 /> 380 </div> 381 <div className="column is-three-quarters"> 382 <Issues 383 data={ this.props.data } 384 severity={ this.state.severity } 385 confidence={ this.state.confidence } 386 issueType={ this.state.issueType } 387 /> 388 </div> 389 </div> 390 </div> 391 ); 392 } 393 }); 394 395 ReactDOM.render( 396 <IssueBrowser data={ data } />, 397 document.getElementById("content") 398 ); 399 </script> 400 </body> 401 </html>`