From 768e42c7ff5e2edf7034706b4892fbfed7aacf77 Mon Sep 17 00:00:00 2001 From: Bruce Tian Date: Wed, 17 Apr 2024 11:20:55 -0700 Subject: [PATCH 1/3] feat(orgAdmin): org admin can promote others to org admin --- .../public/mutations/setOrgUserRole.ts | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/server/graphql/public/mutations/setOrgUserRole.ts b/packages/server/graphql/public/mutations/setOrgUserRole.ts index 404eafc82e9..2922671a9ae 100644 --- a/packages/server/graphql/public/mutations/setOrgUserRole.ts +++ b/packages/server/graphql/public/mutations/setOrgUserRole.ts @@ -18,7 +18,7 @@ const addNotifications = async (orgId: string, userId: string) => { const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( _source, - {orgId, userId, role}, + {orgId, userId, role: roleToSet}, {authToken, dataLoader, socketId: mutatorId} ) => { const r = await getRethink() @@ -35,8 +35,8 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( }) } - if (role && role !== 'BILLING_LEADER' && role !== 'ORG_ADMIN') { - return standardError(new Error('Invalid role'), {userId: viewerId}) + if (roleToSet && roleToSet !== 'BILLING_LEADER' && roleToSet !== 'ORG_ADMIN') { + return standardError(new Error('Invalid role to set'), {userId: viewerId}) } const [organizationUser, viewer] = await Promise.all([ @@ -56,10 +56,17 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( }) } - if ((role === 'ORG_ADMIN' || organizationUser.role === 'ORG_ADMIN') && !isSuperUser(authToken)) { - return standardError(new Error('Must be super user to promote/demote user to admin'), { - userId: viewerId - }) + if ( + roleToSet === 'ORG_ADMIN' && + organizationUser.role !== 'ORG_ADMIN' && + !isSuperUser(authToken) + ) { + return standardError( + new Error('Only super user or user who hold org_admin role can promote/demote user to admin'), + { + userId: viewerId + } + ) } // if someone is leaving, make sure there is someone else to take their place @@ -71,7 +78,7 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( .filter((row: RDatum) => r.expr(['BILLING_LEADER', 'ORG_ADMIN']).contains(row('role'))) .count() .run() - if (leaderCount === 1) { + if (leaderCount === 1 && !roleToSet) { return standardError(new Error('You’re the last leader, you can’t give that up'), { userId: viewerId }) @@ -80,23 +87,23 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( // no change required const {id: organizationUserId} = organizationUser - if (organizationUser.role === role) { + if (organizationUser.role === roleToSet) { return { orgId, organizationUserId, notificationIdsAdded: [] } } - await r.table('OrganizationUser').get(organizationUserId).update({role}).run() + await r.table('OrganizationUser').get(organizationUserId).update({role: roleToSet}).run() - if (role !== 'ORG_ADMIN') { - const modificationType = role === 'BILLING_LEADER' ? 'add' : 'remove' + if (roleToSet !== 'ORG_ADMIN') { + const modificationType = roleToSet === 'BILLING_LEADER' ? 'add' : 'remove' analytics.billingLeaderModified(viewer, userId, orgId, modificationType) } // Don't add notification when promoting to org admin. const notificationIdsAdded = - role === 'BILLING_LEADER' ? await addNotifications(orgId, userId) : [] + roleToSet === 'BILLING_LEADER' ? await addNotifications(orgId, userId) : [] const data = {orgId, organizationUserId, notificationIdsAdded} publish(SubscriptionChannel.ORGANIZATION, orgId, 'SetOrgUserRoleSuccess', data, subOptions) From 6746cd19988b2778f08a7ba44a4f771efec17d90 Mon Sep 17 00:00:00 2001 From: Bruce Tian Date: Wed, 17 Apr 2024 11:37:01 -0700 Subject: [PATCH 2/3] Slightly adjust the permission logic --- .../public/mutations/setOrgUserRole.ts | 25 +++++++++++-------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/packages/server/graphql/public/mutations/setOrgUserRole.ts b/packages/server/graphql/public/mutations/setOrgUserRole.ts index 2922671a9ae..fd718b9010a 100644 --- a/packages/server/graphql/public/mutations/setOrgUserRole.ts +++ b/packages/server/graphql/public/mutations/setOrgUserRole.ts @@ -39,7 +39,7 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( return standardError(new Error('Invalid role to set'), {userId: viewerId}) } - const [organizationUser, viewer] = await Promise.all([ + const [organizationUser, viewer, viewerOrgUser] = await Promise.all([ r .table('OrganizationUser') .getAll(userId, {index: 'userId'}) @@ -47,7 +47,14 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( .nth(0) .default(null) .run(), - dataLoader.get('users').loadNonNull(viewerId) + dataLoader.get('users').loadNonNull(viewerId), + r + .table('OrganizationUser') + .getAll(viewerId, {index: 'userId'}) + .filter({orgId, removedAt: null}) + .nth(0) + .default(null) + .run() ]) if (!organizationUser) { @@ -57,16 +64,14 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( } if ( - roleToSet === 'ORG_ADMIN' && - organizationUser.role !== 'ORG_ADMIN' && - !isSuperUser(authToken) + roleToSet === 'ORG_ADMIN' || // promoting someone to ORG_ADMIN + organizationUser.role === 'ORG_ADMIN' // the user is already an ORG_ADMIN so the mutation is intended to change their role ) { - return standardError( - new Error('Only super user or user who hold org_admin role can promote/demote user to admin'), - { + if (!isSuperUser(authToken) && (!viewerOrgUser || viewerOrgUser.role !== 'ORG_ADMIN')) { + return standardError(new Error('Only super user or org admin can perform this action'), { userId: viewerId - } - ) + }) + } } // if someone is leaving, make sure there is someone else to take their place From ac23592138d3f5edc780c88a5ba1ffe2503a2c34 Mon Sep 17 00:00:00 2001 From: Bruce Tian Date: Tue, 23 Apr 2024 08:49:17 -0700 Subject: [PATCH 3/3] tiny fix --- packages/server/graphql/public/mutations/setOrgUserRole.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/graphql/public/mutations/setOrgUserRole.ts b/packages/server/graphql/public/mutations/setOrgUserRole.ts index fd718b9010a..5b6d2bb4fc6 100644 --- a/packages/server/graphql/public/mutations/setOrgUserRole.ts +++ b/packages/server/graphql/public/mutations/setOrgUserRole.ts @@ -67,7 +67,7 @@ const setOrgUserRole: MutationResolvers['setOrgUserRole'] = async ( roleToSet === 'ORG_ADMIN' || // promoting someone to ORG_ADMIN organizationUser.role === 'ORG_ADMIN' // the user is already an ORG_ADMIN so the mutation is intended to change their role ) { - if (!isSuperUser(authToken) && (!viewerOrgUser || viewerOrgUser.role !== 'ORG_ADMIN')) { + if (!isSuperUser(authToken) && viewerOrgUser?.role !== 'ORG_ADMIN') { return standardError(new Error('Only super user or org admin can perform this action'), { userId: viewerId })