@@ -16,7 +16,20 @@ const prisma = require('../common/prisma').getClient()
1616
1717const payloadFields = [ 'id' , 'challengeId' , 'memberId' , 'memberHandle' , 'roleId' , 'phaseChangeNotifications' , 'created' , 'createdBy' , 'updated' , 'updatedBy' ]
1818
19+ // Restricted roles that cannot be combined with submitter role
20+ const RESTRICTED_ROLE_NAMES = [
21+ 'manager' ,
22+ 'copilot' ,
23+ 'reviewer' ,
24+ 'iterative reviewer' ,
25+ 'screener' ,
26+ 'checkpoint screener' ,
27+ 'checkpoint reviewer' ,
28+ 'approver'
29+ ]
30+
1931let copilotResourceRoleIdsCache
32+ let restrictedRoleIdsCache
2033
2134async function getCopilotResourceRoleIds ( ) {
2235 if ( copilotResourceRoleIdsCache ) {
@@ -34,6 +47,31 @@ async function getCopilotResourceRoleIds () {
3447 return copilotResourceRoleIdsCache
3548}
3649
50+ /**
51+ * Get resource role IDs that are restricted from being combined with submitter role.
52+ * These include: Manager, Copilot, Reviewer, Iterative Reviewer, Screener,
53+ * Checkpoint Screener, Checkpoint Reviewer, and Approver.
54+ * @returns {Promise<Array<String>> } Array of restricted role IDs
55+ */
56+ async function getRestrictedRoleIds ( ) {
57+ if ( restrictedRoleIdsCache ) {
58+ return restrictedRoleIdsCache
59+ }
60+ const roles = await prisma . resourceRole . findMany ( {
61+ where : {
62+ nameLower : {
63+ in : RESTRICTED_ROLE_NAMES
64+ }
65+ } ,
66+ select : {
67+ id : true ,
68+ nameLower : true
69+ }
70+ } )
71+ restrictedRoleIdsCache = roles . map ( role => role . id )
72+ return restrictedRoleIdsCache
73+ }
74+
3775/**
3876 * Check whether the user can access resources
3977 * @param {Array } resources resources of current user for specified challenge id
@@ -291,6 +329,12 @@ async function init (currentUser, challengeId, resource, isCreated) {
291329 const { memberId, email } = memberInfoFromDb
292330 handle = memberInfoFromDb . handle
293331 const userResources = allResources . filter ( ( r ) => _ . toLower ( r . memberHandle ) === _ . toLower ( handle ) )
332+
333+ let restrictedRoleIds
334+ if ( isCreated ) {
335+ restrictedRoleIds = await getRestrictedRoleIds ( )
336+ }
337+
294338 // Retrieve the constraint - Allowed Registrants
295339 if ( isCreated && resource . roleId === config . SUBMITTER_RESOURCE_ROLE_ID ) {
296340 const allowedRegistrants = _ . get ( challenge , 'constraints.allowedRegistrants' )
@@ -307,12 +351,20 @@ async function init (currentUser, challengeId, resource, isCreated) {
307351 `User ${ handle } is not allowed to register.`
308352 )
309353 }
310- if ( ! _ . get ( challenge , 'task.isTask' , false ) && ( _ . toLower ( challenge . createdBy ) === _ . toLower ( handle ) ||
311- _ . some ( userResources , r => r . roleId === config . REVIEWER_RESOURCE_ROLE_ID || r . roleId === config . ITERATIVE_REVIEWER_RESOURCE_ROLE_ID ) ) ) {
354+ // Prevent challenge creator from registering as submitter (for non-tasks)
355+ if ( ! _ . get ( challenge , 'task.isTask' , false ) && _ . toLower ( challenge . createdBy ) === _ . toLower ( memberId ) ) {
312356 throw new errors . BadRequestError (
313357 `User ${ handle } is not allowed to register.`
314358 )
315359 }
360+ // Check if user already has a restricted role (Manager, Copilot, Reviewer, etc.)
361+ const existingRestrictedRole = _ . find ( userResources , r => restrictedRoleIds . includes ( r . roleId ) )
362+ if ( existingRestrictedRole ) {
363+ const roleNamesList = RESTRICTED_ROLE_NAMES . slice ( 0 , - 1 ) . join ( ', ' ) + ', or ' + RESTRICTED_ROLE_NAMES . slice ( - 1 )
364+ throw new errors . BadRequestError (
365+ `User ${ handle } is already assigned a restricted role (${ roleNamesList } ) and cannot be registered as a submitter.`
366+ )
367+ }
316368 }
317369
318370 // Prevent from creating more than 1 submitter resources on tasks
@@ -344,6 +396,18 @@ async function init (currentUser, challengeId, resource, isCreated) {
344396 // ensure resource role existed
345397 const resourceRole = await getResourceRole ( resource . roleId , isCreated )
346398
399+ // Check if user is trying to assign a restricted role and already has submitter role
400+ if ( isCreated ) {
401+ if ( restrictedRoleIds . includes ( resource . roleId ) ) {
402+ const existingSubmitterRole = _ . find ( userResources , r => r . roleId === config . SUBMITTER_RESOURCE_ROLE_ID )
403+ if ( existingSubmitterRole ) {
404+ throw new errors . BadRequestError (
405+ `User ${ handle } is already registered as a submitter and cannot be assigned a ${ resourceRole . name } role.`
406+ )
407+ }
408+ }
409+ }
410+
347411 // Verify the member has agreed to the challenge terms
348412 if ( isCreated ) {
349413 await helper . checkAgreedTerms ( memberId , _ . filter ( _ . get ( challenge , 'terms' , [ ] ) , t => t . roleId === resourceRole . id ) )
0 commit comments