Skip to content

Commit 507aef9

Browse files
committed
Merge remote-tracking branch 'origin/date-handling-using-temporal-api' into 197-csaf-2.1-recommended-test-6.2.41
2 parents 67b07b0 + ab9618d commit 507aef9

21 files changed

+575
-35
lines changed

csaf_2_1/csafAjv.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import addFormats from 'ajv-formats'
2+
import Ajv2020 from 'ajv/dist/2020.js'
3+
import cvss_v2_0 from '../schemas/cvss-v2.0.js'
4+
import cvss_v3_0 from '../schemas/cvss-v3.0.js'
5+
import cvss_v3_1 from '../schemas/cvss-v3.1.js'
6+
import cvss_v4_0 from './csafAjv/cvss-v4.0.js'
7+
import meta from './csafAjv/meta.js'
8+
import formatAssertion from './csafAjv/format-assertion.js'
9+
import ssvcDecisionPointValueSelection from './csafAjv/Decision_Point_Value_Selection-1-0-1.js'
10+
import ssvcDecisionPoint from './csafAjv/Decision_Point-1-0-1.js'
11+
import { timestampRegex, validateTimestamp } from './dateHelper.js'
12+
13+
const csafAjv = new Ajv2020({ strict: false, allErrors: true })
14+
addFormats(csafAjv)
15+
csafAjv.addSchema(cvss_v2_0, 'https://www.first.org/cvss/cvss-v2.0.json')
16+
csafAjv.addSchema(cvss_v3_0, 'https://www.first.org/cvss/cvss-v3.0.json')
17+
csafAjv.addSchema(cvss_v3_1, 'https://www.first.org/cvss/cvss-v3.1.json')
18+
csafAjv.addSchema(cvss_v4_0, 'https://www.first.org/cvss/cvss-v4.0.json')
19+
csafAjv.addSchema(
20+
meta,
21+
'https://docs.oasis-open.org/csaf/csaf/v2.1/schema/meta.json'
22+
)
23+
csafAjv.addSchema(
24+
formatAssertion,
25+
'https://json-schema.org/draft/2020-12/meta/format-assertion'
26+
)
27+
csafAjv.addSchema(
28+
ssvcDecisionPointValueSelection,
29+
'https://certcc.github.io/SSVC/data/schema/v1/Decision_Point_Value_Selection-1-0-1.schema.json'
30+
)
31+
csafAjv.addSchema(
32+
ssvcDecisionPoint,
33+
'https://certcc.github.io/SSVC/data/schema/v1/Decision_Point-1-0-1.schema.json'
34+
)
35+
36+
csafAjv.addFormat('date-time', {
37+
type: 'string',
38+
validate: (v) => {
39+
return timestampRegex.test(v) && validateTimestamp(v)
40+
},
41+
})
42+
43+
export default csafAjv
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

csaf_2_1/dateHelper.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Temporal } from 'temporal-polyfill'
2+
3+
/**
4+
* compare iso timestamps
5+
* returns a negative number if a is less than b, positive if a is greater than b, and zero if they are equal.
6+
* This function also returns 0 if one of the given values could not be parsed.
7+
*
8+
* @param {string} a
9+
* @param {string} b
10+
*/
11+
export const compareZonedDateTimes = (a, b) => {
12+
try {
13+
const duration = Temporal.Instant.from(b).until(Temporal.Instant.from(a))
14+
return duration.sign
15+
} catch (e) {
16+
return 0
17+
}
18+
}
19+
20+
/**
21+
* This regex validates a date against RFC 3339 section 5.6.
22+
* See: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6
23+
*/
24+
export const timestampRegex =
25+
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/
26+
27+
/**
28+
* Checks if the given string is a semantically correct timestamp (RFC 3339). With one
29+
* exception: It does not allow leap seconds.
30+
*
31+
* @param {string} v
32+
* @returns
33+
*/
34+
export const validateTimestamp = (v) => {
35+
try {
36+
// Temporal.Instant.from() throws an error if the date is invalid. But they
37+
// normalize the date if e.g. there are 60 seconds (leap second) ...
38+
Temporal.Instant.from(v)
39+
40+
// ... To handle that case we additionally use the date constructor which
41+
// does not allow more than 59 seconds at all.
42+
if (Number.isNaN(new Date(v).getTime())) return false
43+
return true
44+
} catch (e) {
45+
return false
46+
}
47+
}

0 commit comments

Comments
 (0)