diff --git a/apps/web/pages/settings/my-account/profile.tsx b/apps/web/pages/settings/my-account/profile.tsx index 6bd871bf7c..30f880798c 100644 --- a/apps/web/pages/settings/my-account/profile.tsx +++ b/apps/web/pages/settings/my-account/profile.tsx @@ -106,8 +106,17 @@ const ProfileView = () => { setConfirmAuthEmailChangeWarningDialogOpen(false); setTempFormValues(null); }, - onError: () => { - showToast(t("error_updating_settings"), "error"); + onError: (e) => { + switch (e.message) { + // TODO: Add error codes. + case "email_already_used": + { + showToast(t(e.message), "error"); + } + return; + default: + showToast(t("error_updating_settings"), "error"); + } }, }); diff --git a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts index c4f39f54de..8158dd0c69 100644 --- a/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts +++ b/packages/trpc/server/routers/loggedInViewer/updateProfile.handler.ts @@ -1,4 +1,4 @@ -import type { Prisma } from "@prisma/client"; +import { Prisma } from "@prisma/client"; import type { GetServerSidePropsContext, NextApiResponse } from "next"; import { v4 as uuidv4 } from "uuid"; @@ -6,6 +6,7 @@ import stripe from "@calcom/app-store/stripepayment/lib/server"; import { getPremiumMonthlyPlanPriceId } from "@calcom/app-store/stripepayment/lib/utils"; import { passwordResetRequest } from "@calcom/features/auth/lib/passwordResetRequest"; import hasKeyInMetadata from "@calcom/lib/hasKeyInMetadata"; +import { HttpError } from "@calcom/lib/http-error"; import logger from "@calcom/lib/logger"; import { getTranslation } from "@calcom/lib/server"; import { checkUsername } from "@calcom/lib/server/checkUsername"; @@ -159,11 +160,7 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) data.avatar = null; } - const updatedUser = await prisma.user.update({ - where: { - id: user.id, - }, - data, + const updatedUserSelect = Prisma.validator()({ select: { id: true, username: true, @@ -183,6 +180,27 @@ export const updateProfileHandler = async ({ ctx, input }: UpdateProfileOptions) }, }); + let updatedUser: Prisma.UserGetPayload; + + try { + updatedUser = await prisma.user.update({ + where: { + id: user.id, + }, + data, + ...updatedUserSelect, + }); + } catch (e) { + // Catch unique constraint failure on email field. + if (e instanceof Prisma.PrismaClientKnownRequestError && e.code === "P2002") { + const meta = e.meta as { target: string[] }; + if (meta.target.indexOf("email") !== -1) { + throw new HttpError({ statusCode: 409, message: "email_already_used" }); + } + } + throw e; // make sure other errors are rethrown + } + if (user.timeZone !== data.timeZone && updatedUser.schedules.length > 0) { // on timezone change update timezone of default schedule const defaultScheduleId = await getDefaultScheduleId(user.id, prisma);