import "server-only"; import { Prisma } from "@prisma/client"; import { cache as reactCache } from "react"; import { z } from "zod"; import { prisma } from "@formbricks/database"; import { PrismaErrorType } from "@formbricks/database/types/error"; import { ZId } from "@formbricks/types/common"; import { DatabaseError, ResourceNotFoundError } from "@formbricks/types/errors"; import { TUser, TUserLocale, TUserUpdateInput, ZUserUpdateInput } from "@formbricks/types/user"; import { deleteOrganization, getOrganizationsWhereUserIsSingleOwner } from "@/lib/organization/service"; import { deleteBrevoCustomerByEmail } from "@/modules/auth/lib/brevo"; import { validateInputs } from "../utils/validate"; import { publicUserSelect } from "./public-user"; // function to retrive basic information about a user's user export const getUser = reactCache(async (id: string): Promise => { validateInputs([id, ZId]); try { const user = await prisma.user.findUnique({ where: { id, }, select: publicUserSelect, }); if (!user) { return null; } return user; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }); export const getUserByEmail = reactCache(async (email: string): Promise => { validateInputs([email, z.email()]); try { const user = await prisma.user.findFirst({ where: { email, }, select: publicUserSelect, }); return user; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }); // function to update a user's user export const updateUser = async (personId: string, data: TUserUpdateInput): Promise => { validateInputs([personId, ZId], [data, ZUserUpdateInput.partial()]); try { const updatedUser = await prisma.user.update({ where: { id: personId, }, data: data, select: publicUserSelect, }); return updatedUser; } catch (error) { if ( error instanceof Prisma.PrismaClientKnownRequestError && error.code === PrismaErrorType.RecordDoesNotExist ) { throw new ResourceNotFoundError("User", personId); } throw error; // Re-throw any other errors } }; const deleteUserById = async (id: string): Promise => { validateInputs([id, ZId]); try { const user = await prisma.user.delete({ where: { id, }, select: publicUserSelect, }); return user; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }; // function to delete a user's user including organizations export const deleteUser = async (id: string): Promise => { validateInputs([id, ZId]); try { const organizationsWithSingleOwner = await getOrganizationsWhereUserIsSingleOwner(id); for (const organization of organizationsWithSingleOwner) { await deleteOrganization(organization.id); } const deletedUser = await deleteUserById(id); await deleteBrevoCustomerByEmail({ email: deletedUser.email }); return deletedUser; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }; export const getUsersWithOrganization = async (organizationId: string): Promise => { validateInputs([organizationId, ZId]); try { const users = await prisma.user.findMany({ where: { memberships: { some: { organizationId, }, }, }, select: publicUserSelect, }); return users; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } }; export const getUserLocale = reactCache(async (id: string): Promise => { validateInputs([id, ZId]); try { const user = await prisma.user.findUnique({ where: { id, }, select: publicUserSelect, }); if (!user) { return undefined; } return user.locale; } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { throw new DatabaseError(error.message); } throw error; } });