import { deleteDomain } from "@calcom/lib/domainManager/organization"; import logger from "@calcom/lib/logger"; import { prisma } from "@calcom/prisma"; import { RedirectType } from "@calcom/prisma/enums"; import { TRPCError } from "@trpc/server"; import type { TrpcSessionUser } from "../../../trpc"; import type { TAdminDeleteInput } from "./adminDelete.schema"; const log = logger.getSubLogger({ prefix: ["organizations/adminDelete"] }); type AdminDeleteOption = { ctx: { user: NonNullable; }; input: TAdminDeleteInput; }; export const adminDeleteHandler = async ({ input }: AdminDeleteOption) => { const foundOrg = await prisma.team.findUnique({ where: { id: input.orgId, isOrganization: true, }, include: { members: { select: { user: true, }, }, }, }); if (!foundOrg) throw new TRPCError({ code: "FORBIDDEN", message: "Organization not found", }); if (foundOrg.slug) { try { await deleteDomain(foundOrg.slug); } catch (e) { log.error(`Failed to delete domain ${foundOrg.slug}. Do a manual deletion if needed`); } } await deleteAllRedirectsForUsers(foundOrg.members.map((member) => member.user)); await renameUsersToAvoidUsernameConflicts(foundOrg.members.map((member) => member.user)); await prisma.team.delete({ where: { id: input.orgId, }, }); return { ok: true, message: `Organization ${foundOrg.name} deleted.`, }; }; export default adminDeleteHandler; async function renameUsersToAvoidUsernameConflicts(users: { id: number; username: string | null }[]) { for (const user of users) { let currentUsername = user.username; if (!currentUsername) { currentUsername = "no-username"; log.warn(`User ${user.id} has no username, defaulting to ${currentUsername}`); } await prisma.user.update({ where: { id: user.id, }, data: { // user.id being auto-incremented, we can safely assume that the username will be unique username: `${currentUsername}-${user.id}`, }, }); } } async function deleteAllRedirectsForUsers(users: { username: string | null }[]) { return await Promise.all( users .filter( ( user ): user is { username: string; } => !!user.username ) .map((user) => prisma.tempOrgRedirect.deleteMany({ where: { from: user.username, type: RedirectType.User, fromOrgId: 0, }, }) ) ); }