Skip to content

Commit 61a297f

Browse files
committed
Merge branch 'dev' into emathew/testing
2 parents 61402c5 + af1417f commit 61a297f

File tree

12 files changed

+282
-231
lines changed

12 files changed

+282
-231
lines changed

api-docs/openapi.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"openapi": "3.0.2",
33
"info": {
4-
"version": "ur-v0.2.0-beta.3",
4+
"version": "ur-v0.3.0",
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.2 CVE Record format. Details of the JSON 5.2 schema are located <a href='https://github.com/CVEProject/cve-schema/releases/tag/v5.2.0' target='_blank'>here</a>.</p> <a href='https://cveform.mitre.org/' class='link' target='_blank'>Contact the CVE Services team</a>",
77
"contact": {

package-lock.json

Lines changed: 218 additions & 173 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": "ur-v0.2.0-beta.3",
4+
"version": "ur-v0.3.0",
55
"license": "(CC0)",
66
"devDependencies": {
77
"@faker-js/faker": "^7.6.0",

src/controller/registry-user.controller/registry-user.controller.js

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,16 +178,13 @@ async function updateUser (req, res, next) {
178178

179179
async function deleteUser (req, res, next) {
180180
try {
181-
const userRepo = req.ctx.repositories.getUserRepository()
182-
const orgRepo = req.ctx.repositories.getOrgRepository()
183-
const registryUserRepo = req.ctx.repositories.getRegistryUserRepository()
181+
const userRepo = req.ctx.repositories.getBaseUserRepository()
182+
const orgRepo = req.ctx.repositories.getBaseOrgRepository()
184183
const userUUID = req.ctx.params.identifier
185184

186-
const user = await registryUserRepo.findOneByUUID(userUUID)
187-
188-
// TODO: check permissions
185+
const user = await userRepo.findOneByUUID(userUUID)
189186

190-
await registryUserRepo.deleteByUUID(userUUID)
187+
await userRepo.deleteByUUID(userUUID)
191188

192189
const payload = {
193190
action: 'delete_registry_user',

src/controller/review-object.controller/review-object.controller.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,15 @@ async function approveReviewObject (req, res, next) {
4343
const repo = req.ctx.repositories.getReviewObjectRepository()
4444
const userRepo = req.ctx.repositories.getBaseUserRepository()
4545
const UUID = req.params.uuid
46+
const body = req.body
4647
const session = await mongoose.startSession()
4748
let value
4849

4950
try {
5051
session.startTransaction()
5152
const requestingUserUUID = await userRepo.getUserUUID(req.ctx.user, req.ctx.org, { session })
5253

53-
value = await repo.approveReviewOrgObject(UUID, requestingUserUUID, { session })
54+
value = await repo.approveReviewOrgObject(UUID, requestingUserUUID, { session }, body)
5455
await session.commitTransaction()
5556
} catch (updateErr) {
5657
await session.abortTransaction()

src/middleware/middleware.js

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ async function optionallyValidateUser (req, res, next) {
4444
const org = req.ctx.org
4545
const user = req.ctx.user
4646
const key = req.ctx.key
47-
const userRepo = req.ctx.repositories.getUserRepository()
48-
const orgRepo = req.ctx.repositories.getOrgRepository()
47+
const userRepo = req.ctx.repositories.getBaseUserRepository()
48+
const orgRepo = req.ctx.repositories.getBaseOrgRepository()
4949
let authenticated = true
5050

5151
try {
@@ -127,7 +127,7 @@ async function validateUser (req, res, next) {
127127
return res.status(401).json(error.unauthorized())
128128
}
129129

130-
const result = await userRepo.findOneByUsernameAndOrgUUID(user, orgUUID)
130+
const result = await userRepo.findOneByUserNameAndOrgUUID(user, orgUUID)
131131
if (!result) {
132132
logger.warn(JSON.stringify({ uuid: req.ctx.uuid, message: 'User not found. User authentication FAILED for ' + user }))
133133
return res.status(401).json(error.unauthorized())
@@ -176,24 +176,6 @@ async function onlySecretariatOrBulkDownload (req, res, next) {
176176
}
177177
}
178178

179-
async function onlySecretariatUserRegistry (req, res, next) {
180-
const org = req.ctx.org
181-
const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository()
182-
const CONSTANTS = getConstants()
183-
184-
try {
185-
const isSec = await registryOrgRepo.isSecretariat(org)
186-
if (!isSec) {
187-
logger.info({ uuid: req.ctx.uuid, message: org + ' is NOT a ' + CONSTANTS.AUTH_ROLE_ENUM.SECRETARIAT })
188-
return res.status(403).json(error.secretariatOnly())
189-
}
190-
logger.info({ uuid: req.ctx.uuid, message: 'Confirmed ' + org + 'as a Secretariat' })
191-
next()
192-
} catch (err) {
193-
next(err)
194-
}
195-
}
196-
197179
// Checks that the requester belongs to an org that has the 'SECRETARIAT' role
198180

199181
async function onlySecretariat (req, res, next) {
@@ -577,7 +559,6 @@ module.exports = {
577559
onlySecretariat,
578560
onlySecretariatOrBulkDownload,
579561
onlySecretariatOrAdmin,
580-
onlySecretariatUserRegistry,
581562
onlyCnas,
582563
onlyAdps,
583564
onlyOrgWithPartnerRole,

src/repositories/baseUserRepository.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ class BaseUserRepository extends BaseRepository {
9898
return user || null
9999
}
100100

101-
async findOneByUsernameAndOrgUUID (username, orgUUID, options = {}, isLegacyObject = false) {
101+
async findOneByUserNameAndOrgUUID (username, orgUUID, options = {}, isLegacyObject = false) {
102102
const legacyUserRepo = new UserRepository()
103103
const users = await BaseUser.find({ username: username }, null, options)
104104
if (!users || users.length === 0) {
@@ -125,6 +125,34 @@ class BaseUserRepository extends BaseRepository {
125125
return user || null
126126
}
127127

128+
/**
129+
* Delete a user by UUID from both BaseUser and RegistryUser collections,
130+
* and remove the user reference from any organizations.
131+
*
132+
* @param {string} uuid - The UUID of the user to delete.
133+
* @param {object} options - Mongoose options for the delete operations.
134+
* @returns {Promise<number>} Number of deleted documents (should be 1 if successful).
135+
*/
136+
async deleteUserByUUID (uuid, options = {}) {
137+
// Delete from BaseUser collection
138+
const deleteResult = await BaseUser.deleteOne({ UUID: uuid }, options)
139+
140+
// Delete from RegistryUser collection
141+
await RegistryUser.deleteOne({ UUID: uuid }, options)
142+
143+
// Remove user from any organization’s users and admins arrays
144+
const orgs = await BaseOrgModel.find({ $or: [{ users: uuid }, { admins: uuid }] })
145+
for (const org of orgs) {
146+
org.users = org.users.filter(u => u !== uuid)
147+
if (Array.isArray(org.admins)) {
148+
org.admins = org.admins.filter(a => a !== uuid)
149+
}
150+
await org.save({ options })
151+
}
152+
153+
return deleteResult.deletedCount
154+
}
155+
128156
async getUserUUID (username, orgShortname, options = {}, isLegacyObject = false) {
129157
const user = await this.findOneByUsernameAndOrgShortname(username, orgShortname, options, isLegacyObject)
130158
if (user) {

src/repositories/reviewObjectRepository.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const ReviewObjectModel = require('../model/reviewobject')
22
const BaseRepository = require('./baseRepository')
33
const BaseOrgRepository = require('./baseOrgRepository')
44
const uuid = require('uuid')
5+
const _ = require('lodash')
56

67
class ReviewObjectRepository extends BaseRepository {
78
async findOneByOrgShortName (orgShortName, options = {}) {
@@ -115,7 +116,7 @@ class ReviewObjectRepository extends BaseRepository {
115116
return result.toObject()
116117
}
117118

118-
async approveReviewOrgObject (UUID, requestingUserUUID, options = {}) {
119+
async approveReviewOrgObject (UUID, requestingUserUUID, options = {}, newReviewData) {
119120
console.log('Approving review object with UUID:', UUID)
120121
const reviewObject = await this.findOneByUUID(UUID, options)
121122
if (!reviewObject) {
@@ -129,13 +130,20 @@ class ReviewObjectRepository extends BaseRepository {
129130
}
130131

131132
// We need to trigger the org to update
132-
await baseOrgRepository.updateOrgFull(org.short_name, reviewObject.new_review_data, options, false, requestingUserUUID, false, true)
133+
let dataToUpdate
134+
if (newReviewData && Object.keys(newReviewData).length) {
135+
dataToUpdate = _.merge(org.toObject(), newReviewData)
136+
} else {
137+
dataToUpdate = reviewObject.new_review_data
138+
}
139+
await baseOrgRepository.updateOrgFull(org.short_name, dataToUpdate, options, false, requestingUserUUID, false, true)
133140

134-
reviewObject.status = 'approved'
141+
// Delete the review object after approval
142+
await this.deleteReviewObjectByUUID(UUID, options)
135143

136-
await reviewObject.save({ options })
137-
const result = reviewObject.toObject()
138-
return result
144+
// Return the updated organization
145+
const updatedOrg = await baseOrgRepository.findOneByUUID(reviewObject.target_object_uuid, options)
146+
return updatedOrg ? updatedOrg.toObject() : null
139147
}
140148
}
141149

src/swagger.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const fullCnaContainerRequest = require('../schemas/cve/create-cve-record-cna-re
2020
/* eslint-disable no-multi-str */
2121
const doc = {
2222
info: {
23-
version: 'ur-v0.2.0-beta.3',
23+
version: 'ur-v0.3.0',
2424
title: 'CVE Services API',
2525
description: "The CVE Services API supports automation tooling for the CVE Program. Credentials are \
2626
required for most service endpoints. Representatives of \

src/utils/utils.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ async function getUserUUID (userIdentifier, orgUUID, useRegistry = false, option
4343
return userDocument ? userDocument.UUID : null
4444
} else {
4545
const baseUserRepository = new BaseUserRepository()
46-
const userDocument = await baseUserRepository.findOneByUsernameAndOrgUUID(userIdentifier, orgUUID, options)
46+
const userDocument = await baseUserRepository.findOneByUserNameAndOrgUUID(userIdentifier, orgUUID, options)
4747
return userDocument ? userDocument.UUID : null
4848
}
4949
}
@@ -113,7 +113,7 @@ async function isAdmin (requesterUsername, requesterShortName, isRegistry = fals
113113

114114
const baseUserRepository = new BaseUserRepository()
115115
if (requesterOrgUUID) {
116-
const user = isRegistry ? await baseUserRepository.findOneByUsernameAndOrgUUID(requesterUsername, requesterOrgUUID) : await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterOrgUUID)
116+
const user = isRegistry ? await baseUserRepository.findOneByUserNameAndOrgUUID(requesterUsername, requesterOrgUUID) : await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterOrgUUID)
117117

118118
if (user) {
119119
if (isRegistry) {
@@ -135,7 +135,7 @@ async function isAdminUUID (requesterUsername, requesterOrgUUID, isRegistry = fa
135135
const baseOrgRepository = new BaseOrgRepository()
136136
if (requesterOrgUUID) {
137137
const orgObject = await baseOrgRepository.findOneByUUID(requesterOrgUUID, options)
138-
const user = isRegistry ? await baseUserRepository.findOneByUsernameAndOrgUUID(requesterUsername, requesterOrgUUID) : await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterOrgUUID)
138+
const user = isRegistry ? await baseUserRepository.findOneByUserNameAndOrgUUID(requesterUsername, requesterOrgUUID) : await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterOrgUUID)
139139

140140
if (user && orgObject) {
141141
if (isRegistry) {

0 commit comments

Comments
 (0)