Skip to content

Commit bca4ef8

Browse files
authored
Merge pull request #1391 from CVEProject/prod-staging
Update Master to v2.5.4
2 parents fa88159 + 27a1f1a commit bca4ef8

File tree

12 files changed

+260
-36
lines changed

12 files changed

+260
-36
lines changed

api-docs/openapi.json

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"openapi": "3.0.2",
33
"info": {
4-
"version": "2.5.3",
4+
"version": "2.5.4",
55
"title": "CVE Services API",
66
"description": "The CVE Services API supports automation tooling for the CVE Program. Credentials are required for most service endpoints. Representatives of <a href='https://www.cve.org/ProgramOrganization/CNAs'>CVE Numbering Authorities (CNAs)</a> should use one of the methods below to obtain credentials: <ul><li>If your organization already has an Organizational Administrator (OA) account for the CVE Services, ask your admin for credentials</li> <li>Contact your Root (<a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/Google'>Google</a>, <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/INCIBE'>INCIBE</a>, <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/jpcert'>JPCERT/CC</a>, or <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/redhat'>Red Hat</a>) or Top-Level Root (<a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/icscert'>CISA ICS</a> or <a href='https://www.cve.org/PartnerInformation/ListofPartners/partner/mitre'>MITRE</a>) to request credentials </ul> <p>CVE data is to be in the JSON 5.1 CVE Record format. Details of the JSON 5.1 schema are located <a href='https://github.com/CVEProject/cve-schema/tree/v5.1.1-rc2/schema' target='_blank'>here</a>.</p> <a href='https://cveform.mitre.org/' class='link' target='_blank'>Contact the CVE Services team</a>",
77
"contact": {
@@ -1190,6 +1190,63 @@
11901190
}
11911191
}
11921192
},
1193+
"/cve_count": {
1194+
"get": {
1195+
"tags": [
1196+
"CVE Record"
1197+
],
1198+
"summary": "Retrieves the count of all the CVE Records after applying the query parameters as filters (accessible to all users)",
1199+
"description": " <h2>Access Control</h2> <p>Endpoint is accessible to all</p> <h2>Expected Behavior</h2> <p>Retrieves the count of all CVE records for all organizations</p>",
1200+
"operationId": "cveGetFilteredCount",
1201+
"parameters": [
1202+
{
1203+
"$ref": "#/components/parameters/cveState"
1204+
}
1205+
],
1206+
"responses": {
1207+
"200": {
1208+
"description": "A count of the total number of filtered CVE records",
1209+
"content": {
1210+
"application/json": {
1211+
"schema": {
1212+
"$ref": "../schemas/cve/get-cve-record-count.json"
1213+
}
1214+
}
1215+
}
1216+
},
1217+
"400": {
1218+
"description": "Bad Request",
1219+
"content": {
1220+
"application/json": {
1221+
"schema": {
1222+
"$ref": "../schemas/errors/bad-request.json"
1223+
}
1224+
}
1225+
}
1226+
},
1227+
"404": {
1228+
"description": "Not Found",
1229+
"content": {
1230+
"application/json": {
1231+
"schema": {
1232+
"$ref": "../schemas/errors/generic.json"
1233+
}
1234+
}
1235+
}
1236+
},
1237+
"500": {
1238+
"description": "Internal Server Error",
1239+
"content": {
1240+
"application/json": {
1241+
"schema": {
1242+
"$ref": "../schemas/errors/generic.json"
1243+
}
1244+
}
1245+
}
1246+
}
1247+
}
1248+
}
1249+
},
11931250
"/cve_cursor": {
11941251
"get": {
11951252
"tags": [

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "cve-services",
33
"author": "Automation Working Group",
4-
"version": "2.5.3",
4+
"version": "2.5.4",
55
"license": "(CC0)",
66
"devDependencies": {
77
"@faker-js/faker": "^7.6.0",
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-04/schema",
3+
"type": "object",
4+
"properties": {
5+
"totalCount": {
6+
"type": "integer",
7+
"format": "int32"
8+
}
9+
}
10+
}

src/controller/cve.controller/cve.controller.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,17 @@ async function getCve (req, res, next) {
3131
}
3232
}
3333

34+
// Called by GET /cve
35+
async function getFilteredCveCount (req, res, next) {
36+
try {
37+
req.ctx.query.count_only = '1'
38+
const result = await getFilteredCves(req, res, next)
39+
return result
40+
} catch (err) {
41+
next(err)
42+
}
43+
}
44+
3445
// Called by GET /cve
3546
async function getFilteredCves (req, res, next) {
3647
const CONSTANTS = getConstants()
@@ -916,6 +927,7 @@ module.exports = {
916927
CVE_GET_SINGLE: getCve,
917928
CVE_GET_FILTERED: getFilteredCves,
918929
CVE_GET_FILTERED_CURSOR: getFilteredCvesCursor,
930+
CVE_GET_FILTERED_COUNT: getFilteredCveCount,
919931
CVE_SUBMIT: submitCve,
920932
CVE_UPDATE_SINGLE: updateCve,
921933
CVE_SUBMIT_CNA: submitCna,

src/controller/cve.controller/index.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,58 @@ router.get('/cve',
274274
parseGetParams,
275275
controller.CVE_GET_FILTERED)
276276

277+
router.get('/cve_count',
278+
/*
279+
#swagger.tags = ['CVE Record']
280+
#swagger.operationId = 'cveGetFilteredCount'
281+
#swagger.summary = "Retrieves the count of all the CVE Records after applying the query parameters as filters (accessible to all users)"
282+
#swagger.description = "
283+
<h2>Access Control</h2>
284+
<p>Endpoint is accessible to all</p>
285+
<h2>Expected Behavior</h2>
286+
<p>Retrieves the count of all CVE records for all organizations</p>"
287+
#swagger.parameters['$ref'] = [
288+
'#/components/parameters/cveState',
289+
]
290+
#swagger.responses[200] = {
291+
description: 'A count of the total number of filtered CVE records',
292+
content: {
293+
"application/json": {
294+
schema: { $ref: '../schemas/cve/get-cve-record-count.json' }
295+
}
296+
}
297+
}
298+
#swagger.responses[400] = {
299+
description: 'Bad Request',
300+
content: {
301+
"application/json": {
302+
schema: { $ref: '../schemas/errors/bad-request.json' }
303+
}
304+
}
305+
}
306+
#swagger.responses[404] = {
307+
description: 'Not Found',
308+
content: {
309+
"application/json": {
310+
schema: { $ref: '../schemas/errors/generic.json' }
311+
}
312+
}
313+
}
314+
#swagger.responses[500] = {
315+
description: 'Internal Server Error',
316+
content: {
317+
"application/json": {
318+
schema: { $ref: '../schemas/errors/generic.json' }
319+
}
320+
}
321+
}
322+
*/
323+
query().custom((query) => { return mw.validateQueryParameterNames(query, ['state']) }),
324+
query(['state']).optional().isString().trim().customSanitizer(val => { return val.toUpperCase() }).isIn(CHOICES).withMessage(errorMsgs.CVE_FILTERED_STATES),
325+
parseError,
326+
parseGetParams,
327+
controller.CVE_GET_FILTERED_COUNT)
328+
277329
router.get('/cve_cursor',
278330
/*
279331
#swagger.tags = ['CVE Record']

src/controller/org.controller/org.controller.js

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ async function updateOrg (req, res, next) {
395395

396396
// update org
397397
let result = await orgRepo.updateByOrgUUID(org.UUID, newOrg)
398-
if (result.n === 0) {
398+
if (result.matchedCount === 0) {
399399
logger.info({ uuid: req.ctx.uuid, message: shortName + ' organization could not be updated in MongoDB because it does not exist.' })
400400
return res.status(404).json(error.orgDnePathParam(shortName))
401401
}
@@ -450,34 +450,42 @@ async function createUser (req, res, next) {
450450
return res.status(400).json(error.userLimitReached())
451451
}
452452

453-
Object.keys(req.ctx.body).forEach(k => {
454-
const key = k.toLowerCase()
453+
const body = req.ctx.body
454+
const keys = Object.keys(body)
455455

456-
if (key === 'username') {
457-
newUser.username = req.ctx.body.username
458-
} else if (key === 'authority') {
459-
if (req.ctx.body.authority.active_roles) {
460-
newUser.authority.active_roles = [...new Set(req.ctx.body.authority.active_roles)] // Removes any duplicate strings from array
461-
}
462-
} else if (key === 'name') {
463-
if (req.ctx.body.name.first) {
464-
newUser.name.first = req.ctx.body.name.first
465-
}
466-
if (req.ctx.body.name.last) {
467-
newUser.name.last = req.ctx.body.name.last
468-
}
469-
if (req.ctx.body.name.middle) {
470-
newUser.name.middle = req.ctx.body.name.middle
471-
}
472-
if (req.ctx.body.name.suffix) {
473-
newUser.name.suffix = req.ctx.body.name.suffix
474-
}
475-
} else if (key === 'org_uuid') {
476-
return res.status(400).json(error.uuidProvided('org'))
477-
} else if (key === 'uuid') {
456+
for (const keyRaw of keys) {
457+
const key = keyRaw.toLowerCase()
458+
459+
if (key === 'uuid') {
478460
return res.status(400).json(error.uuidProvided('user'))
479461
}
480-
})
462+
463+
if (key === 'org_uuid') {
464+
return res.status(400).json(error.uuidProvided('org'))
465+
}
466+
467+
const handlers = {
468+
username: () => {
469+
newUser.username = body.username
470+
},
471+
authority: () => {
472+
if (body.authority?.active_roles) {
473+
newUser.authority.active_roles = [...new Set(body.authority.active_roles)]
474+
}
475+
},
476+
name: () => {
477+
const name = body.name || {}
478+
if (name.first) newUser.name.first = name.first
479+
if (name.last) newUser.name.last = name.last
480+
if (name.middle) newUser.name.middle = name.middle
481+
if (name.suffix) newUser.name.suffix = name.suffix
482+
}
483+
}
484+
485+
if (handlers[key]) {
486+
handlers[key]() // execute the appropriate handler
487+
}
488+
}
481489

482490
const requesterOrgUUID = await orgRepo.getOrgUUID(requesterShortName)
483491
const isSecretariat = await orgRepo.isSecretariatUUID(requesterOrgUUID)
@@ -711,7 +719,7 @@ async function updateUser (req, res, next) {
711719
newUser.authority.active_roles = duplicateCheckedRoles
712720

713721
let result = await userRepo.updateByUserNameAndOrgUUID(username, orgUUID, newUser)
714-
if (result.n === 0) {
722+
if (result.matchedCount === 0) {
715723
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be updated because ' + username + ' does not exist for ' + shortName + ' organization.' })
716724
return res.status(404).json(error.userDne(username))
717725
}
@@ -786,7 +794,7 @@ async function resetSecret (req, res, next) {
786794
const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
787795
oldUser.secret = await argon2.hash(randomKey) // store in db
788796
const user = await userRepo.updateByUserNameAndOrgUUID(oldUser.username, orgUUID, oldUser)
789-
if (user.n === 0) {
797+
if (user.matchedCount === 0) {
790798
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be updated because ' + username + ' does not exist for ' + orgShortName + ' organization.' })
791799
return res.status(404).json(error.userDne(username))
792800
}

src/controller/schemas.controller/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ router.get('/cve/create-cve-record-cna-request.json', controller.getCnaFullSchem
2020
router.get('/cve/create-adp-record-adp-request.json', controller.getAdpFullSchema)
2121
router.get('/cve/create-cve-record-secretariat-request.json', controller.getCnaSecretariatFullSchema)
2222
router.get('/cve/cna-minimum-request.json', controller.getCnaMinSchema)
23+
router.get('/cve/get-cve-record-count.json', controller.getCveCountResponseSchema)
2324

2425
// Schemas relating to CVE IDs
2526
router.get('/cve-id/create-cve-ids-response.json', controller.getCreateCveIdsResponseSchema)

src/controller/schemas.controller/schemas.controller.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ async function getUpdateUserResponseSchema (req, res) {
222222
res.status(200)
223223
}
224224

225+
async function getCveCountResponseSchema (req, res) {
226+
const cveCountResponseSchema = require('../../../schemas/cve/get-cve-record-count.json')
227+
res.json(cveCountResponseSchema)
228+
res.status(200)
229+
}
230+
225231
module.exports = {
226232
getBadRequestSchema: getBadRequestSchema,
227233
getCreateCveRecordResponseSchema: getCreateCveRecordResponseSchema,
@@ -258,5 +264,6 @@ module.exports = {
258264
getCnaFullSchema: getCnaFullSchema,
259265
getAdpFullSchema: getAdpFullSchema,
260266
getCnaSecretariatFullSchema: getCnaSecretariatFullSchema,
261-
getCnaMinSchema: getCnaMinSchema
267+
getCnaMinSchema: getCnaMinSchema,
268+
getCveCountResponseSchema: getCveCountResponseSchema
262269
}

src/swagger.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const fullCnaContainerRequest = require('../schemas/cve/create-cve-record-cna-re
1818
/* eslint-disable no-multi-str */
1919
const doc = {
2020
info: {
21-
version: '2.5.3',
21+
version: '2.5.4',
2222
title: 'CVE Services API',
2323
description: "The CVE Services API supports automation tooling for the CVE Program. Credentials are \
2424
required for most service endpoints. Representatives of \

0 commit comments

Comments
 (0)