@@ -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 **/
565743async 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