Skip to content
Merged
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
27 changes: 24 additions & 3 deletions src/services/ResourceService.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
20 changes: 20 additions & 0 deletions test/common/testData.js
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
18 changes: 18 additions & 0 deletions test/unit/getResources.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Loading