diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/actions.ts b/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/actions.ts index 78a2ac3151..5080854aa1 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/actions.ts +++ b/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/actions.ts @@ -3,6 +3,7 @@ import { deleteMembership, getMembershipsByUserId, + getOrganizationOwnerCount, } from "@/app/(app)/environments/[environmentId]/settings/(organization)/general/lib/membership"; import { authenticatedActionClient } from "@/lib/utils/action-client"; import { checkAuthorizationUpdated } from "@/lib/utils/action-client-middleware"; @@ -94,16 +95,23 @@ export const deleteMembershipAction = authenticatedActionClient throw new AuthenticationError("You cannot delete yourself from the organization"); } - const membership = await getMembershipByUserIdOrganizationId(ctx.user.id, parsedInput.organizationId); + const membership = await getMembershipByUserIdOrganizationId( + parsedInput.userId, + parsedInput.organizationId + ); if (!membership) { throw new AuthenticationError("Not a member of this organization"); } - const memberships = await getMembershipsByUserId(ctx.user.id); - const isLastOwner = memberships?.filter((m) => m.role === "owner").length === 1; - if (membership.role === "owner" && isLastOwner) { - throw new ValidationError("You cannot delete the last owner of the organization"); + const isOwner = membership.role === "owner"; + + if (isOwner) { + const ownerCount = await getOrganizationOwnerCount(parsedInput.organizationId); + + if (ownerCount <= 1) { + throw new ValidationError("You cannot delete the last owner of the organization"); + } } return await deleteMembership(parsedInput.userId, parsedInput.organizationId); diff --git a/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/lib/membership.ts b/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/lib/membership.ts index f840985382..2775aa2f65 100644 --- a/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/lib/membership.ts +++ b/apps/web/app/(app)/environments/[environmentId]/settings/(organization)/general/lib/membership.ts @@ -12,6 +12,36 @@ import { ZOptionalNumber, ZString } from "@formbricks/types/common"; import { DatabaseError, UnknownError } from "@formbricks/types/errors"; import { TMember, TMembership } from "@formbricks/types/memberships"; +export const getOrganizationOwnerCount = reactCache( + async (organizationId: string): Promise => + cache( + async () => { + validateInputs([organizationId, ZString]); + + try { + const ownersCount = await prisma.membership.count({ + where: { + organizationId, + role: "owner", + }, + }); + + return ownersCount; + } catch (error) { + if (error instanceof Prisma.PrismaClientKnownRequestError) { + throw new DatabaseError(error.message); + } + + throw error; + } + }, + [`getOrganizationOwnerCount-${organizationId}`], + { + tags: [membershipCache.tag.byOrganizationId(organizationId)], + } + )() +); + export const getMembersByOrganizationId = reactCache( async (organizationId: string, page?: number): Promise => cache(