-
Notifications
You must be signed in to change notification settings - Fork 2
Migration final deploy #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a84951a
c699a78
1a332b8
fb67833
8fc15a5
3bdb524
9ea5fde
3d6d671
41cfbfe
ea06535
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,7 +16,20 @@ const prisma = require('../common/prisma').getClient() | |
|
|
||
| const payloadFields = ['id', 'challengeId', 'memberId', 'memberHandle', 'roleId', 'phaseChangeNotifications', 'created', 'createdBy', 'updated', 'updatedBy'] | ||
|
|
||
| // Restricted roles that cannot be combined with submitter role | ||
| const RESTRICTED_ROLE_NAMES = [ | ||
| 'manager', | ||
| 'copilot', | ||
| 'reviewer', | ||
| 'iterative reviewer', | ||
| 'screener', | ||
| 'checkpoint screener', | ||
| 'checkpoint reviewer', | ||
| 'approver' | ||
| ] | ||
|
|
||
| let copilotResourceRoleIdsCache | ||
| let restrictedRoleIdsCache | ||
|
|
||
| async function getCopilotResourceRoleIds () { | ||
| if (copilotResourceRoleIdsCache) { | ||
|
|
@@ -34,11 +47,42 @@ async function getCopilotResourceRoleIds () { | |
| return copilotResourceRoleIdsCache | ||
| } | ||
|
|
||
| /** | ||
| * Get resource role IDs that are restricted from being combined with submitter role. | ||
| * These include: Manager, Copilot, Reviewer, Iterative Reviewer, Screener, | ||
| * Checkpoint Screener, Checkpoint Reviewer, and Approver. | ||
| * @returns {Promise<Array<String>>} Array of restricted role IDs | ||
| */ | ||
| async function getRestrictedRoleIds () { | ||
| if (restrictedRoleIdsCache) { | ||
| return restrictedRoleIdsCache | ||
| } | ||
| const roles = await prisma.resourceRole.findMany({ | ||
| where: { | ||
| nameLower: { | ||
| in: RESTRICTED_ROLE_NAMES | ||
| } | ||
| }, | ||
| select: { | ||
| id: true, | ||
| nameLower: true | ||
| } | ||
| }) | ||
| restrictedRoleIdsCache = roles.map(role => role.id) | ||
| return restrictedRoleIdsCache | ||
| } | ||
|
|
||
| /** | ||
| * Check whether the user can access resources | ||
| * @param {Array} resources resources of current user for specified challenge id | ||
| */ | ||
| async function checkAccess (currentUserResources) { | ||
| const copilotRoleIds = await getCopilotResourceRoleIds() | ||
| const hasCopilotRole = _.some(currentUserResources, r => copilotRoleIds.includes(r.roleId)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [💡 |
||
| if (hasCopilotRole) { | ||
| return | ||
| } | ||
|
|
||
| const list = await prisma.resourceRole.findMany({}) | ||
| const fullAccessRoles = [] | ||
| _.each(list, e => { | ||
|
|
@@ -291,6 +335,12 @@ async function init (currentUser, challengeId, resource, isCreated) { | |
| const { memberId, email } = memberInfoFromDb | ||
| handle = memberInfoFromDb.handle | ||
| const userResources = allResources.filter((r) => _.toLower(r.memberHandle) === _.toLower(handle)) | ||
|
|
||
| let restrictedRoleIds | ||
| if (isCreated) { | ||
| restrictedRoleIds = await getRestrictedRoleIds() | ||
| } | ||
|
|
||
| // Retrieve the constraint - Allowed Registrants | ||
| if (isCreated && resource.roleId === config.SUBMITTER_RESOURCE_ROLE_ID) { | ||
| const allowedRegistrants = _.get(challenge, 'constraints.allowedRegistrants') | ||
|
|
@@ -307,12 +357,20 @@ async function init (currentUser, challengeId, resource, isCreated) { | |
| `User ${handle} is not allowed to register.` | ||
| ) | ||
| } | ||
| if (!_.get(challenge, 'task.isTask', false) && (_.toLower(challenge.createdBy) === _.toLower(handle) || | ||
| _.some(userResources, r => r.roleId === config.REVIEWER_RESOURCE_ROLE_ID || r.roleId === config.ITERATIVE_REVIEWER_RESOURCE_ROLE_ID))) { | ||
| // Prevent challenge creator from registering as submitter (for non-tasks) | ||
| if (!_.get(challenge, 'task.isTask', false) && _.toLower(challenge.createdBy) === _.toLower(memberId)) { | ||
| throw new errors.BadRequestError( | ||
| `User ${handle} is not allowed to register.` | ||
| ) | ||
| } | ||
| // Check if user already has a restricted role (Manager, Copilot, Reviewer, etc.) | ||
| const existingRestrictedRole = _.find(userResources, r => restrictedRoleIds.includes(r.roleId)) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| if (existingRestrictedRole) { | ||
| const roleNamesList = RESTRICTED_ROLE_NAMES.slice(0, -1).join(', ') + ', or ' + RESTRICTED_ROLE_NAMES.slice(-1) | ||
| throw new errors.BadRequestError( | ||
| `User ${handle} is already assigned a restricted role (${roleNamesList}) and cannot be registered as a submitter.` | ||
| ) | ||
| } | ||
| } | ||
|
|
||
| // Prevent from creating more than 1 submitter resources on tasks | ||
|
|
@@ -344,6 +402,18 @@ async function init (currentUser, challengeId, resource, isCreated) { | |
| // ensure resource role existed | ||
| const resourceRole = await getResourceRole(resource.roleId, isCreated) | ||
|
|
||
| // Check if user is trying to assign a restricted role and already has submitter role | ||
| if (isCreated) { | ||
| if (restrictedRoleIds.includes(resource.roleId)) { | ||
| const existingSubmitterRole = _.find(userResources, r => r.roleId === config.SUBMITTER_RESOURCE_ROLE_ID) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| if (existingSubmitterRole) { | ||
| throw new errors.BadRequestError( | ||
| `User ${handle} is already registered as a submitter and cannot be assigned a ${resourceRole.name} role.` | ||
| ) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // Verify the member has agreed to the challenge terms | ||
| if (isCreated) { | ||
| await helper.checkAgreedTerms(memberId, _.filter(_.get(challenge, 'terms', []), t => t.roleId === resourceRole.id)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,6 +9,7 @@ const { v4: uuid } = require('uuid') | |
| const service = require('../../src/services/ResourceService') | ||
| const ResourceRolePhaseDependencyService = require('../../src/services/ResourceRolePhaseDependencyService') | ||
| const prisma = require('../../src/common/prisma').getClient() | ||
| const helper = require('../../src/common/helper') | ||
| const ResourceRoleService = require('../../src/services/ResourceRoleService') | ||
| const { requestBody, user } = require('../common/testData') | ||
| const { assertValidationError, assertError, assertResource, getRoleIds, clearDependencies } = require('../common/testHelper') | ||
|
|
@@ -264,6 +265,39 @@ module.exports = describe('Create resource', () => { | |
| await assertResource(ret.id, ret) | ||
| }) | ||
|
|
||
| it('copilot can manage resources without full access flags', async () => { | ||
| const originalRole = await helper.getById('ResourceRole', copilotRoleId) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| await ResourceRoleService.updateResourceRole(user.admin, copilotRoleId, { | ||
| name: originalRole.name, | ||
| fullReadAccess: false, | ||
| fullWriteAccess: false, | ||
| isActive: originalRole.isActive, | ||
| selfObtainable: originalRole.selfObtainable | ||
| }) | ||
|
|
||
| const entity = resources.createBody('diazz', reviewerRoleId, challengeId2) | ||
| let createdResource | ||
| try { | ||
| createdResource = await service.createResource(user.phead, entity) | ||
| should.equal(createdResource.roleId, entity.roleId) | ||
| should.equal(createdResource.memberHandle.toLowerCase(), entity.memberHandle.toLowerCase()) | ||
| await assertResource(createdResource.id, createdResource) | ||
| } finally { | ||
| if (createdResource && createdResource.id) { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [ |
||
| await prisma.resource.deleteMany({ | ||
| where: { id: createdResource.id } | ||
| }) | ||
| } | ||
| await ResourceRoleService.updateResourceRole(user.admin, copilotRoleId, { | ||
| name: originalRole.name, | ||
| fullReadAccess: originalRole.fullReadAccess, | ||
| fullWriteAccess: originalRole.fullWriteAccess, | ||
| isActive: originalRole.isActive, | ||
| selfObtainable: originalRole.selfObtainable | ||
| }) | ||
| } | ||
| }) | ||
|
|
||
| it('create resource for user ghostar 1', async () => { | ||
| const entity = resources.createBody('ghostar', reviewerRoleId, challengeId2) | ||
| const ret = await service.createResource(user.m2m, entity) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[⚠️
maintainability]The caching mechanism for
restrictedRoleIdsCachedoes not account for changes in the database. If roles are updated externally, the cache might become stale. Consider implementing a cache invalidation strategy or a mechanism to refresh the cache periodically.