Skip to content

Commit fa472d2

Browse files
authored
Merge pull request #1379 from CVEProject/emathew/unprivileged-get-cve-count
Resolves issue 1378, creates new /cve_count endpoint
2 parents e779d56 + b75d942 commit fa472d2

File tree

8 files changed

+219
-3
lines changed

8 files changed

+219
-3
lines changed

api-docs/openapi.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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": [
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/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
}

test/README.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22

33
# CVE-API-Unit-Tests
4-
In order to Run Tests, make sure you configure a DB connection in the config/config.json under the `test` environment.
4+
In order to Run Tests, make sure you configure a DB connection in the config/default.json under the `test` environment.
55

66
## Dependencies
77

@@ -14,11 +14,16 @@ This project uses or depends on software from
1414
- Mocha https://mochajs.org/
1515
- Chai https://www.chaijs.com/
1616

17+
In order to pre-populate a new database for testing, run the following command:
18+
19+
```sh
20+
npm run populate:test
21+
```
1722

1823
In order to run unit tests, use the following command:
1924

2025
```sh
21-
npm run start:test
26+
npm run test
2227
```
2328

2429
## Notes
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/* eslint-disable no-unused-expressions */
2+
3+
const chai = require('chai')
4+
chai.use(require('chai-http'))
5+
const expect = chai.expect
6+
7+
const constants = require('../constants.js')
8+
const app = require('../../../src/index.js')
9+
10+
describe('Test get /cve_count for CVE records', () => {
11+
context('Positive Tests', () => {
12+
it('Get /cve_count should allow any user to get count', async () => {
13+
await chai.request(app)
14+
.get('/api/cve_count')
15+
.then((res, err) => {
16+
expect(err).to.be.undefined
17+
expect(res).to.have.status(200)
18+
expect(res.body).to.have.property('totalCount').that.is.a('number')
19+
})
20+
})
21+
it('Get /cve_count should allow privledged user to get count also', async () => {
22+
await chai.request(app)
23+
.get('/api/cve_count')
24+
.set(constants.headers)
25+
.then((res, err) => {
26+
expect(err).to.be.undefined
27+
expect(res).to.have.status(200)
28+
expect(res.body).to.have.property('totalCount').that.is.a('number')
29+
})
30+
})
31+
it('Get /cve_count should return count with valid parameters', async () => {
32+
await chai.request(app)
33+
.get('/api/cve_count?state=PUBLISHED')
34+
.set(constants.headers)
35+
.then((res, err) => {
36+
expect(err).to.be.undefined
37+
expect(res).to.have.status(200)
38+
expect(res.body).to.have.property('totalCount').that.is.a('number')
39+
})
40+
})
41+
})
42+
context('Negative Tests', () => {
43+
it('Get /cve should NOT allow any user to get count', async () => {
44+
await chai.request(app)
45+
.get('/api/cve?count_only=1')
46+
.then((res, err) => {
47+
expect(err).to.be.undefined
48+
expect(res).to.have.status(400)
49+
})
50+
})
51+
it('Get /cve_count should fail if it is passed invalid parameters', async () => {
52+
await chai.request(app)
53+
.get('/api/cve_count?time_modified.gt=2022-13-01T00:00:00Z')
54+
.set(constants.headers)
55+
.then((res, err) => {
56+
expect(err).to.be.undefined
57+
expect(res).to.have.status(400)
58+
expect(res.body.message).to.contain('Parameters were invalid')
59+
})
60+
})
61+
it('Get /cve_count should fail if it is `state` parameter value is invalid ', async () => {
62+
await chai.request(app)
63+
.get('/api/cve_count?state=SUCESS')
64+
.set(constants.headers)
65+
.then((res, err) => {
66+
expect(err).to.be.undefined
67+
expect(res).to.have.status(400)
68+
expect(res.body.message).to.contain('Parameters were invalid')
69+
})
70+
})
71+
})
72+
})

0 commit comments

Comments
 (0)