diff --git a/plugins/reporters/web-app-template/src/App.css b/plugins/reporters/web-app-template/src/App.css
index 68ab51da7a45e..7497283ab3971 100644
--- a/plugins/reporters/web-app-template/src/App.css
+++ b/plugins/reporters/web-app-template/src/App.css
@@ -64,9 +64,9 @@
/* === General === */
-/* Colors of exclude, error, hint and warning icons */
+/* Colors of exclude, error, hint and warning icons and texts */
.ort-error {
- color: #f5222d;
+ color: #e53e3e;
}
.ort-excluded {
diff --git a/plugins/reporters/web-app-template/src/components/IssuesTable.jsx b/plugins/reporters/web-app-template/src/components/IssuesTable.jsx
index 3ad9d4c63078d..58eded708362d 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
@@ -74,7 +76,7 @@ const IssuesTable = ({ webAppOrtIssues = [], showExcludesColumn = true }) => {
excludes: [],
message: [],
packageId: [],
- rule: [],
+ source: [],
severityIndex: []
});
@@ -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(
@@ -238,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 })
)
},
{
@@ -407,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/RuleViolationsTable.jsx b/plugins/reporters/web-app-template/src/components/RuleViolationsTable.jsx
index a33f34514650f..97cebde51a0f7 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
@@ -57,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,
@@ -159,59 +158,65 @@ 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 +225,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;
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 a2c222194d422..58960289651e4 100644
--- a/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx
+++ b/plugins/reporters/web-app-template/src/components/VulnerabilitiesTable.jsx
@@ -25,22 +25,23 @@ import {
import {
FileAddOutlined,
FileExcelOutlined,
- FileProtectOutlined,
- IssuesCloseOutlined
+ FileProtectOutlined
} from '@ant-design/icons';
import {
Collapse,
Table,
+ Tag,
Tooltip
} from 'antd';
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';
+import VulnerabilityReferencesList from './VulnerabilityReferencesList';
// Generates the HTML to display vulnerabilities as a table
const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn = true }) => {
@@ -55,6 +56,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
@@ -126,17 +132,17 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn =
if (webAppPackage) {
return webAppPackage.isExcluded
? (
-
-
-
-
-
+
+
+
+
+
)
: (
-
+
);
}
@@ -168,28 +174,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 +274,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(
@@ -335,9 +380,16 @@ const VulnerabilitiesTable = ({ webAppVulnerabilities = [], showExcludesColumn =
expandedRowRender: (record) => {
const webAppVulnerability = record.webAppVulnerability;
const webAppPackage = webAppVulnerability.package;
- let defaultActiveKey = record.isResolved
- ? 'vulnerability-resolutions'
- : ['vulnerability-package-details', 'vulnerability-package-paths'];
+ const defaultActiveKey = record.isResolved
+ ? [
+ 'vulnerability-resolutions',
+ 'vulnerability-references'
+ ]
+ : [
+ 'vulnerability-references',
+ 'vulnerability-package-details',
+ 'vulnerability-package-paths'
+ ];
return (
)
});
}
+ if (webAppVulnerability.hasReferences()) {
+ collapseItems.push({
+ label: 'References',
+ key: 'vulnerability-references',
+ children: (
+
+ )
+ });
+ }
+
collapseItems.push({
label: 'Details',
key: 'vulnerability-package-details',
@@ -415,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,
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;
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;
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;
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/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..f771857e1329d 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,17 +160,12 @@ 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;
}
+
+ hasReferences() {
+ return this.#references.length > 0;
+ }
}
export default WebAppVulnerability;
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;