Skip to content

Commit 70294e3

Browse files
committed
implement new post request: create user for specific org
1 parent 49d5566 commit 70294e3

3 files changed

Lines changed: 109 additions & 7 deletions

File tree

src/controller/registry-org.controller/index.js

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,32 @@ router.post('/registryOrg/:shortname/user',
541541
// // mw.onlyOrgWithPartnerRole,
542542
mw.onlySecretariat,
543543
param(['shortname']).isString().trim().notEmpty().isLength({ min: CONSTANTS.MIN_SHORTNAME_LENGTH, max: CONSTANTS.MAX_SHORTNAME_LENGTH }),
544-
body(['cve_program_org_membership'])
544+
body(['cve_program_org_membership']).optional().custom(isFlatStringArray), // TO-DO: implement custom(mw.isCveProgramOrgMembershipObject),
545+
body(
546+
[
547+
'user_id',
548+
'name.first',
549+
'name.last'
550+
])
551+
.isString(),
552+
body(
553+
[
554+
'name.middle',
555+
'name.suffix',
556+
'contact_info.phone',
557+
'contact_info.email' // // TO-DO: this needs to be required only when contact-info is present?
558+
])
559+
.default('')
560+
.isString(),
561+
body(['org_affiliations'])
545562
.optional()
546-
.custom(mw.isCveProgramOrgMembershipObject),
563+
.custom(isFlatStringArray)
564+
.customSanitizer(toUpperCaseArray),
565+
body(['authority.active_roles'])
566+
.optional()
567+
.custom(isFlatStringArray)
568+
.customSanitizer(toUpperCaseArray)
569+
.custom(isOrgRole), // TO-DO: this needs to be required only when authority is present?
547570
parseError,
548571
parsePostParams,
549572
controller.USER_CREATE_SINGLE)

src/controller/registry-org.controller/registry-org.controller.js

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
const argon2 = require('argon2')
12
const uuid = require('uuid')
23
const logger = require('../../middleware/logger')
34
const { getConstants } = require('../../constants')
45
const RegistryOrg = require('../../model/registry-org')
56
const RegistryUser = require('../../model/registry-user')
67
const errors = require('./error')
8+
const cryptoRandomString = require('crypto-random-string')
79
const error = new errors.RegistryOrgControllerError()
810
const validateUUID = require('uuid').validate
911

@@ -98,7 +100,7 @@ async function createOrg (req, res, next) {
98100
} else if (k === 'short_name') {
99101
newOrg.short_name = body[k]
100102
} else if (k === 'aliases') {
101-
newOrg.aliases = [...new Set(body[k].active_roles)]
103+
newOrg.aliases = [...new Set(body[k])]
102104
} else if (k === 'cve_program_org_function') {
103105
newOrg.cve_program_org_function = body[k]
104106
} else if (k === 'authority') {
@@ -197,7 +199,6 @@ async function updateOrg (req, res, next) {
197199
const shortName = req.ctx.params.shortname
198200
const userRepo = req.ctx.repositories.getRegistryUserRepository()
199201
const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository()
200-
// const shortName = req.ctx.params.shortname
201202

202203
const org = await registryOrgRepo.findOneByShortName(shortName)
203204
if (!org) {
@@ -375,8 +376,86 @@ async function getUsers (req, res, next) {
375376
}
376377
}
377378

378-
function createUserByOrg (req, res, next) {
379-
console.log('HERE')
379+
async function createUserByOrg (req, res, next) {
380+
try {
381+
const requesterUsername = req.ctx.user
382+
const requesterShortName = req.ctx.org
383+
const shortName = req.ctx.params.shortname
384+
385+
const registryUserRepo = req.ctx.repositories.getRegistryUserRepository()
386+
const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository()
387+
const orgUUID = await registryOrgRepo.getOrgUUID(shortName)
388+
const requesterOrgUUID = await registryOrgRepo.getOrgUUID(requesterShortName)
389+
const body = req.ctx.body
390+
391+
const isSecretariat = await registryOrgRepo.isSecretariat(shortName)
392+
const isAdmin = await registryUserRepo.isAdmin(requesterUsername, requesterShortName)
393+
394+
if (!isSecretariat && !isAdmin) { // may be redundant after validation check is implemented
395+
return res.status(403).json(error.notOrgAdminOrSecretariat()) // User must be secretariat or an admin
396+
}
397+
if (!orgUUID) {
398+
return res.status(404).json(error.orgDnePathParam(shortName)) // Org must exist
399+
}
400+
if (!isSecretariat) { // Admins can only create user within the same org
401+
if (orgUUID !== requesterOrgUUID) {
402+
return res.status(403).json(error.notOrgAdminOrSecretariat()) // The Admin user must belong to the new user's organization
403+
}
404+
}
405+
406+
// Creating a new user under specific org
407+
const newUser = new RegistryUser()
408+
Object.keys(body).map(k => k.toLowerCase()).forEach(k => {
409+
if (k === 'user_id' || k === 'username') {
410+
newUser.user_id = body[k]
411+
} else if (k === 'name') {
412+
newUser.name = {
413+
first: '',
414+
last: '',
415+
middle: '',
416+
suffix: '',
417+
...body.name
418+
}
419+
} else if (k === 'org_affiliations') {
420+
// TODO: dedupe
421+
} else if (k === 'cve_program_org_membership') {
422+
// TODO: dedupe
423+
} else if (k === 'uuid') {
424+
return res.status(400).json(error.uuidProvided('user'))
425+
}
426+
})
427+
428+
newUser.UUID = uuid.v4()
429+
const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH })
430+
newUser.secret = await argon2.hash(randomKey)
431+
newUser.last_active = null
432+
newUser.deactivation_date = null
433+
434+
await registryUserRepo.updateByUUID(newUser.UUID, newUser, { upsert: true })
435+
const agt = setAggregateUserObj({ UUID: newUser.UUID })
436+
let result = await registryUserRepo.aggregate(agt)
437+
result = result.length > 0 ? result[0] : null
438+
439+
const payload = {
440+
action: 'create_registry_user',
441+
change: result.user_id + ' was successfully created.',
442+
req_UUID: req.ctx.uuid,
443+
org_UUID: await registryOrgRepo.getOrgUUID(req.ctx.org),
444+
user: result
445+
}
446+
payload.user_UUID = await registryUserRepo.getUserUUID(req.ctx.user, payload.org_UUID)
447+
logger.info(JSON.stringify(payload))
448+
449+
result.secret = randomKey
450+
const responseMessage = {
451+
message: result.user_id + ' was successfully created.',
452+
created: result
453+
}
454+
455+
return res.status(200).json(responseMessage)
456+
} catch (err) {
457+
next(err)
458+
}
380459
}
381460

382461
function setAggregateUserObj (query) {

src/controller/registry-org.controller/registry-org.middleware.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const error = new errors.RegistryOrgControllerError()
66

77
function parsePostParams (req, res, next) {
88
utils.reqCtxMapping(req, 'body', [])
9-
utils.reqCtxMapping(req, 'params', ['identifier, shortname'])
9+
utils.reqCtxMapping(req, 'params', ['identifier', 'shortname'])
1010
utils.reqCtxMapping(req, 'query', [
1111
'long_name', 'short_name', 'aliases',
1212
'cve_program_org_function', 'authority.active_roles',

0 commit comments

Comments
 (0)