Skip to content

Commit a4e8099

Browse files
committed
updating createUser controller/baseUser repository
1 parent c2c9aab commit a4e8099

File tree

2 files changed

+305
-147
lines changed

2 files changed

+305
-147
lines changed

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

Lines changed: 212 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -557,181 +557,246 @@ async function updateOrg (req, res, next) {
557557
}
558558
}
559559

560+
// /**
561+
// * Creates a user only if the org exists and
562+
// * the user does not exist for the specified shortname and username
563+
// * Called by POST /api/org/{shortname}/user
564+
// **/
565+
// async function createUser (req, res, next) {
566+
// const session = await mongoose.startSession() // Start a Mongoose session for transaction
567+
// const isRegistry = req.query.registry === 'true'
568+
569+
// try {
570+
// session.startTransaction()
571+
// const orgShortName = req.ctx.params.shortname
572+
// const requesterUsername = req.ctx.user
573+
// const requesterShortName = req.ctx.org
574+
575+
// const orgRepo = req.ctx.repositories.getOrgRepository()
576+
// const userRepo = req.ctx.repositories.getUserRepository()
577+
578+
// const orgRegistryRepo = req.ctx.repositories.getRegistryOrgRepository()
579+
// const userRegistryRepo = req.ctx.repositories.getRegistryUserRepository()
580+
581+
// const newUser = new User()
582+
// const newRegistryUser = new RegistryUser()
583+
584+
// const orgUUID = await orgRepo.getOrgUUID(orgShortName, { session })
585+
// const orgRegUUID = await orgRegistryRepo.getOrgUUID(orgShortName, { session })
586+
587+
// if (!orgUUID && !orgRegUUID) { // the org can only be non-existent if the requestor is the Secretariat
588+
// logger.info({ uuid: req.ctx.uuid, message: 'The user could not be created because ' + orgShortName + ' organization does not exist.' })
589+
// return res.status(404).json(error.orgDnePathParam(orgShortName))
590+
// }
591+
592+
// const users = await userRepo.findUsersByOrgUUID(orgUUID, { session })
593+
// const regUsers = await userRegistryRepo.findUsersByOrgUUID(orgUUID, { session })
594+
595+
// if (users && regUsers && users !== regUsers) {
596+
// await session.abortTransaction()
597+
// return res.status(500).json({ message: 'Data inconsistency' })
598+
// }
599+
600+
// if (users >= 100) {
601+
// await session.abortTransaction()
602+
// return res.status(400).json(error.userLimitReached())
603+
// }
604+
605+
// const body = req.ctx.body
606+
// const keys = Object.keys(body)
607+
608+
// newRegistryUser.cve_program_org_membership = [{
609+
// program_org: orgUUID,
610+
// roles: [],
611+
// status: 'active'
612+
// }]
613+
614+
// for (const keyRaw of keys) {
615+
// const key = keyRaw.toLowerCase()
616+
617+
// if (key === 'uuid') {
618+
// await session.abortTransaction()
619+
// return res.status(400).json(error.uuidProvided('user'))
620+
// }
621+
622+
// if (key === 'org_uuid') {
623+
// await session.abortTransaction()
624+
// return res.status(400).json(error.uuidProvided('org'))
625+
// }
626+
627+
// const handlers = {
628+
// username: () => {
629+
// newUser.username = body.username
630+
// newRegistryUser.user_id = body.username
631+
// },
632+
// user_id: () => {
633+
// newUser.username = body.user_id
634+
// newRegistryUser.user_id = body.user_id
635+
// },
636+
// authority: () => {
637+
// if (body.authority?.active_roles) {
638+
// newUser.authority.active_roles = [...new Set(body.authority.active_roles)]
639+
// newRegistryUser.cve_program_org_membership = [{ program_org: orgUUID, status: 'active', roles: [...new Set(body.authority.active_roles)] }]
640+
// }
641+
// },
642+
// name: () => {
643+
// const name = body.name || {}
644+
// if (name.first) {
645+
// newUser.name.first = name.first
646+
// newRegistryUser.name.first = name.first
647+
// }
648+
// if (name.last) {
649+
// newUser.name.last = name.last
650+
// newRegistryUser.name.last = name.last
651+
// }
652+
// if (name.middle) {
653+
// newUser.name.middle = name.middle
654+
// newRegistryUser.name.middle = name.middle
655+
// }
656+
// if (name.suffix) {
657+
// newUser.name.suffix = name.suffix
658+
// newRegistryUser.name.suffix = name.suffix
659+
// }
660+
// }
661+
// }
662+
663+
// if (handlers[key]) {
664+
// handlers[key]() // execute the appropriate handler
665+
// }
666+
// }
667+
668+
// // This UUID will match across collections
669+
// const requesterOrgUUID = await orgRepo.getOrgUUID(requesterShortName, { session })
670+
671+
// // Double check sec / admin
672+
// const isSecretariat = await orgRepo.isSecretariatUUID(requesterOrgUUID, { session }) && await orgRegistryRepo.isSecretariat(requesterShortName, { session })
673+
// const isAdmin = await userRepo.isAdminUUID(requesterUsername, requesterOrgUUID, { session }) && await userRegistryRepo.isAdminUUID(requesterUsername, requesterOrgUUID, { session })
674+
// // check if user is only an Admin (not Secretatiat) and the user does not belong to the same organization as the new user
675+
// if (!isSecretariat && isAdmin) {
676+
// if (requesterOrgUUID !== orgUUID) {
677+
// await session.abortTransaction()
678+
// return res.status(403).json(error.notOrgAdminOrSecretariat()) // The Admin user must belong to the new user's organization
679+
// }
680+
// }
681+
682+
// const sharedKey = uuid.v4()
683+
// newUser.org_UUID = orgUUID
684+
// newUser.UUID = sharedKey
685+
// newRegistryUser.UUID = sharedKey
686+
// newUser.active = true
687+
// const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
688+
// const secret = await argon2.hash(randomKey)
689+
// newUser.secret = secret
690+
// newRegistryUser.secret = secret
691+
692+
// const resultLeg = await userRepo.findOneByUserNameAndOrgUUID(newUser.username, newUser.org_UUID, null, { session }) // Find user in MongoDB
693+
// const resultReg = await userRegistryRepo.findOneByUserNameAndOrgUUID(newRegistryUser.user_id, orgUUID, null, { session })
694+
// if (resultLeg || resultReg) {
695+
// logger.info({ uuid: req.ctx.uuid, message: newUser.username + ' was not created because it already exists.' })
696+
// await session.abortTransaction()
697+
// return res.status(400).json(error.userExists(newUser.username))
698+
// }
699+
700+
// // Parsing all user name fields
701+
// newUser.name = parseUserName(newUser)
702+
// newRegistryUser.name = parseUserName(newRegistryUser)
703+
704+
// await userRepo.updateByUserNameAndOrgUUID(newUser.username, newUser.org_UUID, newUser, { upsert: true, session }) // Create user in MongoDB if it doesn't exist
705+
// await userRegistryRepo.updateByUserNameAndOrgUUID(newRegistryUser.user_id, orgUUID, newRegistryUser, { upsert: true, session })
706+
// await userRegistryRepo.addOrgToUserAffiliation(newUser.UUID, orgUUID, { session })
707+
// await orgRegistryRepo.addUserToOrgList(orgUUID, newRegistryUser.UUID, body.authority?.active_roles ? [...new Set(body.authority.active_roles)].includes('ADMIN') : false, { upsert: true, session })
708+
// const agt = isRegistry ? setAggregateRegistryUserObj({ 'cve_program_org_membership.program_org': orgUUID, user_id: newRegistryUser.user_id }) : setAggregateUserObj({ org_UUID: orgUUID, username: newUser.username })
709+
// let result = isRegistry ? await userRegistryRepo.aggregate(agt, { session }) : await userRepo.aggregate(agt, { session })
710+
// result = result.length > 0 ? result[0] : null
711+
712+
// const payloadUsername = isRegistry ? result.user_id : result.username
713+
714+
// const payload = {
715+
// action: 'create_user',
716+
// change: payloadUsername + ' was successfully created.',
717+
// req_UUID: req.ctx.uuid,
718+
// org_UUID: await orgRepo.getOrgUUID(req.ctx.org),
719+
// user: result
720+
// }
721+
// payload.user_UUID = isRegistry ? await userRegistryRepo.getUserUUID(req.ctx.user, payload.org_UUID, { session }) : await userRepo.getUserUUID(req.ctx.user, payload.org_UUID, { session })
722+
// logger.info(JSON.stringify(payload))
723+
724+
// result.secret = randomKey
725+
// const responseMessage = {
726+
// message: payloadUsername + ' was successfully created.',
727+
// created: result
728+
// }
729+
// await session.commitTransaction()
730+
// return res.status(200).json(responseMessage)
731+
// } catch (err) {
732+
// next(err)
733+
// } finally {
734+
// await session.endSession()
735+
// }
736+
// }
737+
560738
/**
561-
* Creates a user only if the org exists and
739+
* Creates a user only if the org exists and
562740
* the user does not exist for the specified shortname and username
563741
* Called by POST /api/org/{shortname}/user
564742
**/
565743
async function createUser (req, res, next) {
566-
const session = await mongoose.startSession() // Start a Mongoose session for transaction
567-
const isRegistry = req.query.registry === 'true'
568-
569744
try {
570-
session.startTransaction()
745+
const session = await mongoose.startSession()
746+
const body = req.ctx.body
747+
const repo = req.ctx.repositories.getBaseUserRepository()
571748
const orgShortName = req.ctx.params.shortname
572-
const requesterUsername = req.ctx.user
573-
const requesterShortName = req.ctx.org
749+
// const isRegistry = req.query.registry === 'true'
750+
let returnValue
574751

575-
const orgRepo = req.ctx.repositories.getOrgRepository()
576-
const userRepo = req.ctx.repositories.getUserRepository()
577-
578-
const orgRegistryRepo = req.ctx.repositories.getRegistryOrgRepository()
579-
const userRegistryRepo = req.ctx.repositories.getRegistryUserRepository()
580-
581-
const newUser = new User()
582-
const newRegistryUser = new RegistryUser()
583-
584-
const orgUUID = await orgRepo.getOrgUUID(orgShortName, { session })
585-
const orgRegUUID = await orgRegistryRepo.getOrgUUID(orgShortName, { session })
586-
587-
if (!orgUUID && !orgRegUUID) { // the org can only be non-existent if the requestor is the Secretariat
588-
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be created because ' + orgShortName + ' organization does not exist.' })
589-
return res.status(404).json(error.orgDnePathParam(orgShortName))
590-
}
591-
592-
const users = await userRepo.findUsersByOrgUUID(orgUUID, { session })
593-
const regUsers = await userRegistryRepo.findUsersByOrgUUID(orgUUID, { session })
594-
595-
if (users && regUsers && users !== regUsers) {
596-
await session.abortTransaction()
597-
return res.status(500).json({ message: 'Data inconsistency' })
598-
}
599-
600-
if (users >= 100) {
601-
await session.abortTransaction()
602-
return res.status(400).json(error.userLimitReached())
752+
// Do not allow the user to pass in a UUID
753+
if (body?.UUID ?? null) {
754+
return res.status(400).json(error.uuidProvided('user'))
603755
}
604756

605-
const body = req.ctx.body
606-
const keys = Object.keys(body)
607-
608-
newRegistryUser.cve_program_org_membership = [{
609-
program_org: orgUUID,
610-
roles: [],
611-
status: 'active'
612-
}]
613-
614-
for (const keyRaw of keys) {
615-
const key = keyRaw.toLowerCase()
757+
// Do not allow the user to pass in an org_UUID
758+
// if (body?.org_UUID ?? null) {
759+
// return res.status(400).json(error.uuidProvided('org'))
760+
// }
616761

617-
if (key === 'uuid') {
618-
await session.abortTransaction()
619-
return res.status(400).json(error.uuidProvided('user'))
620-
}
762+
try {
763+
session.startTransaction()
621764

622-
if (key === 'org_uuid') {
765+
// Ask repo if user already exists
766+
if (await repo.orgHasUser(orgShortName, body?.username, { session })) {
767+
logger.info({ uuid: req.ctx.uuid, message: `${body?.username} user was not created because it already exists.` })
623768
await session.abortTransaction()
624-
return res.status(400).json(error.uuidProvided('org'))
769+
return res.status(400).json(error.userExists(body?.username))
625770
}
626771

627-
const handlers = {
628-
username: () => {
629-
newUser.username = body.username
630-
newRegistryUser.user_id = body.username
631-
},
632-
user_id: () => {
633-
newUser.username = body.user_id
634-
newRegistryUser.user_id = body.user_id
635-
},
636-
authority: () => {
637-
if (body.authority?.active_roles) {
638-
newUser.authority.active_roles = [...new Set(body.authority.active_roles)]
639-
newRegistryUser.cve_program_org_membership = [{ program_org: orgUUID, status: 'active', roles: [...new Set(body.authority.active_roles)] }]
640-
}
641-
},
642-
name: () => {
643-
const name = body.name || {}
644-
if (name.first) {
645-
newUser.name.first = name.first
646-
newRegistryUser.name.first = name.first
647-
}
648-
if (name.last) {
649-
newUser.name.last = name.last
650-
newRegistryUser.name.last = name.last
651-
}
652-
if (name.middle) {
653-
newUser.name.middle = name.middle
654-
newRegistryUser.name.middle = name.middle
655-
}
656-
if (name.suffix) {
657-
newUser.name.suffix = name.suffix
658-
newRegistryUser.name.suffix = name.suffix
659-
}
660-
}
661-
}
772+
returnValue = await repo.createUser(orgShortName, body, { session, upsert: true }, true)
662773

663-
if (handlers[key]) {
664-
handlers[key]() // execute the appropriate handler
665-
}
666-
}
667-
668-
// This UUID will match across collections
669-
const requesterOrgUUID = await orgRepo.getOrgUUID(requesterShortName, { session })
670-
671-
// Double check sec / admin
672-
const isSecretariat = await orgRepo.isSecretariatUUID(requesterOrgUUID, { session }) && await orgRegistryRepo.isSecretariat(requesterShortName, { session })
673-
const isAdmin = await userRepo.isAdminUUID(requesterUsername, requesterOrgUUID, { session }) && await userRegistryRepo.isAdminUUID(requesterUsername, requesterOrgUUID, { session })
674-
// check if user is only an Admin (not Secretatiat) and the user does not belong to the same organization as the new user
675-
if (!isSecretariat && isAdmin) {
676-
if (requesterOrgUUID !== orgUUID) {
677-
await session.abortTransaction()
678-
return res.status(403).json(error.notOrgAdminOrSecretariat()) // The Admin user must belong to the new user's organization
679-
}
680-
}
681-
682-
const sharedKey = uuid.v4()
683-
newUser.org_UUID = orgUUID
684-
newUser.UUID = sharedKey
685-
newRegistryUser.UUID = sharedKey
686-
newUser.active = true
687-
const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
688-
const secret = await argon2.hash(randomKey)
689-
newUser.secret = secret
690-
newRegistryUser.secret = secret
691-
692-
const resultLeg = await userRepo.findOneByUserNameAndOrgUUID(newUser.username, newUser.org_UUID, null, { session }) // Find user in MongoDB
693-
const resultReg = await userRegistryRepo.findOneByUserNameAndOrgUUID(newRegistryUser.user_id, orgUUID, null, { session })
694-
if (resultLeg || resultReg) {
695-
logger.info({ uuid: req.ctx.uuid, message: newUser.username + ' was not created because it already exists.' })
774+
await session.commitTransaction()
775+
} catch (error) {
696776
await session.abortTransaction()
697-
return res.status(400).json(error.userExists(newUser.username))
777+
throw error
778+
} finally {
779+
await session.endSession()
698780
}
699781

700-
// Parsing all user name fields
701-
newUser.name = parseUserName(newUser)
702-
newRegistryUser.name = parseUserName(newRegistryUser)
703-
704-
await userRepo.updateByUserNameAndOrgUUID(newUser.username, newUser.org_UUID, newUser, { upsert: true, session }) // Create user in MongoDB if it doesn't exist
705-
await userRegistryRepo.updateByUserNameAndOrgUUID(newRegistryUser.user_id, orgUUID, newRegistryUser, { upsert: true, session })
706-
await userRegistryRepo.addOrgToUserAffiliation(newUser.UUID, orgUUID, { session })
707-
await orgRegistryRepo.addUserToOrgList(orgUUID, newRegistryUser.UUID, body.authority?.active_roles ? [...new Set(body.authority.active_roles)].includes('ADMIN') : false, { upsert: true, session })
708-
const agt = isRegistry ? setAggregateRegistryUserObj({ 'cve_program_org_membership.program_org': orgUUID, user_id: newRegistryUser.user_id }) : setAggregateUserObj({ org_UUID: orgUUID, username: newUser.username })
709-
let result = isRegistry ? await userRegistryRepo.aggregate(agt, { session }) : await userRepo.aggregate(agt, { session })
710-
result = result.length > 0 ? result[0] : null
711-
712-
const payloadUsername = isRegistry ? result.user_id : result.username
782+
const responseMessage = {
783+
message: `${body?.username} was successfully created.`,
784+
created: returnValue
785+
}
713786

714787
const payload = {
715788
action: 'create_user',
716-
change: payloadUsername + ' was successfully created.',
789+
change: `${body?.username} was successfully created.`,
717790
req_UUID: req.ctx.uuid,
718-
org_UUID: await orgRepo.getOrgUUID(req.ctx.org),
719-
user: result
791+
org_UUID: returnValue.org_UUID,
792+
user_UUID: returnValue.UUID,
793+
user: returnValue
720794
}
721-
payload.user_UUID = isRegistry ? await userRegistryRepo.getUserUUID(req.ctx.user, payload.org_UUID, { session }) : await userRepo.getUserUUID(req.ctx.user, payload.org_UUID, { session })
722-
logger.info(JSON.stringify(payload))
723795

724-
result.secret = randomKey
725-
const responseMessage = {
726-
message: payloadUsername + ' was successfully created.',
727-
created: result
728-
}
729-
await session.commitTransaction()
796+
logger.info(JSON.stringify(payload))
730797
return res.status(200).json(responseMessage)
731798
} catch (err) {
732799
next(err)
733-
} finally {
734-
await session.endSession()
735800
}
736801
}
737802

0 commit comments

Comments
 (0)