|
| 1 | +const argon2 = require('argon2') |
1 | 2 | const uuid = require('uuid') |
2 | 3 | const logger = require('../../middleware/logger') |
3 | 4 | const { getConstants } = require('../../constants') |
4 | 5 | const RegistryOrg = require('../../model/registry-org') |
5 | 6 | const RegistryUser = require('../../model/registry-user') |
6 | 7 | const errors = require('./error') |
| 8 | +const cryptoRandomString = require('crypto-random-string') |
7 | 9 | const error = new errors.RegistryOrgControllerError() |
8 | 10 | const validateUUID = require('uuid').validate |
9 | 11 |
|
@@ -202,7 +204,6 @@ async function updateOrg (req, res, next) { |
202 | 204 | const shortName = req.ctx.params.shortname |
203 | 205 | const userRepo = req.ctx.repositories.getRegistryUserRepository() |
204 | 206 | const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository() |
205 | | - // const shortName = req.ctx.params.shortname |
206 | 207 |
|
207 | 208 | const org = await registryOrgRepo.findOneByShortName(shortName) |
208 | 209 | if (!org) { |
@@ -380,8 +381,131 @@ async function getUsers (req, res, next) { |
380 | 381 | } |
381 | 382 | } |
382 | 383 |
|
383 | | -function createUserByOrg (req, res, next) { |
384 | | - console.log('HERE') |
| 384 | +async function createUserByOrg (req, res, next) { |
| 385 | + try { |
| 386 | + const requesterUsername = req.ctx.user |
| 387 | + const requesterShortName = req.ctx.org |
| 388 | + const shortName = req.ctx.params.shortname |
| 389 | + |
| 390 | + const registryUserRepo = req.ctx.repositories.getRegistryUserRepository() |
| 391 | + const registryOrgRepo = req.ctx.repositories.getRegistryOrgRepository() |
| 392 | + const orgUUID = await registryOrgRepo.getOrgUUID(shortName) |
| 393 | + const requesterOrgUUID = await registryOrgRepo.getOrgUUID(requesterShortName) |
| 394 | + const body = req.ctx.body |
| 395 | + |
| 396 | + const isSecretariat = await registryOrgRepo.isSecretariat(requesterShortName) |
| 397 | + const isAdmin = await registryUserRepo.isAdmin(requesterUsername, requesterShortName) |
| 398 | + |
| 399 | + if (!isSecretariat && !isAdmin) { // may be redundant after validation check is implemented |
| 400 | + return res.status(403).json(error.notOrgAdminOrSecretariat()) // User must be secretariat or an admin |
| 401 | + } |
| 402 | + if (!orgUUID) { |
| 403 | + return res.status(404).json(error.orgDnePathParam(shortName)) // Org must exist |
| 404 | + } |
| 405 | + if (!isSecretariat) { // Admins can only create user within the same org |
| 406 | + if (orgUUID !== requesterOrgUUID) { |
| 407 | + return res.status(403).json(error.notOrgAdminOrSecretariat()) // The Admin user must belong to the new user's organization |
| 408 | + } |
| 409 | + } |
| 410 | + |
| 411 | + const username = body.user_id || body.username |
| 412 | + if (!username) { |
| 413 | + return res.status(400).json({ message: 'user_id is required' }) |
| 414 | + } |
| 415 | + const existingUser = await registryUserRepo.findOneByUserNameAndOrgUUID(username, orgUUID) |
| 416 | + if (existingUser) { |
| 417 | + return res.status(400).json(error.userExists(username)) |
| 418 | + } |
| 419 | + |
| 420 | + const bodyKeys = Object.keys(body).map(k => k.toLowerCase()) |
| 421 | + if (bodyKeys.includes('uuid')) { |
| 422 | + return res.status(400).json(error.uuidProvided('user')) |
| 423 | + } |
| 424 | + |
| 425 | + // Creating a new user under specific org |
| 426 | + const newUser = new RegistryUser() |
| 427 | + bodyKeys.forEach(k => { |
| 428 | + if (k === 'user_id' || k === 'username') { |
| 429 | + newUser.user_id = body[k] |
| 430 | + } else if (k === 'name') { |
| 431 | + newUser.name = { |
| 432 | + first: '', |
| 433 | + last: '', |
| 434 | + middle: '', |
| 435 | + suffix: '', |
| 436 | + ...body.name |
| 437 | + } |
| 438 | + } else if (k === 'org_affiliations') { |
| 439 | + newUser.org_affiliations = body[k].map(item => { |
| 440 | + const { |
| 441 | + orgId = '', |
| 442 | + email = '', |
| 443 | + phone = '', |
| 444 | + ...rest |
| 445 | + } = item |
| 446 | + |
| 447 | + return { |
| 448 | + org_id: orgId, |
| 449 | + email, |
| 450 | + phone, |
| 451 | + ...rest |
| 452 | + } |
| 453 | + }) |
| 454 | + } else if (k === 'cve_program_org_membership') { |
| 455 | + newUser.cve_program_org_membership = body[k].map(item => { |
| 456 | + const { |
| 457 | + programOrg = '', |
| 458 | + roles = [], |
| 459 | + |
| 460 | + status = false, |
| 461 | + ...rest |
| 462 | + } = item |
| 463 | + |
| 464 | + return { |
| 465 | + program_org: programOrg, |
| 466 | + roles, |
| 467 | + status, |
| 468 | + ...rest |
| 469 | + } |
| 470 | + }) |
| 471 | + } |
| 472 | + }) |
| 473 | + |
| 474 | + newUser.UUID = uuid.v4() |
| 475 | + |
| 476 | + const randomKey = cryptoRandomString({ length: getConstants().CRYPTO_RANDOM_STRING_LENGTH }) |
| 477 | + newUser.secret = await argon2.hash(randomKey) |
| 478 | + newUser.last_active = null |
| 479 | + newUser.deactivation_date = null |
| 480 | + |
| 481 | + await registryUserRepo.updateByUserNameAndOrgUUID(newUser.user_id, orgUUID, newUser, { upsert: true }) |
| 482 | + await registryUserRepo.addOrgToUserAffiliation(newUser.UUID, orgUUID) |
| 483 | + await registryOrgRepo.addUserToOrgList(orgUUID, newUser.UUID, body.authority?.active_roles ? [...new Set(body.authority.active_roles)].includes('ADMIN') : false, { upsert: true }) |
| 484 | + |
| 485 | + const agt = setAggregateUserObj({ UUID: newUser.UUID }) |
| 486 | + let result = await registryUserRepo.aggregate(agt) |
| 487 | + result = result.length > 0 ? result[0] : null |
| 488 | + |
| 489 | + const payload = { |
| 490 | + action: 'create_registry_user', |
| 491 | + change: result.user_id + ' was successfully created.', |
| 492 | + req_UUID: req.ctx.uuid, |
| 493 | + org_UUID: orgUUID, |
| 494 | + user: result |
| 495 | + } |
| 496 | + payload.user_UUID = await registryUserRepo.getUserUUID(req.ctx.user, orgUUID) |
| 497 | + logger.info(JSON.stringify(payload)) |
| 498 | + |
| 499 | + result.secret = randomKey |
| 500 | + const responseMessage = { |
| 501 | + message: result.user_id + ' was successfully created.', |
| 502 | + created: result |
| 503 | + } |
| 504 | + |
| 505 | + return res.status(200).json(responseMessage) |
| 506 | + } catch (err) { |
| 507 | + next(err) |
| 508 | + } |
385 | 509 | } |
386 | 510 |
|
387 | 511 | function setAggregateUserObj (query) { |
|
0 commit comments