From f3c92d2c33067095e7f8a1d05d8e33282ae4fb03 Mon Sep 17 00:00:00 2001 From: Mithun Kamath Date: Mon, 26 Jul 2021 22:53:57 +0530 Subject: [PATCH] #243 - Update permissions on review route --- src/common/helper.js | 40 ++++++++++++++++++++++++++++++++++- src/routes/ReviewRoutes.js | 2 +- src/services/ReviewService.js | 4 +++- 3 files changed, 43 insertions(+), 3 deletions(-) diff --git a/src/common/helper.js b/src/common/helper.js index bdfa6984..3fb2265a 100755 --- a/src/common/helper.js +++ b/src/common/helper.js @@ -601,10 +601,21 @@ function * checkGetAccess (authUser, submission) { * @returns {Promise} */ function * checkReviewGetAccess (authUser, submission) { + let resources let challengeDetails const token = yield getM2Mtoken() const challengeId = yield getV5ChallengeId(submission.challengeId) + try { + resources = yield request.get(`${config.RESOURCEAPI_V5_BASE_URL}/resources?challengeId=${challengeId}`) + .set('Authorization', `Bearer ${token}`) + .set('Content-Type', 'application/json') + } catch (ex) { + logger.error(`Error while accessing ${config.RESOURCEAPI_V5_BASE_URL}/resources?challengeId=${challengeId}`) + logger.error(ex) + throw new errors.HttpStatusError(503, `Could not determine the user's role in the challenge with id ${challengeId}`) + } + try { challengeDetails = yield request.get(`${config.CHALLENGEAPI_V5_URL}/${challengeId}`) .set('Authorization', `Bearer ${token}`) @@ -615,9 +626,32 @@ function * checkReviewGetAccess (authUser, submission) { return false } - if (challengeDetails) { + // Get map of role id to role name + const resourceRolesMap = yield getRoleIdToRoleNameMap() + + // Check if role id to role name mapping is available. If not user's role cannot be determined. + if (resourceRolesMap == null || _.size(resourceRolesMap) === 0) { + throw new errors.HttpStatusError(503, `Could not determine the user's role in the challenge with id ${challengeId}`) + } + + if (resources && challengeDetails) { + // Fetch all roles of the User pertaining to the current challenge + const currUserRoles = _.filter(resources.body, { memberHandle: authUser.handle }) + + // Populate the role names for the current user role ids + _.forEach(currUserRoles, currentUserRole => { + currentUserRole.role = resourceRolesMap[currentUserRole.roleId] + }) + const subTrack = challengeDetails.body.legacy.subTrack + // Check if the User is a Copilot, Manager or Observer for that contest + const validRoles = ['Copilot', 'Manager', 'Observer'] + const passedRoles = currUserRoles.filter(a => validRoles.includes(a.role)) + if (passedRoles.length !== 0) { + return true + } + // For Marathon Match, everyone can access review result if (subTrack === 'DEVELOP_MARATHON_MATCH') { logger.info('No access check for Marathon match') @@ -632,6 +666,10 @@ function * checkReviewGetAccess (authUser, submission) { return true } + } else { + // We don't have enough details to validate the access + logger.debug('No enough details to validate the Permissions') + throw new errors.HttpStatusError(503, `Not all information could be fetched about challenge with id ${submission.challengeId}`) } } diff --git a/src/routes/ReviewRoutes.js b/src/routes/ReviewRoutes.js index 4e7d4975..f6f4c929 100644 --- a/src/routes/ReviewRoutes.js +++ b/src/routes/ReviewRoutes.js @@ -24,7 +24,7 @@ module.exports = { controller: 'ReviewController', method: 'getReview', auth: 'jwt', - access: ['Administrator', 'Copilot'], + access: ['Administrator', 'Copilot', 'Topcoder User'], scopes: ['read:review', 'all:review'] }, put: { diff --git a/src/services/ReviewService.js b/src/services/ReviewService.js index ffd565d0..3a61ddf7 100644 --- a/src/services/ReviewService.js +++ b/src/services/ReviewService.js @@ -70,7 +70,9 @@ function * getReview (authUser, reviewId) { false ) logger.info('Check User access before returning the review') - yield helper.checkReviewGetAccess(authUser, submission) + if (_.intersection(authUser.roles, ['Administrator', 'administrator']).length === 0 && !authUser.scopes) { + yield helper.checkReviewGetAccess(authUser, submission) + } // Return the review return review }