Skip to content
6 changes: 3 additions & 3 deletions api-docs/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -5078,7 +5078,7 @@
}
}
},
"/review/org/{uuid}": {
"/review/{uuid}": {
"put": {
"tags": [
"Review Object"
Expand Down Expand Up @@ -5181,7 +5181,7 @@
}
}
},
"/review/org/{uuid}/approve": {
"/review/{uuid}/approve": {
"put": {
"tags": [
"Review Object"
Expand Down Expand Up @@ -5285,7 +5285,7 @@
}
}
},
"/review/org/{uuid}/reject": {
"/review/{uuid}/reject": {
"put": {
"tags": [
"Review Object"
Expand Down
2 changes: 1 addition & 1 deletion src/controller/org.controller/org.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ async function getUser (req, res, next) {

/**
* Get details on ID quota for an org with the specified org shortname.
* Called by GET /api/registry/org/{shortname}/id_quota, GET /api/org/{shortname}/id_quota
* Called by GET /api/registry/org/{shortname}/hard_quota, GET /api/org/{shortname}/id_quota
*
* @param {Object} req - The request object
* @param {Object} res - The response object
Expand Down
6 changes: 3 additions & 3 deletions src/controller/review-object.controller/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ router.get('/review/org/:identifier/reviews',
)

// Update a review object
router.put('/review/org/:uuid',
router.put('/review/:uuid',
/*
#swagger.tags = ['Review Object']
#swagger.operationId = 'updateReviewObjectByReviewUUID'
Expand Down Expand Up @@ -407,7 +407,7 @@ router.put('/review/org/:uuid',
)

// Approve a review object
router.put('/review/org/:uuid/approve',
router.put('/review/:uuid/approve',
/*
#swagger.tags = ['Review Object']
#swagger.operationId = 'approveReviewObject'
Expand Down Expand Up @@ -491,7 +491,7 @@ router.put('/review/org/:uuid/approve',
)

// Reject a review object
router.put('/review/org/:uuid/reject',
router.put('/review/:uuid/reject',
/*
#swagger.tags = ['Review Object']
#swagger.operationId = 'rejectReviewObject'
Expand Down
107 changes: 79 additions & 28 deletions src/controller/review-object.controller/review-object.controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ async function getReviewObjectByOrgIdentifier (req, res, next) {
let value
// We may want this to be something different, but for now we are just testing
if (identifierIsUUID) {
value = await repo.getOrgReviewObjectByOrgUUID(identifier, isSecretariat)
value = await repo.getOrgReviewObjectByOrgUUID(identifier, isSecretariat, {})
} else {
value = await repo.getOrgReviewObjectByOrgShortname(identifier, isSecretariat)
value = await repo.getOrgReviewObjectByOrgShortname(identifier, isSecretariat, {})
}
if (!value) {
return res.status(404).json({ message: 'No pending review object exists for this organization' })
Expand Down Expand Up @@ -61,19 +61,26 @@ async function approveReviewObject (req, res, next) {
const reviewRepo = req.ctx.repositories.getReviewObjectRepository()
const baseOrgRepo = req.ctx.repositories.getBaseOrgRepository()
const userRepo = req.ctx.repositories.getBaseUserRepository()
const isSecretariat = await baseOrgRepo.isSecretariatByShortName(req.ctx.org)
const isPendingReview = true
const UUID = req.params.uuid
const body = req.body
const session = await mongoose.startSession()
let reviewObj
const session = await mongoose.startSession({ causalConsistency: false })
let updatedOrgObj

try {
session.startTransaction()

const reviewObject = await reviewRepo.findOneByUUID(UUID, { session })
const bodyValidation = (body && Object.keys(body).length) ? baseOrgRepo.validateOrg(body) : { isValid: true }
if (!bodyValidation.isValid) {
await session.abortTransaction()
return res.status(400).json({ message: 'Invalid body parameters', errors: bodyValidation.errors })
}

const reviewObject = await reviewRepo.findOneByUUIDWithConversation(UUID, isSecretariat, isPendingReview, { session })
if (!reviewObject) {
await session.abortTransaction()
return res.status(404).json({ message: `No review object found with UUID ${UUID}` })
return res.status(404).json({ message: `No pending review object found with UUID ${UUID}` })
}

const org = await baseOrgRepo.findOneByUUID(reviewObject.target_object_uuid, { session })
Expand All @@ -88,56 +95,89 @@ async function approveReviewObject (req, res, next) {

const requestingUserUUID = await userRepo.getUserUUID(req.ctx.user, req.ctx.org, { session })

reviewObj = await reviewRepo.approveReviewOrgObject(UUID, { session })
await baseOrgRepo.updateOrgFull(org.short_name, dataToUpdate, { session }, false, requestingUserUUID, false, true)
const reviewObj = await reviewRepo.approveReviewOrgObject(UUID, { session })
if (!reviewObj) {
await session.abortTransaction()
return res.status(404).json({ message: `Review object not approved with UUID ${UUID}` })
}
updatedOrgObj = await baseOrgRepo.updateOrgFull(org.short_name, dataToUpdate, { session }, false, requestingUserUUID, false, true)
if (!updatedOrgObj) {
await session.abortTransaction()
return res.status(404).json({ message: `Org Object not updated with UUID ${UUID}` })
}

await session.commitTransaction()

// Return the updated organization
updatedOrgObj = await baseOrgRepo.findOneByUUID(reviewObject.target_object_uuid)
} catch (updateErr) {
await session.abortTransaction()
throw updateErr
return res.status(500).json({ message: updateErr.message || 'Failed to approve review object' })
} finally {
await session.endSession()
}

if (!reviewObj) {
return res.status(404).json({ message: `No review object found with UUID ${UUID}` })
}

return res.status(200).json(updatedOrgObj ? updatedOrgObj.toObject() : null)
_.unset(updatedOrgObj, 'joint_approval_required')
return res.status(200).json(updatedOrgObj)
}

async function updateReviewObjectByReviewUUID (req, res, next) {
const repo = req.ctx.repositories.getReviewObjectRepository()
const UUID = req.params.uuid
const orgRepo = req.ctx.repositories.getBaseOrgRepository()
const body = req.body
const session = await mongoose.startSession({ causalConsistency: false })
let updatedReviewObj

const result = orgRepo.validateOrg(body)
if (!result.isValid) {
return res.status(400).json({ message: 'Invalid new_review_data', errors: result.errors })
}

const value = await repo.updateReviewOrgObject(body, UUID)
try {
session.startTransaction()
const reviewObject = await repo.findOneByUUIDWithConversation(UUID, false, true, { session })
if (!reviewObject) {
await session.abortTransaction()
return res.status(404).json({ message: `No pending review object found with UUID ${UUID}` })
}
updatedReviewObj = await repo.updateReviewOrgObject(body, UUID, { session })
} catch (updateErr) {
await session.abortTransaction()
return res.status(500).json({ message: updateErr.message || 'Failed to update review object' })
} finally {
await session.endSession()
}

if (!value) {
if (!updatedReviewObj) {
return res.status(404).json({ message: `No review object found with UUID ${UUID}` })
}
return res.status(200).json(value)
return res.status(200).json(updatedReviewObj)
}

async function createReviewObject (req, res, next) {
const baseOrgRepo = req.ctx.repositories.getBaseOrgRepository()
const repo = req.ctx.repositories.getReviewObjectRepository()
const body = req.body
const session = await mongoose.startSession({ causalConsistency: false })
let createdReviewObj

const value = await repo.createReviewOrgObject(body)
try {
session.startTransaction()
const bodyValidation = (body && Object.keys(body).length) ? baseOrgRepo.validateOrg(body, { session }) : { isValid: false }
if (!bodyValidation.isValid) {
await session.abortTransaction()
return res.status(400).json({ message: 'Invalid body parameters', errors: bodyValidation.errors })
}
createdReviewObj = await repo.createReviewOrgObject(body, { session })
await session.commitTransaction()
} catch (createErr) {
await session.abortTransaction()
return res.status(500).json({ message: createErr.message || 'Failed to create review object' })
} finally {
await session.endSession()
}

if (!value) {
if (!createdReviewObj) {
return res.status(500).json({ message: 'Failed to create review object' })
}
return res.status(200).json(value)
return res.status(200).json(createdReviewObj)
}

/**
Expand Down Expand Up @@ -173,19 +213,30 @@ async function getReviewHistoryByOrgShortNamePaginated (req, res, next) {
}

async function rejectReviewObject (req, res, next) {
const repo = req.ctx.repositories.getReviewObjectRepository()
const reviewRepo = req.ctx.repositories.getReviewObjectRepository()
const baseOrgRepo = req.ctx.repositories.getBaseOrgRepository()
const UUID = req.params.uuid
const session = await mongoose.startSession()
const session = await mongoose.startSession({ causalConsistency: false })

const isSecretariat = await baseOrgRepo.isSecretariatByShortName(req.ctx.org, { session })

const isPendingReview = true
let value

try {
session.startTransaction()

value = await repo.rejectReviewOrgObject(UUID, { session })
const reviewObject = await reviewRepo.findOneByUUIDWithConversation(UUID, isSecretariat, isPendingReview, { session })
if (!reviewObject) {
await session.abortTransaction()
return res.status(404).json({ message: `No pending review object found with UUID ${UUID}` })
}

value = await reviewRepo.rejectReviewOrgObject(UUID, { session })
await session.commitTransaction()
} catch (rejectErr) {
await session.abortTransaction()
throw rejectErr
return res.status(500).json({ message: rejectErr.message || 'Failed to reject review object' })
} finally {
await session.endSession()
}
Expand Down
5 changes: 3 additions & 2 deletions src/repositories/reviewObjectRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ class ReviewObjectRepository extends BaseRepository {
return reviewObject || null
}

async findOneByUUIDWithConversation (UUID, isSecretariat, options = {}) {
async findOneByUUIDWithConversation (UUID, isSecretariat, pending = false, options = {}) {
const ConversationRepository = require('./conversationRepository')
const conversationRepository = new ConversationRepository()
let reviewObject
const reviewObjectRaw = await ReviewObjectModel.findOne({ uuid: UUID }, null, options)
const query = pending ? { uuid: UUID, status: 'pending' } : { uuid: UUID }
const reviewObjectRaw = await ReviewObjectModel.findOne(query, null, options)
if (reviewObjectRaw) {
reviewObject = reviewObjectRaw.toObject()
const conversations = await conversationRepository.getAllByTargetUUID(reviewObject.target_object_uuid, isSecretariat, options)
Expand Down
15 changes: 12 additions & 3 deletions src/scripts/populate.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,15 +132,24 @@ db.once('open', async () => {

// don't close database connection until all remaining populate
// promises are resolved
Promise.all(populatePromises).then(function () {
Promise.all(populatePromises).then(async function () {
logger.info('Successfully populated the database!')

const indexPromises = []
Object.keys(indexesToCreate).forEach(col => {
indexesToCreate[col].forEach(index => {
db.collections[col].createIndex(index)
indexPromises.push(db.collections[col].createIndex(index))
})
})
mongoose.connection.close()

try {
await Promise.all(indexPromises)
logger.info('Successfully created indexes!')
} catch (err) {
logger.error('Error creating indexes:', err)
} finally {
mongoose.connection.close()
}
})
} else {
mongoose.connection.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,9 @@ describe('Testing Joint approval', () => {
})
})
it('Secretariat can approve the ORG review with body parameter', async function () {
const newBody = { short_name: 'final_non_secretariat_org', hard_quota: 20000 }
const newBody = { short_name: 'final_non_secretariat_org', hard_quota: 20000, long_name: 'Final Non Secretariat Organization' }
await chai.request(app)
.put(`/api/review/org/${reviewUUID}/approve`)
.put(`/api/review/${reviewUUID}/approve`)
.set(secretariatHeaders)
.send(newBody)
.then((res) => {
Expand Down Expand Up @@ -306,7 +306,7 @@ describe('Testing Joint approval', () => {
})
it('Secretariat can approve the ORG review', async function () {
await chai.request(app)
.put(`/api/review/org/${reviewUUID}/approve`)
.put(`/api/review/${reviewUUID}/approve`)
.set(secretariatHeaders)
.then((res) => {
expect(res).to.have.status(200)
Expand Down
Loading
Loading