diff --git a/src/services/ResourceService.js b/src/services/ResourceService.js index 8ddadc1..04e17a3 100644 --- a/src/services/ResourceService.js +++ b/src/services/ResourceService.js @@ -27,6 +27,13 @@ const RESTRICTED_ROLE_NAMES = [ 'checkpoint reviewer', 'approver' ] +const RESOURCE_MANAGER_ROLE_NAMES = new Set([ + _.toLower(constants.UserRoles.Manager), + 'project manager', + 'topcoder project manager', + 'talent manager', + 'topcoder talent manager' +]) let copilotResourceRoleIdsCache let restrictedRoleIdsCache @@ -72,11 +79,25 @@ async function getRestrictedRoleIds () { return restrictedRoleIdsCache } +/** + * Check whether the current user has a Work manager role that can manage challenge resources. + * @param {Object} currentUser the current user + * @returns {Boolean} true when the user has a resource manager role + */ +function hasResourceManagerRole (currentUser) { + return _.some(_.get(currentUser, 'roles', []), role => RESOURCE_MANAGER_ROLE_NAMES.has(_.toLower(role))) +} + /** * Check whether the user can access resources + * @param {Object} currentUser the current user * @param {Array} resources resources of current user for specified challenge id */ -async function checkAccess (currentUserResources) { +async function checkAccess (currentUser, currentUserResources) { + if (hasResourceManagerRole(currentUser)) { + return + } + const copilotRoleIds = await getCopilotResourceRoleIds() const hasCopilotRole = _.some(currentUserResources, r => copilotRoleIds.includes(r.roleId)) if (hasCopilotRole) { @@ -166,7 +187,7 @@ async function getResources (currentUser, challengeId, roleId, memberId, memberH } }) try { - await checkAccess(resources) + await checkAccess(currentUser, resources) hasFullAccess = true } catch (e) { hasFullAccess = false @@ -453,7 +474,7 @@ async function init (currentUser, challengeId, resource, isCreated) { if (!resourceRole.selfObtainable || _.toString(memberId) !== _.toString(currentUser.userId)) { // if user is not creating/deleting a self obtainable resource for itself // we need to perform check access first - await checkAccess(currentUserResources) + await checkAccess(currentUser, currentUserResources) } } } diff --git a/test/common/testData.js b/test/common/testData.js index e21d6d7..c37aeb6 100644 --- a/test/common/testData.js +++ b/test/common/testData.js @@ -55,6 +55,26 @@ const user = { email: 'email@domain.com.z', jti: 'f1e613be-d5b9-4231-baae-ee9f2d227234' }, + projectManager: { + roles: [ 'Topcoder User', 'project manager' ], + iss: 'https://api.topcoder-dev.com', + handle: 'projectmanager', + exp: 1561792370, + userId: '8123456', + iat: 1549791770, + email: 'email@domain.com.z', + jti: 'f1e613be-d5b9-4231-baae-ee9f2d227234' + }, + talentManager: { + roles: [ 'Topcoder User', 'talent manager' ], + iss: 'https://api.topcoder-dev.com', + handle: 'talentmanager', + exp: 1561792370, + userId: '8123457', + iat: 1549791770, + email: 'email@domain.com.z', + jti: 'f1e613be-d5b9-4231-baae-ee9f2d227234' + }, lunarkid: { roles: [ 'Topcoder User' ], iss: 'https://api.topcoder-dev.com', diff --git a/test/unit/getResources.test.js b/test/unit/getResources.test.js index a80183b..ee6b8d2 100644 --- a/test/unit/getResources.test.js +++ b/test/unit/getResources.test.js @@ -79,6 +79,24 @@ module.exports = describe('Get resources', () => { should.equal(hasReviewerRole, true) }) + it('get resources by project manager role', async () => { + const result = await service.getResources(user.projectManager, challengeId) + should.equal(result.total, 5) + for (const record of result.data) { + await assertResource(record.id, record) + should.exist(record.roleName) + } + }) + + it('get resources by talent manager role', async () => { + const result = await service.getResources(user.talentManager, challengeId) + should.equal(result.total, 5) + for (const record of result.data) { + await assertResource(record.id, record) + should.exist(record.roleName) + } + }) + it('enforces challenge user whitelist for interactive resource reads', async () => { await helper.prismaChallenge.challengeUserWhitelist.deleteMany({ where: { challengeId }