Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions src/controller/format.constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const LEGACY_FORMAT = true
const REGISTRY_FORMAT = false

module.exports = {
LEGACY_FORMAT,
REGISTRY_FORMAT
}
98 changes: 47 additions & 51 deletions src/controller/org.controller/org.controller.js

Large diffs are not rendered by default.

19 changes: 10 additions & 9 deletions src/controller/registry.controller/org.registry.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const conversationErrors = require('../conversation.controller/error')
const convoError = new conversationErrors.ConversationControllerError()
const validateUUID = require('uuid').validate
const authContext = require('../../utils/authContext')
const { REGISTRY_FORMAT } = require('../format.constants')

function addUUIDsToSet (uuidSet, values) {
if (!Array.isArray(values)) return
Expand Down Expand Up @@ -128,7 +129,7 @@ async function getAllOrgs (req, res, next) {
options.page = req.ctx.query.page ? parseInt(req.ctx.query.page) : CONSTANTS.PAGINATOR_PAGE // if 'page' query parameter is not defined, set 'page' to the default page value

try {
returnValue = await repo.getAllOrgs({ ...options }, false, isSecretariat)
returnValue = await repo.getAllOrgs({ ...options }, REGISTRY_FORMAT, isSecretariat)
// fetch conversations
for (let i = 0; i < returnValue.organizations.length; i++) {
const conversation = await conversationRepo.getAllByTargetUUID(returnValue.organizations[i].UUID, isSecretariat)
Expand Down Expand Up @@ -181,7 +182,7 @@ async function getOrg (req, res, next) {
logger.info({ uuid: req.ctx.uuid, message: identifier + ' organization can only be viewed by the users of the same organization or the Secretariat.' })
return res.status(403).json(error.notSameOrgOrSecretariat())
}
returnValue = await repo.getOrg(identifier, identifierIsUUID, {}, false, isSecretariat)
returnValue = await repo.getOrg(identifier, identifierIsUUID, {}, REGISTRY_FORMAT, isSecretariat)

if (returnValue) {
let userRepo
Expand Down Expand Up @@ -306,7 +307,7 @@ async function createOrg (req, res, next) {
const userRepo = req.ctx.repositories.getBaseUserRepository()
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, repo, { session })
// Create the org – repo.createOrg will handle field mapping
createdOrg = await repo.createOrg(body, { session, upsert: true }, false, requestingUserUUID, isSecretariat)
createdOrg = await repo.createOrg(body, { session, upsert: true }, REGISTRY_FORMAT, requestingUserUUID, isSecretariat)

await session.commitTransaction()
} catch (createErr) {
Expand Down Expand Up @@ -549,7 +550,7 @@ async function updateOrg (req, res, next) {
// Update Org full will cause a write to the Conversations collection, to avoid a read-after-write issue, we need to get the previous conversation data first
const previousConversation = await conversationRepo.getAllByTargetUUID(await repo.getOrgUUID(shortName, { session }), isSecretariat, { session }) || []

updatedOrg = await repo.updateOrgFull(shortName, req.ctx.body, { session }, false, requestingUser.UUID, isAdmin, isSecretariat)
updatedOrg = await repo.updateOrgFull(shortName, req.ctx.body, { session }, REGISTRY_FORMAT, requestingUser.UUID, isAdmin, isSecretariat)
jointApprovalRequired = _.get(updatedOrg, 'joint_approval_required', false)
_.unset(updatedOrg, 'joint_approval_required')
// append previous conversations to any conversations that are in the org already
Expand Down Expand Up @@ -702,7 +703,7 @@ async function getUsers (req, res, next) {
}

// This should always return Registry typed
const payload = await userRepo.getAllUsersByOrgShortname(orgShortName, options, true)
const payload = await userRepo.getAllUsersByOrgShortname(orgShortName, options, REGISTRY_FORMAT)

// Hydrate the role field
const org = await orgRepo.findOneByShortName(orgShortName)
Expand Down Expand Up @@ -738,7 +739,7 @@ async function createUserByOrg (req, res, next) {
let returnValue

// Check to make sure Org Exists first
const orgUUID = await orgRepo.getOrgUUID(orgShortName, {}, false)
const orgUUID = await orgRepo.getOrgUUID(orgShortName, {}, REGISTRY_FORMAT)
if (!orgUUID) {
logger.info({ uuid: req.ctx.uuid, message: 'The user could not be created because ' + orgShortName + ' organization does not exist.' })
return res.status(404).json(error.orgDnePathParam(orgShortName))
Expand Down Expand Up @@ -769,7 +770,7 @@ async function createUserByOrg (req, res, next) {
}

// Ask repo if user already exists
if (await userRepo.orgHasUser(orgShortName, body?.username, { session }, true)) {
if (await userRepo.orgHasUser(orgShortName, body?.username, { session }, REGISTRY_FORMAT)) {
logger.info({ uuid: req.ctx.uuid, message: `${body?.username} user was not created because it already exists.` })
await session.abortTransaction()
return res.status(400).json(error.userExists(body?.username))
Expand All @@ -789,7 +790,7 @@ async function createUserByOrg (req, res, next) {
}

const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, { session })
returnValue = await userRepo.createUser(orgShortName, body, { session, upsert: true }, true, requestingUserUUID)
returnValue = await userRepo.createUser(orgShortName, body, { session, upsert: true }, REGISTRY_FORMAT, requestingUserUUID)
await session.commitTransaction()
} catch (error) {
await session.abortTransaction()
Expand Down Expand Up @@ -849,7 +850,7 @@ async function editConversationForOrg (req, res, next) {
const session = await mongoose.startSession({ causalConsistency: false })

try {
const orgUUID = await repo.getOrgUUID(orgShortName, {}, false)
const orgUUID = await repo.getOrgUUID(orgShortName, {}, REGISTRY_FORMAT)
if (!orgUUID) {
await session.endSession()
return res.status(404).json(error.orgDnePathParam(orgShortName))
Expand Down
69 changes: 35 additions & 34 deletions src/controller/registry.controller/user.registry.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const error = new errors.UserControllerError()
const validateUUID = require('uuid').validate
const _ = require('lodash')
const authContext = require('../../utils/authContext')
const { REGISTRY_FORMAT } = require('../format.constants')

const immutableUpdateFields = ['created', 'last_updated']

Expand Down Expand Up @@ -43,7 +44,7 @@ async function getAllUsers (req, res, next) {
options.sort = { short_name: 'asc' }
options.page = req.ctx.query.page ? parseInt(req.ctx.query.page) : CONSTANTS.PAGINATOR_PAGE // if 'page' query parameter is not defined, set 'page' to the default page value

const returnValue = await repo.getAllUsers(options)
const returnValue = await repo.getAllUsers(options, REGISTRY_FORMAT)
// Hydrate roles
const orgRepo = req.ctx.repositories.getBaseOrgRepository()
const distinctOrgUUIDs = [...new Set(returnValue.users.map(u => u.org_UUID))]
Expand All @@ -55,7 +56,7 @@ async function getAllUsers (req, res, next) {
const orgMap = {}
for (const uuid of distinctOrgUUIDs) {
// We need the org content to get admins
const org = await orgRepo.findOneByUUID(uuid)
const org = await orgRepo.findOneByUUID(uuid, {}, REGISTRY_FORMAT)
if (org) {
orgMap[uuid] = org
}
Expand Down Expand Up @@ -110,14 +111,14 @@ async function getUser (req, res, next) {

const userRepo = req.ctx.repositories.getBaseUserRepository()
const repo = req.ctx.repositories.getBaseOrgRepository()
const isSecretariat = await authContext.isRequesterSecretariat(req, repo)
const isSecretariat = await authContext.isRequesterSecretariat(req, repo, {}, REGISTRY_FORMAT)

try {
let result
let org

if (identifier) {
result = await userRepo.findUserByUUID(identifier)
result = await userRepo.findUserByUUID(identifier, {}, REGISTRY_FORMAT)
if (!result) {
logger.info({ uuid: req.ctx.uuid, message: identifier + ' user could not be found.' })
return res.status(404).json(error.userDne(identifier))
Expand All @@ -129,22 +130,22 @@ async function getUser (req, res, next) {
return res.status(404).json(error.userDne(identifier))
}

org = await repo.findOneByUUID(orgUUID)
org = await repo.findOneByUUID(orgUUID, {}, REGISTRY_FORMAT)

userToGetParameters = {
org: org.short_name,
username: result.username
}
} else {
org = await repo.findOneByShortName(req.ctx.params.shortname)
org = await repo.findOneByShortName(req.ctx.params.shortname, {}, REGISTRY_FORMAT)

const isSameOrg = await authContext.isRequesterSameOrg(req, repo, org)
const isSameOrg = await authContext.isRequesterSameOrg(req, repo, org, {}, REGISTRY_FORMAT)
if (!isSecretariat && !isSameOrg) {
logger.info({ uuid: req.ctx.uuid, message: userToGetParameters.org + ' organization can only be viewed by the users of the same organization or the Secretariat.' })
return res.status(403).json(error.notSameOrgOrSecretariat())
}

result = await userRepo.findOneByUsernameAndOrgShortname(userToGetParameters.username, userToGetParameters.org)
result = await userRepo.findOneByUsernameAndOrgShortname(userToGetParameters.username, userToGetParameters.org, {}, REGISTRY_FORMAT)
if (!result) {
logger.info({ uuid: req.ctx.uuid, message: userToGetParameters.username + ' user could not be found.' })
return res.status(404).json(error.userDne(userToGetParameters.username))
Expand All @@ -157,7 +158,7 @@ async function getUser (req, res, next) {
}

if (identifier) {
const isSameOrg = await authContext.isRequesterSameOrg(req, repo, org)
const isSameOrg = await authContext.isRequesterSameOrg(req, repo, org, {}, REGISTRY_FORMAT)
if (!isSecretariat && !isSameOrg) {
logger.info({ uuid: req.ctx.uuid, message: identifier + ' organization can only be viewed by the users of the same organization or the Secretariat.' })
return res.status(403).json(error.notSameOrgOrSecretariat())
Expand Down Expand Up @@ -213,15 +214,15 @@ async function updateUser (req, res, next) {
username: req.ctx.params.username
}

const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo)
const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo, {}, REGISTRY_FORMAT)

// TODO: This will need to be atomic at some point like revoke or grant
// Specific check for org_short_name (Secretariat only)

let userToEdit
let org
if (identifier) {
userToEdit = await userRepo.findUserByUUID(identifier)
userToEdit = await userRepo.findUserByUUID(identifier, {}, REGISTRY_FORMAT)
if (!userToEdit) {
logger.info({ uuid: req.ctx.uuid, message: identifier + ' user could not be found.' })
return res.status(404).json(error.userDne(identifier))
Expand All @@ -233,20 +234,20 @@ async function updateUser (req, res, next) {
return res.status(404).json(error.orgDnePathParam(identifier))
}

org = await orgRepo.findOneByUUID(orgUUID)
org = await orgRepo.findOneByUUID(orgUUID, {}, REGISTRY_FORMAT)
userToEditParameters.org = org.short_name
userToEditParameters.username = userToEdit.username
} else {
userToEdit = await userRepo.findOneByUsernameAndOrgShortname(userToEditParameters.username, userToEditParameters.org)
org = await orgRepo.findOneByShortName(userToEditParameters.org)
userToEdit = await userRepo.findOneByUsernameAndOrgShortname(userToEditParameters.username, userToEditParameters.org, {}, REGISTRY_FORMAT)
org = await orgRepo.findOneByShortName(userToEditParameters.org, {}, REGISTRY_FORMAT)
if (!org) {
logger.info({ uuid: req.ctx.uuid, message: `Target organization ${userToEditParameters.org} does not exist.` })
return res.status(404).json(error.orgDnePathParam(userToEditParameters.org))
}
}

const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, org)
const requesterUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo)
const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, org, {}, REGISTRY_FORMAT)
const requesterUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, {}, REGISTRY_FORMAT)

// Allow existing UUIDs to be passed, but block any attempts to mutate them
if (userToEdit) {
Expand All @@ -267,7 +268,7 @@ async function updateUser (req, res, next) {
}

if (body.org_short_name) {
const targetOrg = await orgRepo.findOneByShortName(body.org_short_name)
const targetOrg = await orgRepo.findOneByShortName(body.org_short_name, {}, REGISTRY_FORMAT)
if (!targetOrg) {
logger.info({ uuid: req.ctx.uuid, message: `Target organization ${body.org_short_name} does not exist.` })
return res.status(404).json(error.orgDnePathParam(body.org_short_name))
Expand All @@ -284,7 +285,7 @@ async function updateUser (req, res, next) {
return res.status(404).json(error.orgDnePathParam(userToEditParameters.org))
}

const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, org)
const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, org, {}, REGISTRY_FORMAT)
if (!isSecretariat && !isAdmin && !requesterSameOrg) {
logger.info({ uuid: req.ctx.uuid, message: requestingUserParameters.org + ' user can only be updated by the user or admins of the same organization or the Secretariat.' })
return res.status(403).json(error.notSameOrgOrSecretariat())
Expand Down Expand Up @@ -341,7 +342,7 @@ async function updateUser (req, res, next) {

// Ask repo if user already exists
if (body?.username && body.username !== userToEdit.username) {
if (await userRepo.orgHasUser(userToEditParameters.org, body.username, { session })) {
if (await userRepo.orgHasUser(userToEditParameters.org, body.username, { session }, REGISTRY_FORMAT)) {
logger.info({ uuid: req.ctx.uuid, message: 'The username ' + body.username + ' already exists.' })
await session.abortTransaction()
return res.status(403).json(error.duplicateUsername())
Expand All @@ -352,7 +353,7 @@ async function updateUser (req, res, next) {
const requestingUserUUID = requesterUserUUID
updatedUserUUID = userToEdit.UUID

updatedUser = await userRepo.updateUserFull(userToEdit.UUID, body, { session }, true, requestingUserUUID)
updatedUser = await userRepo.updateUserFull(userToEdit.UUID, body, { session }, REGISTRY_FORMAT, requestingUserUUID)
await session.commitTransaction()
} catch (error) {
await session.abortTransaction()
Expand Down Expand Up @@ -397,22 +398,22 @@ async function deleteUser (req, res, next) {
const orgRepo = req.ctx.repositories.getBaseOrgRepository()
const orgShortName = req.ctx.params.shortname
const username = req.ctx.params.username
const org = await orgRepo.findOneByShortName(orgShortName)
const org = await orgRepo.findOneByShortName(orgShortName, {}, REGISTRY_FORMAT)

if (!org) {
logger.info({ uuid: req.ctx.uuid, message: 'Org DNE' })
return res.status(404).json(error.orgDnePathParam(orgShortName))
}

const user = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName)
const user = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName, {}, REGISTRY_FORMAT)

if (!user) {
logger.info({ uuid: req.ctx.uuid, message: 'User DNE' })
return res.status(404).json(error.userDne(username))
}

const userUUID = user.UUID
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo)
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, {}, REGISTRY_FORMAT)
await userRepo.deleteUserByUUID(userUUID, {}, requestingUserUUID)

const payload = {
Expand Down Expand Up @@ -459,21 +460,21 @@ async function grantRole (req, res, next) {
return res.status(404).json(error.orgDnePathParam(orgShortName))
}

const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo)
const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo, {}, REGISTRY_FORMAT)
const targetOrg = { UUID: targetOrgUUID, short_name: orgShortName }

const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, targetOrg)
const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, targetOrg, {}, REGISTRY_FORMAT)
if (!requesterSameOrg && !isSecretariat) {
return res.status(403).json(error.notSameOrgOrSecretariat())
}

const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, targetOrg)
const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, targetOrg, {}, REGISTRY_FORMAT)
if (!isSecretariat && !isAdmin) {
return res.status(403).json(error.notOrgAdminOrSecretariatUpdate())
}

// Check if target user exists in target org
const targetUser = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName)
const targetUser = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName, {}, REGISTRY_FORMAT)
if (!targetUser) {
return res.status(404).json(error.userDne(username))
}
Expand All @@ -482,7 +483,7 @@ async function grantRole (req, res, next) {

try {
session.startTransaction({ readPreference: 'primary' })
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, { session })
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, { session }, REGISTRY_FORMAT)
await orgRepo.addAdmin(orgShortName, targetUser.UUID, { session }, requestingUserUUID)
await session.commitTransaction()
} catch (error) {
Expand Down Expand Up @@ -524,27 +525,27 @@ async function revokeRole (req, res, next) {
return res.status(404).json(error.orgDnePathParam(orgShortName))
}

const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo)
const isSecretariat = await authContext.isRequesterSecretariat(req, orgRepo, {}, REGISTRY_FORMAT)
const targetOrg = { UUID: targetOrgUUID, short_name: orgShortName }

const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, targetOrg)
const requesterSameOrg = await authContext.isRequesterSameOrg(req, orgRepo, targetOrg, {}, REGISTRY_FORMAT)
if (!requesterSameOrg && !isSecretariat) {
return res.status(403).json(error.notSameOrgOrSecretariat())
}

const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, targetOrg)
const isAdmin = await authContext.isRequesterAdminOfOrg(req, userRepo, orgRepo, targetOrg, {}, REGISTRY_FORMAT)
if (!isSecretariat && !isAdmin) {
return res.status(403).json(error.notOrgAdminOrSecretariatUpdate())
}

// Check if target user exists in target org
const targetUser = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName)
const targetUser = await userRepo.findOneByUsernameAndOrgShortname(username, orgShortName, {}, REGISTRY_FORMAT)
if (!targetUser) {
return res.status(404).json(error.userDne(username))
}

// Prevent Self-Demotion
const callingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo)
const callingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, {}, REGISTRY_FORMAT)
if (callingUserUUID === targetUser.UUID) {
return res.status(403).json({ error: 'NOT_ALLOWED_TO_SELF_DEMOTE', message: 'You cannot remove the ADMIN role from yourself.' })
}
Expand All @@ -553,7 +554,7 @@ async function revokeRole (req, res, next) {

try {
session.startTransaction({ readPreference: 'primary' })
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, { session })
const requestingUserUUID = await authContext.getRequesterUserUUID(req, userRepo, orgRepo, { session }, REGISTRY_FORMAT)
await orgRepo.removeAdmin(orgShortName, targetUser.UUID, { session }, requestingUserUUID)
await session.commitTransaction()
} catch (error) {
Expand Down
Loading
Loading