import { prisma } from "@formbricks/database"; import { ZId } from "@formbricks/types/v1/environment"; import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/v1/errors"; import { TMembership, TMembershipRole, ZMembershipRole } from "@formbricks/types/v1/memberships"; import { TProfile, TProfileUpdateInput, ZProfileUpdateInput } from "@formbricks/types/v1/profile"; import { MembershipRole, Prisma } from "@prisma/client"; import { cache } from "react"; import { validateInputs } from "../utils/validate"; import { deleteTeam } from "./team"; const responseSelection = { id: true, name: true, email: true, createdAt: true, updatedAt: true, onboardingCompleted: true, }; // function to retrive basic information about a user's profile export const getProfile = cache(async (userId: string): Promise => { validateInputs([userId, ZId]); try { const profile = await prisma.user.findUnique({ where: { id: userId, }, select: responseSelection, }); if (!profile) { return null; } return profile; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError("Database operation failed"); } throw error; } }); const updateUserMembership = async (teamId: string, userId: string, role: TMembershipRole) => { validateInputs([teamId, ZId], [userId, ZId], [role, ZMembershipRole]); await prisma.membership.update({ where: { userId_teamId: { userId, teamId, }, }, data: { role, }, }); }; const getAdminMemberships = (memberships: TMembership[]): TMembership[] => memberships.filter((membership) => membership.role === MembershipRole.admin); // function to update a user's profile export const updateProfile = async ( personId: string, data: Partial ): Promise => { validateInputs([personId, ZId], [data, ZProfileUpdateInput.partial()]); try { const updatedProfile = await prisma.user.update({ where: { id: personId, }, data: data, }); return updatedProfile; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2016") { throw new ResourceNotFoundError("Profile", personId); } else { throw error; // Re-throw any other errors } } }; const deleteUser = async (userId: string) => { validateInputs([userId, ZId]); await prisma.user.delete({ where: { id: userId, }, }); }; // function to delete a user's profile including teams export const deleteProfile = async (personId: string): Promise => { validateInputs([personId, ZId]); try { const currentUserMemberships = await prisma.membership.findMany({ where: { userId: personId, }, include: { team: { select: { id: true, name: true, memberships: true, }, }, }, }); for (const currentUserMembership of currentUserMemberships) { const teamMemberships = currentUserMembership.team.memberships; const role = currentUserMembership.role; const teamId = currentUserMembership.teamId; const teamAdminMemberships = getAdminMemberships(teamMemberships); const teamHasAtLeastOneAdmin = teamAdminMemberships.length > 0; const teamHasOnlyOneMember = teamMemberships.length === 1; const currentUserIsTeamOwner = role === MembershipRole.owner; if (teamHasOnlyOneMember) { await deleteTeam(teamId); } else if (currentUserIsTeamOwner && teamHasAtLeastOneAdmin) { const firstAdmin = teamAdminMemberships[0]; await updateUserMembership(teamId, firstAdmin.userId, MembershipRole.owner); } else if (currentUserIsTeamOwner) { await deleteTeam(teamId); } } await deleteUser(personId); } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError("Database operation failed"); } throw error; } }; export async function getUserIdFromEnvironment(environmentId: string) { const environment = await prisma.environment.findUnique({ where: { id: environmentId }, select: { product: { select: { team: { select: { memberships: { select: { user: { select: { id: true, }, }, }, }, }, }, }, }, }, }); return environment?.product.team.memberships[0].user.id; }