diff --git a/packages/server/graphql/mutations/archiveTeam.ts b/packages/server/graphql/mutations/archiveTeam.ts index 39970cd9f80..aaa5ec888f6 100644 --- a/packages/server/graphql/mutations/archiveTeam.ts +++ b/packages/server/graphql/mutations/archiveTeam.ts @@ -6,7 +6,7 @@ import NotificationTeamArchived from '../../database/types/NotificationTeamArchi import removeMeetingTemplatesForTeam from '../../postgres/queries/removeMeetingTemplatesForTeam' import safeArchiveTeam from '../../safeMutations/safeArchiveTeam' import {analytics} from '../../utils/analytics/analytics' -import {getUserId, isSuperUser, isTeamLead} from '../../utils/authorization' +import {getUserId, isSuperUser, isTeamLead, isUserOrgAdmin} from '../../utils/authorization' import publish from '../../utils/publish' import standardError from '../../utils/standardError' import {GQLContext} from '../graphql' @@ -35,12 +35,14 @@ export default { // AUTH const viewerId = getUserId(authToken) - const [teamLead, viewer] = await Promise.all([ + const [teamLead, viewer, teamToArchive] = await Promise.all([ isTeamLead(viewerId, teamId, dataLoader), - dataLoader.get('users').loadNonNull(viewerId) + dataLoader.get('users').loadNonNull(viewerId), + dataLoader.get('teams').loadNonNull(teamId) ]) - if (!teamLead && !isSuperUser(authToken)) { - return standardError(new Error('Not team lead'), {userId: viewerId}) + const isOrgAdmin = await isUserOrgAdmin(viewerId, teamToArchive.orgId, dataLoader) + if (!teamLead && !isSuperUser(authToken) && !isOrgAdmin) { + return standardError(new Error('Not team lead or org admin'), {userId: viewerId}) } // RESOLUTION diff --git a/packages/server/graphql/mutations/promoteToTeamLead.ts b/packages/server/graphql/mutations/promoteToTeamLead.ts index 11c03ff7b5d..975346055f1 100644 --- a/packages/server/graphql/mutations/promoteToTeamLead.ts +++ b/packages/server/graphql/mutations/promoteToTeamLead.ts @@ -2,7 +2,7 @@ import {GraphQLID, GraphQLNonNull} from 'graphql' import {SubscriptionChannel} from 'parabol-client/types/constEnums' import TeamMemberId from '../../../client/shared/gqlIds/TeamMemberId' import getRethink from '../../database/rethinkDriver' -import {getUserId, isSuperUser} from '../../utils/authorization' +import {getUserId, isSuperUser, isUserOrgAdmin} from '../../utils/authorization' import publish from '../../utils/publish' import standardError from '../../utils/standardError' import {GQLContext} from '../graphql' @@ -32,18 +32,22 @@ export default { const viewerId = getUserId(authToken) // AUTH - const oldLeadTeamMemberId = await r - .table('TeamMember') - .getAll(teamId, {index: 'teamId'}) - .filter({isNotRemoved: true, isLead: true}) - .nth(0)('id') - .default(null) - .run() + const [oldLeadTeamMemberId, team] = await Promise.all([ + r + .table('TeamMember') + .getAll(teamId, {index: 'teamId'}) + .filter({isNotRemoved: true, isLead: true}) + .nth(0)('id') + .default(null) + .run(), + dataLoader.get('teams').loadNonNull(teamId) + ]) if (!isSuperUser(authToken)) { + const isOrgAdmin = await isUserOrgAdmin(viewerId, team.orgId, dataLoader) const viewerTeamMemberId = TeamMemberId.join(teamId, viewerId) - if (viewerTeamMemberId !== oldLeadTeamMemberId) { - return standardError(new Error('Not team lead'), {userId: viewerId}) + if (viewerTeamMemberId !== oldLeadTeamMemberId && !isOrgAdmin) { + return standardError(new Error('Not team lead or org admin'), {userId: viewerId}) } } diff --git a/packages/server/graphql/mutations/removeTeamMember.ts b/packages/server/graphql/mutations/removeTeamMember.ts index 8c17c71b881..f235589a70a 100644 --- a/packages/server/graphql/mutations/removeTeamMember.ts +++ b/packages/server/graphql/mutations/removeTeamMember.ts @@ -1,7 +1,7 @@ import {GraphQLID, GraphQLNonNull, GraphQLObjectType} from 'graphql' import {SubscriptionChannel} from 'parabol-client/types/constEnums' import fromTeamMemberId from 'parabol-client/utils/relay/fromTeamMemberId' -import {getUserId, isTeamLead} from '../../utils/authorization' +import {getUserId, isTeamLead, isUserOrgAdmin} from '../../utils/authorization' import publish from '../../utils/publish' import standardError from '../../utils/standardError' import {GQLContext} from '../graphql' @@ -30,10 +30,15 @@ export default { // AUTH const viewerId = getUserId(authToken) const {userId, teamId} = fromTeamMemberId(teamMemberId) + const team = await dataLoader.get('teams').loadNonNull(teamId) + const [isOrgAdmin, isViewerTeamLead] = await Promise.all([ + isUserOrgAdmin(viewerId, team.orgId, dataLoader), + isTeamLead(viewerId, teamId, dataLoader) + ]) const isSelf = viewerId === userId if (!isSelf) { - if (!(await isTeamLead(viewerId, teamId, dataLoader))) { - return standardError(new Error('Not team lead'), {userId: viewerId}) + if (!isOrgAdmin && !isViewerTeamLead) { + return standardError(new Error('Not team lead or org admin'), {userId: viewerId}) } }