mirror of
https://github.com/hanzoai/calendar.git
synced 2026-09-24 22:42:24 +00:00
* refactor(teams): improve membership validation for org admins - Add organization scope validation to removeMember handler - Ensure team operations are scoped to users organization context - Update related tests * test(teams): align removeMember tests with updated interface - Add organizationId to test contexts - Add team.findMany mock for org validation - Add test cases for org scope validation * refactor(teams): use TeamRepository for org validation in LegacyRemoveMemberService - Add findByIdsAndOrgId method to TeamRepository - Inject TeamRepository into LegacyRemoveMemberService via constructor - Update RemoveMemberServiceFactory to instantiate and inject TeamRepository - Update tests to mock TeamRepository instead of direct prisma calls Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> --------- Co-authored-by: [email protected] <[email protected]> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
78 lines
1.9 KiB
TypeScript
78 lines
1.9 KiB
TypeScript
import { checkRateLimitAndThrowError } from "@calcom/lib/checkRateLimitAndThrowError";
|
|
|
|
import { TRPCError } from "@trpc/server";
|
|
|
|
import type { TRemoveMemberInputSchema } from "./removeMember.schema";
|
|
import { RemoveMemberServiceFactory } from "./removeMember/RemoveMemberServiceFactory";
|
|
|
|
type RemoveMemberOptions = {
|
|
ctx: {
|
|
user: {
|
|
id: number;
|
|
organizationId: number | null;
|
|
organization?: {
|
|
id: number | null;
|
|
isOrgAdmin: boolean;
|
|
};
|
|
};
|
|
};
|
|
input: TRemoveMemberInputSchema;
|
|
};
|
|
|
|
export const removeMemberHandler = async ({
|
|
ctx: {
|
|
user: { id: userId, organizationId, organization },
|
|
},
|
|
input,
|
|
}: RemoveMemberOptions): Promise<void> => {
|
|
await checkRateLimitAndThrowError({
|
|
identifier: `removeMember.${userId}`,
|
|
});
|
|
|
|
const { memberIds, teamIds, isOrg } = input;
|
|
const isOrgAdmin = organization?.isOrgAdmin ?? false;
|
|
const userOrgId = organizationId ?? organization?.id ?? null;
|
|
|
|
// Note: This assumes that all teams in the request have the same PBAC setting 9999% chance they do.
|
|
const primaryTeamId = teamIds[0];
|
|
if (!primaryTeamId) {
|
|
throw new TRPCError({
|
|
code: "BAD_REQUEST",
|
|
message: "At least one team ID must be provided",
|
|
});
|
|
}
|
|
|
|
// Get the appropriate service based on feature flag
|
|
const service = await RemoveMemberServiceFactory.create(primaryTeamId);
|
|
|
|
const { hasPermission } = await service.checkRemovePermissions({
|
|
userId,
|
|
isOrgAdmin,
|
|
organizationId: userOrgId,
|
|
memberIds,
|
|
teamIds,
|
|
isOrg,
|
|
});
|
|
|
|
if (!hasPermission) {
|
|
throw new TRPCError({ code: "UNAUTHORIZED" });
|
|
}
|
|
|
|
await service.validateRemoval(
|
|
{
|
|
userId,
|
|
isOrgAdmin,
|
|
organizationId: userOrgId,
|
|
memberIds,
|
|
teamIds,
|
|
isOrg,
|
|
},
|
|
hasPermission
|
|
);
|
|
|
|
// Perform the removal
|
|
await service.removeMembers(memberIds, teamIds, isOrg);
|
|
};
|
|
|
|
export default removeMemberHandler;
|