From 703bcd861e6f0bdaaa50ba476b89ddc33365ce7a Mon Sep 17 00:00:00 2001 From: Somay Chauhan Date: Fri, 3 Nov 2023 00:07:19 +0530 Subject: [PATCH] fix: should allow org owners and admins to delete members from subteams (#11710) Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> --- .../ee/teams/components/MemberListItem.tsx | 4 +++- .../features/ee/teams/pages/team-members-view.tsx | 14 +++++++++++--- .../routers/viewer/teams/removeMember.handler.ts | 3 ++- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/features/ee/teams/components/MemberListItem.tsx b/packages/features/ee/teams/components/MemberListItem.tsx index 936732b7dc..2b356747ca 100644 --- a/packages/features/ee/teams/components/MemberListItem.tsx +++ b/packages/features/ee/teams/components/MemberListItem.tsx @@ -37,6 +37,7 @@ import TeamPill, { TeamRole } from "./TeamPill"; interface Props { team: RouterOutputs["viewer"]["teams"]["get"]; member: RouterOutputs["viewer"]["teams"]["get"]["members"][number]; + isOrgAdminOrOwner: boolean | undefined; } /** TODO: Migrate the one in apps/web to tRPC package */ @@ -109,7 +110,8 @@ export default function MemberListItem(props: Props) { (props.member.role !== MembershipRole.OWNER || ownersInTeam() > 1 || props.member.id !== currentUserId)) || - (props.team.membership?.role === MembershipRole.ADMIN && props.member.role !== MembershipRole.OWNER); + (props.team.membership?.role === MembershipRole.ADMIN && props.member.role !== MembershipRole.OWNER) || + props.isOrgAdminOrOwner; const impersonationMode = editMode && !props.member.disableImpersonation && diff --git a/packages/features/ee/teams/pages/team-members-view.tsx b/packages/features/ee/teams/pages/team-members-view.tsx index ca73614763..227c213f08 100644 --- a/packages/features/ee/teams/pages/team-members-view.tsx +++ b/packages/features/ee/teams/pages/team-members-view.tsx @@ -22,13 +22,14 @@ type Team = RouterOutputs["viewer"]["teams"]["get"]; interface MembersListProps { team: Team | undefined; + isOrgAdminOrOwner: boolean | undefined; } const checkIfExist = (comp: string, query: string) => comp.toLowerCase().replace(/\s+/g, "").includes(query.toLowerCase().replace(/\s+/g, "")); function MembersList(props: MembersListProps) { - const { team } = props; + const { team, isOrgAdminOrOwner } = props; const { t } = useLocale(); const [query, setQuery] = useState(""); @@ -56,7 +57,14 @@ function MembersList(props: MembersListProps) { {membersList?.length && team ? ( ) : null} @@ -161,7 +169,7 @@ const MembersView = () => { {((team?.isPrivate && isAdmin) || !team?.isPrivate || isOrgAdminOrOwner) && ( <> - +
)} diff --git a/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts b/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts index 9f9ed4bbb6..96b7b3cc9d 100644 --- a/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts +++ b/packages/trpc/server/routers/viewer/teams/removeMember.handler.ts @@ -23,7 +23,8 @@ export const removeMemberHandler = async ({ ctx, input }: RemoveMemberOptions) = const isOrgAdmin = ctx.user.organizationId ? await isTeamAdmin(ctx.user.id, ctx.user.organizationId) : false; - if (!isAdmin && ctx.user.id !== input.memberId) throw new TRPCError({ code: "UNAUTHORIZED" }); + if (!(isAdmin || isOrgAdmin) && ctx.user.id !== input.memberId) + throw new TRPCError({ code: "UNAUTHORIZED" }); // Only a team owner can remove another team owner. if ((await isTeamOwner(input.memberId, input.teamId)) && !(await isTeamOwner(ctx.user.id, input.teamId))) throw new TRPCError({ code: "UNAUTHORIZED" });