Skip to content

Commit 69bc7a4

Browse files
committed
Get secret is now backwards compatible.
1 parent b9454c0 commit 69bc7a4

7 files changed

Lines changed: 103 additions & 48 deletions

File tree

src/controller/org.controller/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,7 @@ router.get('/org/:shortname/user/:username',
620620
}
621621
*/
622622
mw.validateUser,
623+
param(['registry']).optional().isBoolean(),
623624
param(['shortname']).isString().trim().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
624625
param(['username']).isString().trim().notEmpty().custom(isValidUsername),
625626
parseError,
@@ -801,6 +802,7 @@ router.put('/org/:shortname/user/:username/reset_secret',
801802
*/
802803
mw.validateUser,
803804
mw.onlyOrgWithPartnerRole,
805+
param(['registry']).optional().isBoolean(),
804806
param(['shortname']).isString().trim().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
805807
param(['username']).isString().trim().notEmpty().custom(isValidUsername),
806808
parseError,

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

Lines changed: 70 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -170,10 +170,12 @@ async function getUsers (req, res, next) {
170170
**/
171171
async function getUser (req, res, next) {
172172
try {
173+
const isRegistry = req.query.registry === 'true'
173174
const shortName = req.ctx.org
174175
const username = req.ctx.params.username
175176
const orgShortName = req.ctx.params.shortname
176-
const orgRepo = req.ctx.repositories.getOrgRepository()
177+
178+
const orgRepo = isRegistry ? req.ctx.repositories.getRegistryOrgRepository() : req.ctx.repositories.getOrgRepository()
177179
const isSecretariat = await orgRepo.isSecretariat(shortName)
178180

179181
if (orgShortName !== shortName && !isSecretariat) {
@@ -187,8 +189,8 @@ async function getUser (req, res, next) {
187189
return res.status(404).json(error.orgDnePathParam(orgShortName))
188190
}
189191

190-
const userRepo = req.ctx.repositories.getUserRepository()
191-
const agt = setAggregateUserObj({ username: username, org_UUID: orgUUID })
192+
const userRepo = isRegistry ? req.ctx.repositories.getRegistryUserRepository() : req.ctx.repositories.getUserRepository()
193+
const agt = isRegistry ? setAggregateRegistryUserObj({ user_id: username, 'cve_program_org_membership.program_org': orgUUID }) : setAggregateUserObj({ username: username, org_UUID: orgUUID })
192194
let result = await userRepo.aggregate(agt)
193195
result = result.length > 0 ? result[0] : null
194196

@@ -1016,47 +1018,84 @@ async function updateUser (req, res, next) {
10161018

10171019
// Called by PUT /org/{shortname}/user/{username}/reset_secret
10181020
async function resetSecret (req, res, next) {
1021+
const session = await mongoose.startSession()
1022+
session.startTransaction()
10191023
try {
1024+
let randomKey
1025+
10201026
const requesterShortName = req.ctx.org
10211027
const requesterUsername = req.ctx.user
10221028
const username = req.ctx.params.username
10231029
const orgShortName = req.ctx.params.shortname
1030+
10241031
const userRepo = req.ctx.repositories.getUserRepository()
10251032
const orgRepo = req.ctx.repositories.getOrgRepository()
1026-
const isSecretariat = await orgRepo.isSecretariat(requesterShortName)
1027-
const orgUUID = await orgRepo.getOrgUUID(orgShortName) // userUUID may be null if user does not exist
1028-
if (!orgUUID) {
1029-
logger.info({ uuid: req.ctx.uuid, messsage: orgShortName + ' organization does not exist.' })
1030-
return res.status(404).json(error.orgDnePathParam(orgShortName))
1031-
}
10321033

1033-
if (orgShortName !== requesterShortName && !isSecretariat) {
1034-
logger.info({ uuid: req.ctx.uuid, message: orgShortName + ' organization can only be viewed by the users of the same organization or the Secretariat.' })
1035-
return res.status(403).json(error.notSameOrgOrSecretariat())
1036-
}
1034+
const userRegistryRepo = req.ctx.repositories.getRegistryUserRepository()
1035+
const orgRegistryRepo = req.ctx.repositories.getRegistryOrgRepository()
10371036

1038-
const oldUser = await userRepo.findOneByUserNameAndOrgUUID(username, orgUUID)
1039-
if (!oldUser) {
1040-
logger.info({ uuid: req.ctx.uuid, messsage: username + ' user does not exist.' })
1041-
return res.status(404).json(error.userDne(username))
1042-
}
1037+
try {
1038+
const isSecretariatLeg = await orgRepo.isSecretariat(requesterShortName, { session })
1039+
const isSecretariatReg = await orgRegistryRepo.isSecretariat(requesterShortName, { session })
1040+
const isSecretariat = isSecretariatLeg && isSecretariatReg
10431041

1044-
const isAdmin = await userRepo.isAdmin(requesterUsername, requesterShortName)
1045-
// check if the user is not the requester or if the requester is not a secretariat
1046-
if ((orgShortName !== requesterShortName || username !== requesterUsername) && !isSecretariat) {
1042+
const orgUUID = await orgRepo.getOrgUUID(orgShortName, { session }) // userUUID may be null if user does not exist
1043+
const orgRegUUID = await orgRegistryRepo.getOrgUUID(orgShortName, { session })
1044+
1045+
// check if orgUUID and orgRegUUID are the same
1046+
if (orgUUID.toString() !== orgRegUUID.toString()) {
1047+
logger.info({ uuid: req.ctx.uuid, message: 'The organization UUID and the organization registry UUID are not the same.' })
1048+
return res.status(500).json(error.internalServerError())
1049+
}
1050+
1051+
if (!orgUUID && !orgRegUUID) {
1052+
logger.info({ uuid: req.ctx.uuid, messsage: orgShortName + ' organization does not exist.' })
1053+
return res.status(404).json(error.orgDnePathParam(orgShortName))
1054+
}
1055+
1056+
if (orgShortName !== requesterShortName && !isSecretariat) {
1057+
logger.info({ uuid: req.ctx.uuid, message: orgShortName + ' organization can only be viewed by the users of the same organization or the Secretariat.' })
1058+
return res.status(403).json(error.notSameOrgOrSecretariat())
1059+
}
1060+
1061+
const oldUser = await userRepo.findOneByUserNameAndOrgUUID(username, orgUUID, null, { session })
1062+
const oldUserRegistry = await userRegistryRepo.findOneByUserNameAndOrgUUID(username, orgRegUUID)
1063+
1064+
if (!oldUser && !oldUserRegistry) {
1065+
logger.info({ uuid: req.ctx.uuid, messsage: username + ' user does not exist.' })
1066+
return res.status(404).json(error.userDne(username))
1067+
}
1068+
1069+
const isLegAdmin = await userRepo.isAdmin(requesterUsername, requesterShortName, { session })
1070+
const isRegAdmin = await userRegistryRepo.isAdmin(requesterUsername, orgRegUUID, { session })
1071+
const isAdmin = isLegAdmin && isRegAdmin
1072+
1073+
// check if the user is not the requester or if the requester is not a secretariat
1074+
if ((orgShortName !== requesterShortName || username !== requesterUsername) && !isSecretariat) {
10471075
// check if the requester is not and admin; if admin, the requester must be from the same org as the user
1048-
if (!isAdmin || (isAdmin && orgShortName !== requesterShortName)) {
1049-
logger.info({ uuid: req.ctx.uuid, message: 'The api secret can only be reset by the Secretariat, an Org admin or if the requester is the user.' })
1050-
return res.status(403).json(error.notSameUserOrSecretariat())
1076+
if (!isAdmin || (isAdmin && orgShortName !== requesterShortName)) {
1077+
logger.info({ uuid: req.ctx.uuid, message: 'The api secret can only be reset by the Secretariat, an Org admin or if the requester is the user.' })
1078+
return res.status(403).json(error.notSameUserOrSecretariat())
1079+
}
10511080
}
1052-
}
10531081

1054-
const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
1055-
oldUser.secret = await argon2.hash(randomKey) // store in db
1056-
const user = await userRepo.updateByUserNameAndOrgUUID(oldUser.username, orgUUID, oldUser)
1057-
if (user.n === 0) {
1058-
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be updated because ' + username + ' does not exist for ' + orgShortName + ' organization.' })
1059-
return res.status(404).json(error.userDne(username))
1082+
randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
1083+
oldUser.secret = await argon2.hash(randomKey) // store in db
1084+
oldUserRegistry.secret = await argon2.hash(randomKey) // store in db
1085+
1086+
const user = await userRepo.updateByUserNameAndOrgUUID(oldUser.username, orgUUID, oldUser, { session })
1087+
const userReg = await userRegistryRepo.updateByUserNameAndOrgUUID(oldUserRegistry.user_id, orgRegUUID, oldUserRegistry, { session })
1088+
1089+
if (user.matchedCount === 0 || userReg.matchedCount === 0) {
1090+
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be updated because ' + username + ' does not exist for ' + orgShortName + ' organization.' })
1091+
return res.status(404).json(error.userDne(username))
1092+
}
1093+
await session.commitTransaction()
1094+
} catch (error) {
1095+
await session.abortTransaction()
1096+
throw error
1097+
} finally {
1098+
session.endSession()
10601099
}
10611100

10621101
logger.info({ uuid: req.ctx.uuid, message: `The API secret was successfully reset and sent to ${username}` })

src/middleware/middleware.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ async function validateUser (req, res, next) {
131131
// Check if user has active status organization's registry org membership list
132132
for (var organization of result.cve_program_org_membership) {
133133
if (organization.program_org === orgUUID) {
134-
if (organization.status === 'active') {
134+
if (organization.status === 'active' || organization.status === 'true') {
135135
activeInOrg = true
136136
}
137137
break

src/repositories/registryOrgRepository.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ class RegistryOrgRepository extends BaseRepository {
1717
return this.collection.findOne().byUUID(UUID)
1818
}
1919

20-
async getOrgUUID (shortName) {
21-
return utils.getOrgUUID(shortName, true) // use registryOrgRepository to find org UUID
20+
async getOrgUUID (shortName, options = {}) {
21+
return utils.getOrgUUID(shortName, true, options) // use registryOrgRepository to find org UUID
2222
}
2323

2424
async getAllOrgs () {

src/repositories/registryUserRepository.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,27 @@ class RegistryUserRepository extends BaseRepository {
1919
return this.collection.find()
2020
}
2121

22-
async isSecretariat (org) {
23-
return utils.isSecretariat(org, true)
22+
async isSecretariat (org, options = {}) {
23+
return utils.isSecretariat(org, true, options)
24+
}
25+
26+
async isAdmin (username, orgShortname, options = {}) {
27+
return utils.isAdmin(username, orgShortname, true, options)
2428
}
2529

2630
async updateByUUID (uuid, user, options = {}) {
2731
return this.collection.findOneAndUpdate().byUUID(uuid).updateOne(user).setOptions(options)
2832
}
2933

30-
async findOneByUserNameAndOrgUUID (userName, orgUUID) {
31-
return this.collection.findOne().byUserIdAndOrgUUID(userName, orgUUID)
34+
async findOneByUserNameAndOrgUUID (userName, orgUUID, projection = null, options = {}) {
35+
const query = { user_id: userName, 'org_affiliations.org_id': orgUUID }
36+
return this.collection.findOne(query, projection, options)
37+
}
38+
39+
async updateByUserNameAndOrgUUID (userName, orgUUID, user, options = {}) {
40+
const filter = { user_id: userName, 'org_affiliations.org_id': orgUUID }
41+
const updatePayload = { $set: user }
42+
return this.collection.findOneAndUpdate(filter, updatePayload, options)
3243
}
3344

3445
async deleteByUUID (uuid) {

src/repositories/userRepository.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ class UserRepository extends BaseRepository {
1111
return utils.getUserUUID(userName, orgUUID, options)
1212
}
1313

14-
async isAdmin (username, shortname) {
15-
return utils.isAdmin(username, shortname)
14+
async isAdmin (username, shortname, options = {}) {
15+
return utils.isAdmin(username, shortname, false, options)
1616
}
1717

1818
async isAdminUUID (username, orgUUID) {
@@ -28,11 +28,14 @@ class UserRepository extends BaseRepository {
2828
}
2929

3030
async findOneByUserNameAndOrgUUID (userName, orgUUID, projection = null, options = {}) {
31-
return this.collection.findOne().byUserNameAndOrgUUID(userName, orgUUID)
31+
const query = { username: userName, org_UUID: orgUUID }
32+
return this.collection.findOne(query, projection, options)
3233
}
3334

3435
async updateByUserNameAndOrgUUID (username, orgUUID, user, options = {}) {
35-
return this.collection.findOneAndUpdate().byUserNameAndOrgUUID(username, orgUUID).updateOne(user).setOptions(options)
36+
const filter = { username: username, org_UUID: orgUUID }
37+
const updatePayload = { $set: user }
38+
return this.collection.findOneAndUpdate(filter, updatePayload, options)
3639
}
3740

3841
async getAllUsers () {

src/utils/utils.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,17 +51,17 @@ async function getUserUUID (userIdentifier, orgUUID, useRegistry = false, option
5151
return userDocument ? userDocument.UUID : null
5252
}
5353

54-
async function isSecretariat (shortName, useRegistry = false) {
54+
async function isSecretariat (shortName, useRegistry = false, options = {}) {
5555
let result = false
5656
let orgUUID = null
5757
let secretariats = []
5858

5959
const CONSTANTS = getConstants()
6060
if (useRegistry) {
61-
orgUUID = await getOrgUUID(shortName, useRegistry) // may be null if org does not exists
61+
orgUUID = await getOrgUUID(shortName, useRegistry, options) // may be null if org does not exists
6262
secretariats = await RegistryOrg.find({ 'authority.active_roles': { $in: [CONSTANTS.AUTH_ROLE_ENUM.SECRETARIAT] } })
6363
} else {
64-
orgUUID = await getOrgUUID(shortName) // may be null if org does not exists
64+
orgUUID = await getOrgUUID(shortName, false, options) // may be null if org does not exists
6565
secretariats = await Org.find({ 'authority.active_roles': { $in: [CONSTANTS.AUTH_ROLE_ENUM.SECRETARIAT] } })
6666
}
6767

@@ -109,13 +109,13 @@ async function isBulkDownload (shortName) {
109109
return result // org does not have bulk download as a role
110110
}
111111

112-
async function isAdmin (requesterUsername, requesterShortName) {
112+
async function isAdmin (requesterUsername, requesterShortName, isRegistry = false, options = {}) {
113113
let result = false
114114
const CONSTANTS = getConstants()
115-
const requesterOrgUUID = await getOrgUUID(requesterShortName) // may be null if org does not exists
115+
const requesterOrgUUID = await getOrgUUID(requesterShortName, isRegistry, options) // may be null if org does not exists
116116

117117
if (requesterOrgUUID) {
118-
const user = await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterOrgUUID)
118+
const user = isRegistry ? await RegistryUser.findOne().byUserNameAndOrgUUID(requesterUsername, requesterShortName) : await User.findOne().byUserNameAndOrgUUID(requesterUsername, requesterShortName)
119119

120120
if (user) {
121121
result = user.authority.active_roles.includes(CONSTANTS.USER_ROLE_ENUM.ADMIN)

0 commit comments

Comments
 (0)