From 5751f0f634bd1e95770cecfc13d0105ed334b0c8 Mon Sep 17 00:00:00 2001 From: Somay Chauhan Date: Tue, 19 Dec 2023 11:40:06 +0530 Subject: [PATCH] fix: join subteam as their respective organization role (#12216) * fix: join subteam as their respective organization role * refactor code * fix: join subteam as their respective organization role * fix: join subteam as their respective organization role for pending members * fix: Set subteam role to admin when updating organization role to admin * refactor: suggested changes and fix type error * fix: type error --- .../organizations/updateUser.handler.ts | 39 +++++++++++++++++++ .../inviteMember/inviteMember.handler.ts | 18 ++++++--- .../viewer/teams/inviteMember/utils.ts | 12 ++++-- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts index 35f17b9435..b83a10c60f 100644 --- a/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts +++ b/packages/trpc/server/routers/viewer/organizations/updateUser.handler.ts @@ -15,6 +15,20 @@ type UpdateUserOptions = { input: TUpdateUserInputSchema; }; +const applyRoleToAllTeams = async (userId: number, teamIds: number[], role: MembershipRole) => { + await prisma.membership.updateMany({ + where: { + userId, + teamId: { + in: teamIds, + }, + }, + data: { + role, + }, + }); +}; + export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => { const { user } = ctx; const { id: userId, organizationId } = user; @@ -35,6 +49,24 @@ export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => { teamId: organizationId, accepted: true, }, + include: { + team: { + include: { + children: { + where: { + members: { + some: { + userId: input.userId, + }, + }, + }, + include: { + members: true, + }, + }, + }, + }, + }, }); if (!requestedMember) @@ -72,6 +104,13 @@ export const updateUserHandler = async ({ ctx, input }: UpdateUserOptions) => { }), ]); + if (input.role === MembershipRole.ADMIN || input.role === MembershipRole.OWNER) { + const teamIds = requestedMember.team.children + .map((sub_team) => sub_team.members.find((item) => item.userId === input.userId)?.teamId) + .filter(Boolean) as number[]; //filter out undefined + + await applyRoleToAllTeams(input.userId, teamIds, input.role); + } // TODO: audit log this return { diff --git a/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts b/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts index 6417c563a6..0d7378c449 100644 --- a/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/inviteMember/inviteMember.handler.ts @@ -117,12 +117,18 @@ export const inviteMemberHandler = async ({ ctx, input }: InviteMemberOptions) = // invited users can autojoin, create their memberships in org if (autoJoinUsers.length) { await prisma.membership.createMany({ - data: autoJoinUsers.map((userToAutoJoin) => ({ - userId: userToAutoJoin.id, - teamId: team.id, - accepted: true, - role: input.role, - })), + data: autoJoinUsers.map((userToAutoJoin) => { + const organizationRole = userToAutoJoin.teams?.[0]?.role; + return { + userId: userToAutoJoin.id, + teamId: team.id, + accepted: true, + role: + organizationRole === MembershipRole.ADMIN || organizationRole === MembershipRole.OWNER + ? organizationRole + : input.role, + }; + }), }); } diff --git a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts index 1279996cb5..696576ef5e 100644 --- a/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts +++ b/packages/trpc/server/routers/viewer/teams/inviteMember/utils.ts @@ -10,7 +10,7 @@ import slugify from "@calcom/lib/slugify"; import { prisma } from "@calcom/prisma"; import type { Membership, Team } from "@calcom/prisma/client"; import { Prisma, type User } from "@calcom/prisma/client"; -import type { MembershipRole } from "@calcom/prisma/enums"; +import { MembershipRole } from "@calcom/prisma/enums"; import { teamMetadataSchema } from "@calcom/prisma/zod-utils"; import { TRPCError } from "@trpc/server"; @@ -25,7 +25,7 @@ export type Invitee = Pick< >; export type UserWithMembership = Invitee & { - teams?: Pick[]; + teams?: Pick[]; }; export async function checkPermissions({ @@ -168,7 +168,7 @@ export async function getUsersToInvite({ completedOnboarding: true, identityProvider: true, teams: { - select: { teamId: true, userId: true, accepted: true }, + select: { teamId: true, userId: true, accepted: true, role: true }, where: { OR: memberships, }, @@ -286,12 +286,16 @@ export async function createProvisionalMemberships({ try { await prisma.membership.createMany({ data: invitees.flatMap((invitee) => { + const organizationRole = invitee?.teams?.[0]?.role; const data = []; // membership for the team data.push({ teamId: input.teamId, userId: invitee.id, - role: input.role as MembershipRole, + role: + organizationRole === MembershipRole.ADMIN || organizationRole === MembershipRole.OWNER + ? organizationRole + : input.role, }); // membership for the org