Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion api-docs/openapi.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"openapi": "3.0.2",
"info": {
"version": "0.5.0-beta",
"version": "1.0.0-beta",
"title": "CVE Search API",
"description": "CVE Search API to retrieve all matching CVE records after applying request inputs as filters.",
"contact": {
Expand Down
14 changes: 8 additions & 6 deletions controllers/searchController.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,20 @@ function getWebSearchSuccessData(searchResponse) {

const hits = searchResponse?.data?.hits;
const totalValue = hits?.total?.value;
const notes = searchResponse.notes === undefined ? [] : searchResponse.notes;
const responseErrors = searchResponse.errors === undefined ? [] : searchResponse.errors;
const hasValidMetadata =
typeof searchResponse.status === 'string' &&
Array.isArray(searchResponse.notes) &&
Array.isArray(searchResponse.errors);
typeof searchResponse.status === 'string' && Array.isArray(notes) && Array.isArray(responseErrors);

if (!hasValidMetadata || !Array.isArray(hits?.hits) || !Number.isSafeInteger(totalValue) || totalValue < 0) {
return null;
}

return {
hits: hits.hits,
totalValue
totalValue,
notes,
errors: responseErrors
};
}

Expand Down Expand Up @@ -286,8 +288,8 @@ async function webSearchHandler(req, res, next) {
if (successData) {
status = 200;
body.searchMetadata.searchStatus = searchResponse.status;
body.searchMetadata.notes = searchResponse.notes;
body.searchMetadata.errors = searchResponse.errors;
body.searchMetadata.notes = successData.notes;
body.searchMetadata.errors = successData.errors;
body.resultsTotal = successData.totalValue;
body.data = successData.hits;
} else {
Expand Down
32 changes: 29 additions & 3 deletions controllers/searchController.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ function rawResponse(totalValue, hits = []) {
return advancedResponse(totalValue, hits).data;
}

function basicResponse({ ok = true, status = 'ok', total = 0, hits = [], notes = [], errors = [] } = {}) {
function basicResponse({ ok = true, status = 'ok', total = 0, hits = [], notes, errors } = {}) {
return {
status,
notes,
Expand Down Expand Up @@ -1459,8 +1459,6 @@ describe('Search controller WEB_SEARCH handler', () => {
test('WEB_SEARCH fails closed when cve-core reports success without a complete hits response', async () => {
mockBasicSearch.mockResolvedValue({
status: 'ok',
notes: [],
errors: [],
data: {},
isOk: jest.fn(() => true)
});
Expand Down Expand Up @@ -1496,6 +1494,34 @@ describe('Search controller WEB_SEARCH handler', () => {
});
});

test.each([
['notes', 'invalid notes'],
['errors', { message: 'invalid errors' }]
])('WEB_SEARCH fails closed when successful cve-core metadata has invalid %s', async (field, value) => {
mockBasicSearch.mockResolvedValue({
...basicResponse(),
[field]: value
});

await controller.WEB_SEARCH(
{
body: {
query: 'apache'
}
},
res,
next
);

expect(res.status).toHaveBeenCalledWith(502);
expect(res.json.mock.calls[0][0].searchMetadata.errors).toStrictEqual([
{
error: 'UPSTREAM_SEARCH_ERROR',
message: 'Search backend returned an error. Please try again later.'
}
]);
});

test('WEB_SEARCH returns a sanitized error when BasicSearchManager throws', async () => {
mockBasicSearch.mockRejectedValue(new Error('boom'));

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cve-search-api",
"version": "0.5.0-beta",
"version": "1.0.0-beta",
"scripts": {
"dev": "node routes/swagger.js && nodemon server.js",
"coverage": "jest --coverage",
Expand Down
4 changes: 2 additions & 2 deletions routes/search.integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ function advancedResponse(totalValue, hits = []) {
function basicResponse({ total = 0, hits = [] } = {}) {
return {
status: 'ok',
notes: [],
errors: [],
data: {
hits: {
total: {
Expand Down Expand Up @@ -290,6 +288,8 @@ describe('search route integration', () => {
from: 5,
size: 10
});
expect(response.body.searchMetadata.notes).toStrictEqual([]);
expect(response.body.searchMetadata.errors).toStrictEqual([]);
expect(response.body.resultsTotal).toBe(1);
expect(response.body.data).toStrictEqual([{ _id: 'CVE-2024-0002' }]);
});
Expand Down
Loading