Skip to content

Commit c6968cb

Browse files
refactor: use map to easier filter decision points
1 parent d178db2 commit c6968cb

File tree

1 file changed

+43
-46
lines changed

1 file changed

+43
-46
lines changed

csaf_2_1/mandatoryTests/mandatoryTest_6_1_48.js

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,27 @@ const inputSchema = /** @type {const} */ ({
5757

5858
const validateInput = ajv.compile(inputSchema)
5959

60+
/**
61+
* @param {string | undefined} name
62+
* @param {string | undefined} namespace
63+
* @param {string | undefined} version
64+
*/
65+
function decisionPointHash(name, namespace, version) {
66+
return JSON.stringify({
67+
name: name ?? '',
68+
namespace: namespace ?? '',
69+
version: version ?? '',
70+
})
71+
}
72+
73+
/** @type {Map<string,{ name: string; namespace: string; version: string; key?: string; values: { key: string; name: string; description: string; }[]; }>} */
74+
const decisionPointMap = new Map(
75+
ssvcDecisionPoints.decisionPoints.map((obj) => [
76+
decisionPointHash(obj.name, obj.namespace, obj.version),
77+
obj,
78+
])
79+
)
80+
6081
/**
6182
* This implements the mandatory test 6.1.48 of the CSAF 2.1 standard.
6283
*
@@ -74,16 +95,6 @@ export function mandatoryTest_6_1_48(doc) {
7495
}
7596

7697
const registeredSsvcNamespaces = ['ssvc', 'cvss']
77-
// subset of all the valid decision points containing only the relevant properties
78-
const relevantSsvcDecisionPointsSubset =
79-
ssvcDecisionPoints.decisionPoints.map((dp) =>
80-
JSON.stringify({
81-
name: dp.name ?? '',
82-
namespace: dp.namespace ?? '',
83-
version: dp.version ?? '',
84-
values: dp.values ?? '',
85-
})
86-
)
8798

8899
doc.vulnerabilities.forEach((vulnerability, vulnerabilityIndex) => {
89100
vulnerability.metrics?.forEach((metric, metricIndex) => {
@@ -93,46 +104,31 @@ export function mandatoryTest_6_1_48(doc) {
93104
s.namespace !== undefined &&
94105
registeredSsvcNamespaces.includes(s.namespace)
95106
)
96-
selectionsWithRegisteredNamespace?.forEach(
97-
(selection, selectionIndex) => {
98-
// check if a decision point with these properties exists
99-
const filteredDecisionPoints =
100-
relevantSsvcDecisionPointsSubset.filter((jsonDp) => {
101-
const dp = JSON.parse(jsonDp)
102-
return (
103-
dp.name === selection.name &&
104-
dp.namespace === selection.namespace &&
105-
dp.version === selection.version
106-
)
107-
})
108-
if (filteredDecisionPoints.length === 0) {
107+
selectionsWithRegisteredNamespace?.forEach((select, selectionIndex) => {
108+
// check if a decision point with these properties exists
109+
const selectedDecisionPnt = decisionPointMap.get(
110+
decisionPointHash(select.name, select.namespace, select.version)
111+
)
112+
113+
if (!selectedDecisionPnt) {
114+
ctx.isValid = false
115+
ctx.errors.push({
116+
instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/selections/${selectionIndex}`,
117+
message: `there exists no decision point with name ${select.name} and version ${select.version} in the namespace ${select.namespace}`,
118+
})
119+
} else {
120+
if (
121+
select.values &&
122+
!areValuesValidAndinOrder(selectedDecisionPnt.values, select.values)
123+
) {
109124
ctx.isValid = false
110125
ctx.errors.push({
111126
instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/selections/${selectionIndex}`,
112-
message: `there exists no decision point with name ${selection.name} and version ${selection.version} in the namespace ${selection.namespace}`,
127+
message: `this decision point contains invalid values or its values are not in order`,
113128
})
114-
} else {
115-
// name, namespace and version define a unique decisionPoint, i.e. the array filteredDecisionPoints
116-
// can only have zero (catched in the previous if-statement) or one entry.
117-
// Therefore, it is sufficient to access the first and only entry in filteredDecisionPoints here
118-
if (
119-
selection.values &&
120-
!areValuesValidAndinOrder(
121-
JSON.parse(filteredDecisionPoints[0]).values.map(
122-
(/** @type {{ name: string; }} */ value) => value.name
123-
),
124-
selection.values
125-
)
126-
) {
127-
ctx.isValid = false
128-
ctx.errors.push({
129-
instancePath: `/vulnerabilities/${vulnerabilityIndex}/metrics/${metricIndex}/content/ssvc_v1/selections/${selectionIndex}`,
130-
message: `this decision point contains invalid values or its values are not in order`,
131-
})
132-
}
133129
}
134130
}
135-
)
131+
})
136132
})
137133
})
138134

@@ -144,11 +140,12 @@ export function mandatoryTest_6_1_48(doc) {
144140
* according to the specification.
145141
* If values are missing, this is not an issue.
146142
*
147-
* @param {string[]} specifiedValues the valid elements of the values array of the respective decision point
143+
* @param {{ key: string; name: string; description: string; }[]} decisionPointValues the valid elements of the values array of the respective decision point
148144
* and their order according to the SSVC specification
149145
* @param {string[]} usedValues the actual used values of the decision point
150146
*/
151-
function areValuesValidAndinOrder(specifiedValues, usedValues) {
147+
function areValuesValidAndinOrder(decisionPointValues, usedValues) {
148+
const specifiedValues = decisionPointValues.map((value) => value.name)
152149
//check if there is an invalid value used
153150
for (let i = 0; i < usedValues.length; i++) {
154151
const element = usedValues[i]

0 commit comments

Comments
 (0)