From 102700fd02ea809b2ad3535d3ac9fa80955857ea Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 01:31:06 +0100 Subject: [PATCH 01/14] fix(web-app-template): Reduce unnecessary render recomputations Prevent unnecessary recomputation of `SeverityIndex` and `isResolved` values in React, ensuring they are only recalculated when their actual values change. Signed-off-by: Thomas Steenbergen --- .../src/models/WebAppRuleViolation.js | 44 +++++++++++-------- .../src/models/WebAppVulnerability.js | 32 ++++++++------ 2 files changed, 44 insertions(+), 32 deletions(-) diff --git a/plugins/reporters/web-app-template/src/models/WebAppRuleViolation.js b/plugins/reporters/web-app-template/src/models/WebAppRuleViolation.js index 3fffa4713d518..8aeca4edd9483 100644 --- a/plugins/reporters/web-app-template/src/models/WebAppRuleViolation.js +++ b/plugins/reporters/web-app-template/src/models/WebAppRuleViolation.js @@ -24,6 +24,8 @@ class WebAppRuleViolation { #howToFix; + #isResolved; + #license; #licenseIndex; @@ -38,6 +40,8 @@ class WebAppRuleViolation { #severity; + #severityIndex; + #resolutionIndexes = new Set(); #resolutionReasons; @@ -82,6 +86,20 @@ class WebAppRuleViolation { this.#severity = obj.severity; } + switch (this.#severity) { + case 'ERROR': + this.#severityIndex = 0; + break; + case 'WARNING': + this.#severityIndex = 1; + break; + case 'HINT': + this.#severityIndex = 3; + break; + default: + this.#severityIndex = 4; + } + if (obj.resolutions) { this.#resolutionIndexes = new Set(obj.resolutions); } @@ -104,6 +122,12 @@ class WebAppRuleViolation { } } + this.#isResolved = !!(this.#resolutionIndexes.size > 0); + + if (this.#isResolved) { + this.#severityIndex = this.#severityIndex + 10; + } + this.key = randomStringGenerator(20); } } @@ -113,7 +137,7 @@ class WebAppRuleViolation { } get isResolved() { - return this.#resolutionIndexes && this.#resolutionIndexes.size > 0; + return this.#isResolved; } get howToFix() { @@ -189,23 +213,7 @@ class WebAppRuleViolation { } get severityIndex() { - if (this.isResolved) { - return 3; - } - - if (this.#severity === 'ERROR') { - return 0; - } - - if (this.#severity === 'WARNING') { - return 1; - } - - if (this.#severity === 'HINT') { - return 2; - } - - return -1; + return this.#severityIndex; } hasHowToFix() { diff --git a/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js b/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js index 13159c5b6625f..be9972fba8d90 100644 --- a/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js +++ b/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js @@ -26,6 +26,8 @@ class WebAppVulnerability { #id; + #isResolved; + #package; #packageIndex; @@ -69,6 +71,15 @@ class WebAppVulnerability { this.#resolutionIndexes = new Set(obj.resolutions); } + if (!this.#severityIndex) { + this.#severityIndex = 4; + this.#references.forEach((reference) => { + if (reference.severityIndex < this.#severityIndex) { + this.#severityIndex = reference.severityIndex; + } + }); + } + if (webAppOrtResult) { this.#webAppOrtResult = webAppOrtResult; @@ -78,6 +89,12 @@ class WebAppVulnerability { } } + this.#isResolved = !!(this.#resolutionIndexes.size > 0); + + if (this.#isResolved) { + this.#severityIndex += 10; + } + this.key = randomStringGenerator(20); } } @@ -91,11 +108,7 @@ class WebAppVulnerability { } get isResolved() { - if (this.#resolutionIndexes && this.#resolutionIndexes.size > 0) { - return true; - } - - return false; + return this.#isResolved; } get package() { @@ -147,15 +160,6 @@ class WebAppVulnerability { } get severityIndex() { - if (!this.#severityIndex) { - this.#severityIndex = 4; - this.#references.forEach((reference) => { - if (reference.severityIndex < this.#severityIndex) { - this.#severityIndex = reference.severityIndex; - } - }); - } - return this.#severityIndex; } } From 8f6caa32718c55ef24b222829e58f93300748e66 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sat, 25 Jan 2025 23:09:26 +0100 Subject: [PATCH 02/14] fix(web-app-template): Enhance rule severity icons Replace policy rule violation severity icons with tags so they are more distinguishable and quicker to understand. Signed-off-by: Thomas Steenbergen --- .../src/components/RuleViolationsTable.jsx | 56 +++++++++--------- .../src/components/SeverityTag.jsx | 57 +++++++++++++++++++ 2 files changed, 87 insertions(+), 26 deletions(-) create mode 100644 plugins/reporters/web-app-template/src/components/SeverityTag.jsx diff --git a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx index a33f34514650f..46cfc37ac6b91 100644 --- a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx +++ b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx @@ -23,16 +23,13 @@ import { } from 'react'; import { - ExclamationCircleOutlined, FileAddOutlined, - FileExcelOutlined, - InfoCircleOutlined, - IssuesCloseOutlined, - WarningOutlined + FileExcelOutlined } from '@ant-design/icons'; import { Collapse, Table, + Tag, Tooltip } from 'antd'; import Markdown from 'markdown-to-jsx'; @@ -44,6 +41,7 @@ import PackagePaths from './PackagePaths'; import PathExcludesTable from './PathExcludesTable'; import ResolutionTable from './ResolutionTable'; import ScopeExcludesTable from './ScopeExcludesTable'; +import SeverityTag from './SeverityTag'; import { getColumnSearchProps } from './Shared'; // Generates the HTML to display violations as a table @@ -159,59 +157,64 @@ const RuleViolationsTable = ({ webAppRuleViolations = [], showExcludesColumn = t key: 'severityIndex', filters: [ { - text: 'Errors', + text: (), value: 0 }, { - text: 'Warnings', + text: (), value: 1 }, { - text: 'Hint', + text: (), value: 2 }, { - text: 'Resolved', - value: 3 + text: (Resolved), + value: 10 } ], filteredValue: filteredInfo.severityIndex || null, - onFilter: (value, record) => record.severityIndex === Number(value), + onFilter: (value, record) => record.severityIndex === Number(value) + || (record.severityIndex > 10 && Number(value) >= 10), render: (text, record) => ( record.isResolved ? ( - - - + 0 ? 's' : '' + }`} + /> ) : ( { record.severity === 'ERROR' + && !record.isResolved && ( - ) } { record.severity === 'WARNING' + && !record.isResolved && ( - ) } { record.severity === 'HINT' + && !record.isResolved && ( - ) } @@ -220,7 +223,8 @@ const RuleViolationsTable = ({ webAppRuleViolations = [], showExcludesColumn = t ), sorter: (a, b) => a.severityIndex - b.severityIndex, sortOrder: sortedInfo.field === 'severityIndex' && sortedInfo.order, - width: '5em' + title: 'Severity', + width: '8em' }); columns.push( diff --git a/plugins/reporters/web-app-template/src/components/SeverityTag.jsx b/plugins/reporters/web-app-template/src/components/SeverityTag.jsx new file mode 100644 index 0000000000000..5854add7ca22a --- /dev/null +++ b/plugins/reporters/web-app-template/src/components/SeverityTag.jsx @@ -0,0 +1,57 @@ +/* + * Copyright (C) 2025 The ORT Project Authors (see ) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +import { + Tag, + Tooltip +} from 'antd'; + +const SeverityTag = ({ severity, isResolved = false, tooltipText = '' }) => { + const severityColors = { + error: '#e53e3e', + warning: '#f59e0b', + hint: '#84b6eb' + }; + + return isResolved + ? ( + + + + {`${severity.charAt(0).toUpperCase()}${severity.slice(1)}`} + + + + ) + : ( + + + {`${severity.charAt(0).toUpperCase()}${severity.slice(1)}`} + + ); +}; + +export default SeverityTag; From 5042d82f8a28610ddf4886730f01a0c6f5f78d1c Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 01:38:45 +0100 Subject: [PATCH 03/14] fix(web-app-template): Auto-fix minor linter issues Address minor linter issues by running `yarn lint --fix` to enhance code quality and maintainability. Signed-off-by: Thomas Steenbergen --- .../src/components/VulnerabilitiesTable.jsx | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx index a2c222194d422..7f3a8347b7b45 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx @@ -126,17 +126,17 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = if (webAppPackage) { return webAppPackage.isExcluded ? ( - - - - - + + + + + ) : ( - + ); } @@ -335,7 +335,7 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = expandedRowRender: (record) => { const webAppVulnerability = record.webAppVulnerability; const webAppPackage = webAppVulnerability.package; - let defaultActiveKey = record.isResolved + const defaultActiveKey = record.isResolved ? 'vulnerability-resolutions' : ['vulnerability-package-details', 'vulnerability-package-paths']; From a1c24bb7845e1b7afa821f4461131e8a15f297aa Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 02:56:46 +0100 Subject: [PATCH 04/14] fix(web-app-template): Enhance vulnerability severity filtering Improve the filtering of vulnerability severity levels to provide a clearer and more effective user experience. Signed-off-by: Thomas Steenbergen --- .../src/components/RuleViolationsTable.jsx | 11 +-- .../src/components/VulnerabilitiesTable.jsx | 88 ++++++++++++++----- .../src/components/VulnerabilityRatingTag.jsx | 39 +++++--- 3 files changed, 100 insertions(+), 38 deletions(-) diff --git a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx index 46cfc37ac6b91..538da9e66fffa 100644 --- a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx +++ b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx @@ -182,11 +182,12 @@ const RuleViolationsTable = ({ webAppRuleViolations = [], showExcludesColumn = t 0 ? 's' : '' - }`} + tooltipText={ + `Resolved with ${Array.from(record.webAppRuleViolation.resolutionReasons).join(', ') + } resolution${ + record.webAppRuleViolation.resolutionReasons.size > 0 ? 's' : '' + }` + } /> ) : ( diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx index 7f3a8347b7b45..7b0d9fa8b692e 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx @@ -25,12 +25,12 @@ import { import { FileAddOutlined, FileExcelOutlined, - FileProtectOutlined, - IssuesCloseOutlined + FileProtectOutlined } from '@ant-design/icons'; import { Collapse, Table, + Tag, Tooltip } from 'antd'; @@ -55,6 +55,11 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = key: webAppVulnerability.key, packageId: webAppVulnerability.package.id, references: webAppVulnerability.references, + resolutionReasonsText: `Resolved with ${ + Array.from(webAppVulnerability.resolutionReasons).join(', ') + } resolution${ + webAppVulnerability.resolutionReasons.size > 0 ? 's' : '' + }`, severity: webAppVulnerability.severity, severityIndex: webAppVulnerability.severityIndex, webAppVulnerability @@ -168,28 +173,73 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = text: (), value: 3 }, - { - text: (), - value: 5 - }, { text: (), value: 4 + }, + { + text: (Resolved), + value: 10 } ], filteredValue: filteredInfo.severityIndex || null, - onFilter: (value, record) => record.severityIndex === Number(value), + onFilter: (value, record) => record.severityIndex === Number(value) + || (record.severityIndex > 10 && Number(value) >= 10), render: (text, record) => ( record.isResolved ? ( - - - + + { + record.severityIndex === 10 + && ( + + ) + } + { + record.severityIndex === 11 + && ( + + ) + } + { + record.severityIndex === 12 + && ( + + ) + } + { + record.severityIndex === 13 + && ( + + ) + } + { + record.severityIndex === 14 + && ( + + ) + } + ) : ( @@ -223,19 +273,13 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = ) } - { - record.severityIndex === 5 - && ( - - ) - } ) ), sorter: (a, b) => a.severityIndex - b.severityIndex, sortOrder: sortedInfo.field === 'severityIndex' && sortedInfo.order, title: 'Severity', - width: '10em' + width: '8em' }); columns.push( diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilityRatingTag.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilityRatingTag.jsx index 17c2ebbfc47f3..3e4471f82650c 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilityRatingTag.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilityRatingTag.jsx @@ -17,25 +17,42 @@ * License-Filename: LICENSE */ -import { Tag } from 'antd'; +import { + Tag, + Tooltip +} from 'antd'; -const VulnerabilityRatingTag = ({ severity }) => { +const VulnerabilityRatingTag = ({ severity, isResolved = false, tooltipText = '' }) => { const severityColors = { critical: '#e53e3e', high: '#dd6b20', low: '#f6e05e', medium: '#f59e0b', - none: '#808080', - resolved: '#b0c4de' + none: '#808080' }; - return ( - - {`${severity.charAt(0).toUpperCase()}${severity.slice(1)}`} - - ); + return isResolved + ? ( + + + + {`${severity.charAt(0).toUpperCase()}${severity.slice(1)}`} + + + + ) + : ( + + {`${severity.charAt(0).toUpperCase()}${severity.slice(1)}`} + + ); }; export default VulnerabilityRatingTag; From 6691d546a2fc5e08862823948ae6430b9d618037 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 02:59:28 +0100 Subject: [PATCH 05/14] chore(web-app-template): Improve CSS comment for clarity Enhance comment to clearly indicate the elements to which the CSS classes apply, improving code readability. Signed-off-by: Thomas Steenbergen --- plugins/reporters/web-app-template/src/App.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/reporters/web-app-template/src/App.css b/plugins/reporters/web-app-template/src/App.css index 68ab51da7a45e..98af8e0a5e9df 100644 --- a/plugins/reporters/web-app-template/src/App.css +++ b/plugins/reporters/web-app-template/src/App.css @@ -64,7 +64,7 @@ /* === General === */ -/* Colors of exclude, error, hint and warning icons */ +/* Colors of exclude, error, hint and warning icons and texts */ .ort-error { color: #f5222d; } From c853a0033477869b38e801e2e4c7611e5a53d8bf Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 03:03:37 +0100 Subject: [PATCH 06/14] style(web-app-template): Align error color Align the red color of error text with the color of the critical known security vulnerability tag in `VulnerabilityRatingTag` to ensure consistency in visual representation. Signed-off-by: Thomas Steenbergen --- plugins/reporters/web-app-template/src/App.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/reporters/web-app-template/src/App.css b/plugins/reporters/web-app-template/src/App.css index 98af8e0a5e9df..7497283ab3971 100644 --- a/plugins/reporters/web-app-template/src/App.css +++ b/plugins/reporters/web-app-template/src/App.css @@ -66,7 +66,7 @@ /* Colors of exclude, error, hint and warning icons and texts */ .ort-error { - color: #f5222d; + color: #e53e3e; } .ort-excluded { From 79e94663e70a66c1ca267eafe090b399fc436ea4 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sun, 26 Jan 2025 03:25:10 +0100 Subject: [PATCH 07/14] fix(web-app-template): Display `id` property for vulnerability resolutions Ensure the `id` property of vulnerability resolutions [1] is displayed in `ResolutionTable`, addressing the previous limitation where only issue and policy rule violation resolutions [2] were supported. [1]: https://github.com/oss-review-toolkit/ort/blob/ef8b61c/website/docs/configuration/ort-yml.md#resolving-vulnerabilities [2]: https://github.com/oss-review-toolkit/ort/blob/ef8b61c/website/docs/configuration/ort-yml.md#resolution-basics Signed-off-by: Thomas Steenbergen --- .../VulnerabilitiesResolutionTable.jsx | 68 ++++++++++++++++++ .../src/components/VulnerabilitiesTable.jsx | 4 +- .../src/models/WebAppOrtResult.js | 3 +- .../models/WebAppVulnerabilityResolution.js | 70 +++++++++++++++++++ 4 files changed, 142 insertions(+), 3 deletions(-) create mode 100644 plugins/reporters/web-app-template/src/components/VulnerabilitiesResolutionTable.jsx create mode 100644 plugins/reporters/web-app-template/src/models/WebAppVulnerabilityResolution.js diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesResolutionTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesResolutionTable.jsx new file mode 100644 index 0000000000000..0dc19c86e2432 --- /dev/null +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesResolutionTable.jsx @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2025 The ORT Project Authors (see ) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +import { Table } from 'antd'; + +// Generates the HTML to display webAppVulnerabilityResolution(s) as a table +const VulnerabilitiesResolutionTable = ({ resolutions }) => { + const columns = [ + { + dataIndex: 'reason', + key: 'reason', + title: 'Reason' + }, + { + dataIndex: 'id', + key: 'id', + title: 'Id' + }, + { + dataIndex: 'comment', + key: 'comment', + textWrap: 'word-break', + title: 'Comment', + width: '50%' + } + ]; + + return ( + `${range[0]}-${range[1]} of ${total} results` + } + } + /> + ); +}; + +export default VulnerabilitiesResolutionTable; diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx index 7b0d9fa8b692e..9de4bd8f4f1b5 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx @@ -37,9 +37,9 @@ import { import PackageDetails from './PackageDetails'; import PackagePaths from './PackagePaths'; import PathExcludesTable from './PathExcludesTable'; -import ResolutionTable from './ResolutionTable'; import ScopeExcludesTable from './ScopeExcludesTable'; import { getColumnSearchProps } from './Shared'; +import VulnerabilitiesResolutionTable from './VulnerabilitiesResolutionTable'; import VulnerabilityRatingTag from './VulnerabilityRatingTag'; // Generates the HTML to display vulnerabilities as a table @@ -396,7 +396,7 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = label: 'Resolutions', key: 'vulnerability-resolutions', children: ( - ) diff --git a/plugins/reporters/web-app-template/src/models/WebAppOrtResult.js b/plugins/reporters/web-app-template/src/models/WebAppOrtResult.js index 260c41db008df..a7ee925549c15 100644 --- a/plugins/reporters/web-app-template/src/models/WebAppOrtResult.js +++ b/plugins/reporters/web-app-template/src/models/WebAppOrtResult.js @@ -33,6 +33,7 @@ import WebAppScope from './WebAppScope'; import WebAppScopeExclude from './WebAppScopeExclude'; import WebAppTreeNode from './WebAppTreeNode'; import WebAppVulnerability from './WebAppVulnerability'; +import WebAppVulnerabilityResolution from './WebAppVulnerabilityResolution'; class WebAppOrtResult { #concludedLicensePackages = []; @@ -328,7 +329,7 @@ class WebAppOrtResult { || obj.vulnerabilitiesResolutions; for (let i = 0, len = vulnerabilityResolutions.length; i < len; i++) { - this.#vulnerabilityResolutions.push(new WebAppResolution(vulnerabilityResolutions[i])); + this.#vulnerabilityResolutions.push(new WebAppVulnerabilityResolution(vulnerabilityResolutions[i])); } } diff --git a/plugins/reporters/web-app-template/src/models/WebAppVulnerabilityResolution.js b/plugins/reporters/web-app-template/src/models/WebAppVulnerabilityResolution.js new file mode 100644 index 0000000000000..014c4ea3341c5 --- /dev/null +++ b/plugins/reporters/web-app-template/src/models/WebAppVulnerabilityResolution.js @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2025 The ORT Project Authors (see ) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +import { randomStringGenerator } from '../utils'; + +class WebAppVulnerabilityResolution { + #_id; + + #comment; + + #id; + + #reason; + + constructor(obj) { + if (obj) { + if (Number.isInteger(obj._id)) { + this.#_id = obj._id; + } + + if (obj.comment) { + this.#comment = obj.comment; + } + + if (obj.id) { + this.#id = obj.id; + } + + if (obj.reason) { + this.#reason = obj.reason; + } + } + + this.key = randomStringGenerator(20); + } + + get _id() { + return this.#_id; + } + + get comment() { + return this.#comment; + } + + get id() { + return this.#id; + } + + get reason() { + return this.#reason; + } +} + +export default WebAppVulnerabilityResolution; From 550289b3bdb7d8669d5b6a42e2e2c281e65b7ed4 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Tue, 28 Jan 2025 17:26:59 +0100 Subject: [PATCH 08/14] fix(web-app-template): Enhance issue severity filtering Improve the filtering of issue severity levels to provide a clearer and more effective user experience. Signed-off-by: Thomas Steenbergen --- .../src/components/IssuesTable.jsx | 63 +++++++++++-------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx index 3ad9d4c63078d..faaddc0a7c826 100644 --- a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx @@ -23,14 +23,15 @@ import { } from 'react'; import { - ExclamationCircleOutlined, FileAddOutlined, - FileExcelOutlined, - InfoCircleOutlined, - IssuesCloseOutlined, - WarningOutlined + FileExcelOutlined } from '@ant-design/icons'; -import { Collapse, Table, Tooltip } from 'antd'; +import { + Collapse, + Table, + Tag, + Tooltip +} from 'antd'; import Markdown from 'markdown-to-jsx'; import PackageDetails from './PackageDetails'; @@ -40,6 +41,7 @@ import PackagePaths from './PackagePaths'; import PathExcludesTable from './PathExcludesTable'; import ResolutionTable from './ResolutionTable'; import ScopeExcludesTable from './ScopeExcludesTable'; +import SeverityTag from './SeverityTag'; import { getColumnSearchProps } from './Shared'; // Generates the HTML to display issues as a table @@ -155,59 +157,65 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => { key: 'severityIndex', filters: [ { - text: 'Errors', + text: (), value: 0 }, { - text: 'Warnings', + text: (), value: 1 }, { - text: 'Hint', + text: (), value: 2 }, { - text: 'Resolved', - value: 3 + text: (Resolved), + value: 10 } ], filteredValue: filteredInfo.severityIndex || null, - onFilter: (value, record) => record.severityIndex === Number(value), + onFilter: (value, record) => record.severityIndex === Number(value) + || (record.severityIndex > 10 && Number(value) >= 10), render: (text, record) => ( record.isResolved ? ( - - - + 0 ? 's' : '' + }` + } + /> ) : ( { record.severity === 'ERROR' + && !record.isResolved && ( - ) } { record.severity === 'WARNING' + && !record.isResolved && ( - ) } { record.severity === 'HINT' + && !record.isResolved && ( - ) } @@ -216,7 +224,8 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => { ), sorter: (a, b) => a.severityIndex - b.severityIndex, sortOrder: sortedInfo.field === 'severityIndex' && sortedInfo.order, - width: '5em' + title: 'Severity', + width: '8em' }); columns.push( From 5c8dad4609c9ec98554e7a61f35b7d96dbc37697 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Tue, 28 Jan 2025 17:34:02 +0100 Subject: [PATCH 09/14] fix(web-app-template): Fix issue severity filtering Re-apply parts 3106879 which was reverted for unclear reasons. Signed-off-by: Thomas Steenbergen --- .../web-app-template/src/components/IssuesTable.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx index faaddc0a7c826..0211535967709 100644 --- a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx @@ -76,7 +76,7 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => { excludes: [], message: [], packageId: [], - rule: [], + source: [], severityIndex: [] }); @@ -247,17 +247,17 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => { }, { dataIndex: 'source', - filteredValue: filteredInfo.rule || null, + filteredValue: filteredInfo.source || null, key: 'source', responsive: ['md'], - sorter: (a, b) => a.rule.localeCompare(b.rule), - sortOrder: sortedInfo.field === 'rule' && sortedInfo.order, + sorter: (a, b) => a.source.localeCompare(b.source), + sortOrder: sortedInfo.field === 'source' && sortedInfo.order, title: 'Source', width: '25%', ...getColumnSearchProps( 'source', - filteredInfo.rule, - (value) => setFilteredInfo({ ...filteredInfo, rule: value }) + filteredInfo.source, + (value) => setFilteredInfo({ ...filteredInfo, source: value }) ) }, { From 82821339efb7ab92ac31abc113c6c9aa350ecf33 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Wed, 29 Jan 2025 23:52:08 +0100 Subject: [PATCH 10/14] feat(web-app-template): Add `score` and `vector` to VulnerabilityReference Implement score and vector following their addition to VulnerabilityReference.kt in 60ef7c9. Signed-off-by: Thomas Steenbergen --- .../src/models/VulnerabilityReference.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/plugins/reporters/web-app-template/src/models/VulnerabilityReference.js b/plugins/reporters/web-app-template/src/models/VulnerabilityReference.js index 8f73ae1661680..f051304766974 100644 --- a/plugins/reporters/web-app-template/src/models/VulnerabilityReference.js +++ b/plugins/reporters/web-app-template/src/models/VulnerabilityReference.js @@ -20,14 +20,22 @@ class VulnerabilityReference { #scoringSystem; + #score; + #severity; #severityIndex; #url; + #vector + constructor(obj) { if (obj instanceof Object) { + if (obj.score !== null) { + this.#score = obj.score; + } + if (obj.scoring_system !== null || obj.scoringSystem) { this.#scoringSystem = obj.scoring_system || obj.cscoringSystem; } @@ -56,9 +64,17 @@ class VulnerabilityReference { if (obj.url !== null) { this.#url = obj.url; } + + if (obj.vector !== null) { + this.#vector = obj.vector; + } } } + get score() { + return this.#score; + } + get scoringSystem() { return this.#scoringSystem; } @@ -74,6 +90,10 @@ class VulnerabilityReference { get url() { return this.#url; } + + get vector() { + return this.#vector; + } } export default VulnerabilityReference; From f45201974b4bb751beddbedba7329abc20821c44 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Thu, 30 Jan 2025 00:00:54 +0100 Subject: [PATCH 11/14] feat(web-app-template): Add helper function to WebAppVulnerability In preparation for an upcoming change to show all references for each vulnerability. Signed-off-by: Thomas Steenbergen --- .../web-app-template/src/models/WebAppVulnerability.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js b/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js index be9972fba8d90..f771857e1329d 100644 --- a/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js +++ b/plugins/reporters/web-app-template/src/models/WebAppVulnerability.js @@ -162,6 +162,10 @@ class WebAppVulnerability { get severityIndex() { return this.#severityIndex; } + + hasReferences() { + return this.#references.length > 0; + } } export default WebAppVulnerability; From cd20cfc72b91c9cb41d0b71745b261665f112e4f Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Thu, 30 Jan 2025 00:10:17 +0100 Subject: [PATCH 12/14] feat(web-app-template): Display vulnerability references Show all reference information to facilitate the validation of vulnerabilities, enhancing user understanding. Signed-off-by: Thomas Steenbergen --- .../src/components/VulnerabilitiesTable.jsx | 24 ++- .../VulnerabilityReferencesList.jsx | 141 ++++++++++++++++++ 2 files changed, 163 insertions(+), 2 deletions(-) create mode 100644 plugins/reporters/web-app-template/src/components/VulnerabilityReferencesList.jsx diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx index 9de4bd8f4f1b5..b4372994cbbed 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx @@ -41,6 +41,7 @@ import ScopeExcludesTable from './ScopeExcludesTable'; import { getColumnSearchProps } from './Shared'; import VulnerabilitiesResolutionTable from './VulnerabilitiesResolutionTable'; import VulnerabilityRatingTag from './VulnerabilityRatingTag'; +import VulnerabilityReferencesList from './VulnerabilityReferencesList'; // Generates the HTML to display vulnerabilities as a table const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = true }) => { @@ -380,8 +381,15 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = const webAppVulnerability = record.webAppVulnerability; const webAppPackage = webAppVulnerability.package; const defaultActiveKey = record.isResolved - ? 'vulnerability-resolutions' - : ['vulnerability-package-details', 'vulnerability-package-paths']; + ? [ + 'vulnerability-resolutions', + 'vulnerability-references' + ] + : [ + 'vulnerability-references', + 'vulnerability-package-details', + 'vulnerability-package-paths' + ]; return ( + ) + }); + } + collapseItems.push({ label: 'Details', key: 'vulnerability-package-details', diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilityReferencesList.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilityReferencesList.jsx new file mode 100644 index 0000000000000..22dcf90f1ed15 --- /dev/null +++ b/plugins/reporters/web-app-template/src/components/VulnerabilityReferencesList.jsx @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2025 The ORT Project Authors (see ) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * License-Filename: LICENSE + */ + +import { + useState +} from 'react'; + +import { + Descriptions, + List +} from 'antd'; + +const { Item } = Descriptions; + +// Generates the HTML to display references for a vulnerability as a list +const VulnerabilityReferencesList = ({ references = [] }) => { + // State variable for displaying list in various pages + const [pagination, setPagination] = useState({ current: 1, pageSize: 5 }); + + // Handle for list pagination changes + const handlePaginationChange = (page, pageSize) => { + setPagination({ current: page, pageSize }); + }; + + return ( + { + const { + url, + scoringSystem, + severity, + score, + vector + } = reference; + + return ( + + + { + !!scoringSystem + && ( + + {scoringSystem} + + ) + } + { + !!score + && ( + + {score} + + ) + } + { + !!severity + && ( + + {severity} + + ) + } + { + !!vector + && ( + + {vector} + + ) + } + { + !!url + && ( + + + {url} + + + ) + } + + + ); + }} + /> + ) +}; + +export default VulnerabilityReferencesList; From 5e4aa35b708b4739be7f59b79d18ce2323b7f413 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Thu, 30 Jan 2025 00:19:34 +0100 Subject: [PATCH 13/14] fix(web-app-template): Correct pagination in various tables Ensure the `pageSize` is passed to pagination, allowing the table to adhere to the `pageSize` set in the initial state. Signed-off-by: Thomas Steenbergen --- .../reporters/web-app-template/src/components/IssuesTable.jsx | 1 + .../web-app-template/src/components/LicenseStatsTable.jsx | 4 ++-- .../web-app-template/src/components/VulnerabilitiesTable.jsx | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx index 0211535967709..58eded708362d 100644 --- a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx @@ -416,6 +416,7 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => { current: pagination.current, hideOnSinglePage: true, onChange: handlePaginationChange, + pageSize: pagination.pageSize, pageSizeOptions: ['50', '100', '250', '500', '1000', '5000'], position: 'bottom', showQuickJumper: true, diff --git a/plugins/reporters/web-app-template/src/components/LicenseStatsTable.jsx b/plugins/reporters/web-app-template/src/components/LicenseStatsTable.jsx index 083c49627f304..5b789d1194bfe 100644 --- a/plugins/reporters/web-app-template/src/components/LicenseStatsTable.jsx +++ b/plugins/reporters/web-app-template/src/components/LicenseStatsTable.jsx @@ -29,7 +29,7 @@ const LicenseStatsTable = ({ emptyText, licenses, licenseStats }) => { /* === Table state handling === */ // State variable for displaying table in various pages - const [pagination, setPagination] = useState({ current: 1, pageSize: 100 }); + const [pagination, setPagination] = useState({ current: 1, pageSize: 50 }); // State variable for filtering the contents of table columns const filteredInfoDefault = { @@ -94,10 +94,10 @@ const LicenseStatsTable = ({ emptyText, licenses, licenseStats }) => { pagination={ { current: pagination.current, - defaultPageSize: 50, hideOnSinglePage: true, onChange: handlePaginationChange, position: 'bottom', + pageSize: pagination.pageSize, pageSizeOptions: ['50', '100', '250', '500', '1000', '5000'], showTotal: (total, range) => `${range[0]}-${range[1]} of ${total} results` } diff --git a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx index b4372994cbbed..58960289651e4 100644 --- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx +++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx @@ -479,6 +479,7 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = current: pagination.current, hideOnSinglePage: true, onChange: handlePaginationChange, + pageSize: pagination.pageSize, pageSizeOptions: ['50', '100', '250', '500', '1000', '5000'], position: 'bottom', showQuickJumper: true, From 618ab4cc559287063aae3b8cf0f98a3342a52ec8 Mon Sep 17 00:00:00 2001 From: Thomas Steenbergen Date: Sat, 1 Feb 2025 22:59:36 +0100 Subject: [PATCH 14/14] fix(web-app-template): Fix webAppRuleViolation.package.id typeError Evaluator allows policy rule violations without a package see [1], however this case was not supported in the data mapping from `WebAppRuleViolation` to Ant Design table row data. Fixes #9880. [1]: https://github.com/oss-review-toolkit/ort/blob/cc6f09d/model/src/main/kotlin/RuleViolation.kt#L33 Signed-off-by: Thomas Steenbergen --- .../web-app-template/src/components/RuleViolationsTable.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx index 538da9e66fffa..97cebde51a0f7 100644 --- a/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx +++ b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx @@ -55,7 +55,8 @@ const RuleViolationsTable = ({ webAppRuleViolations = [], showExcludesColumn = t isResolved: webAppRuleViolation.isResolved, key: webAppRuleViolation.key, message: webAppRuleViolation.message, - packageId: webAppRuleViolation.package.id, + packageId: webAppRuleViolation.package + ? webAppRuleViolation.package.id : '', rule: webAppRuleViolation.rule, severity: webAppRuleViolation.severity, severityIndex: webAppRuleViolation.severityIndex,