diff --git a/apps/web/src/auth.ts b/apps/web/src/auth.ts index bd72017d3..e8ec7e085 100644 --- a/apps/web/src/auth.ts +++ b/apps/web/src/auth.ts @@ -24,7 +24,7 @@ import { getValueByPath } from "@/utils/get-value-by-path"; import { decryptToken } from "@/utils/session"; import { CustomPrismaAdapter } from "./auth/custom-prisma-adapter"; -import { mergeGuestsIntoUser, temporarilyMigrateData } from "./auth/merge-user"; +import { mergeGuestsIntoUser } from "./auth/merge-user"; const providers: Provider[] = [ // When a user registers, we don't want to go through the email verification process @@ -170,7 +170,14 @@ if ( const getAuthOptions = (...args: GetServerSessionParams) => ({ - adapter: CustomPrismaAdapter(prisma), + adapter: CustomPrismaAdapter(prisma, { + migrateData: async (userId) => { + const session = await getServerSession(...args); + if (session && session.user.email === null) { + await mergeGuestsIntoUser(userId, [session.user.id]); + } + }, + }), secret: process.env.SECRET_PASSWORD, session: { strategy: "jwt", @@ -238,24 +245,18 @@ const getAuthOptions = (...args: GetServerSessionParams) => if (isUnregisteredUser) { return false; } - } else { + } + + // when we login with a social account for the first time, the user is not created yet + // and the user id will be the same as the provider account id + // we handle this case the the prisma adapter when we link accounts + const isInitialSocialLogin = user.id === profile?.sub; + + if (!isInitialSocialLogin) { // merge guest user into newly logged in user const session = await getServerSession(...args); if (session && session.user.email === null) { - // check if user exists - const count = await prisma.user.count({ - where: { - email: user.email as string, - }, - }); - - if (count !== 0) { - await mergeGuestsIntoUser(user.id, [session.user.id]); - } else { - // when logging in with a social account, the user doesn't exist yet - // so we temporarily migrate the data to a different guest user. - await temporarilyMigrateData(user.id, [session.user.id]); - } + await mergeGuestsIntoUser(user.id, [session.user.id]); } } diff --git a/apps/web/src/auth/custom-prisma-adapter.ts b/apps/web/src/auth/custom-prisma-adapter.ts index a5d8ce87c..f4ebc9e87 100644 --- a/apps/web/src/auth/custom-prisma-adapter.ts +++ b/apps/web/src/auth/custom-prisma-adapter.ts @@ -13,10 +13,14 @@ import { PrismaAdapter } from "@auth/prisma-adapter"; import type { ExtendedPrismaClient, PrismaClient } from "@rallly/database"; import type { Adapter, AdapterAccount } from "next-auth/adapters"; -export function CustomPrismaAdapter(client: ExtendedPrismaClient): Adapter { +export function CustomPrismaAdapter( + client: ExtendedPrismaClient, + options: { migrateData: (userId: string) => Promise }, +): Adapter { return { ...PrismaAdapter(client as PrismaClient), - linkAccount: (data) => { + linkAccount: async (data) => { + await options.migrateData(data.userId); return client.account.create({ data: { userId: data.userId, diff --git a/apps/web/src/auth/merge-user.ts b/apps/web/src/auth/merge-user.ts index ac4405175..00b309950 100644 --- a/apps/web/src/auth/merge-user.ts +++ b/apps/web/src/auth/merge-user.ts @@ -1,88 +1,51 @@ import { prisma } from "@rallly/database"; +import * as Sentry from "@sentry/nextjs"; export const mergeGuestsIntoUser = async ( userId: string, guestIds: string[], ) => { - return await prisma.$transaction(async (tx) => { - await Promise.all([ - tx.poll.updateMany({ - where: { - guestId: { - in: guestIds, + try { + return await prisma.$transaction(async (tx) => { + await Promise.all([ + tx.poll.updateMany({ + where: { + guestId: { + in: guestIds, + }, }, - }, - data: { - guestId: null, - userId: userId, - }, - }), + data: { + guestId: null, + userId: userId, + }, + }), - tx.participant.updateMany({ - where: { - guestId: { - in: guestIds, + tx.participant.updateMany({ + where: { + guestId: { + in: guestIds, + }, }, - }, - data: { - guestId: null, - userId: userId, - }, - }), + data: { + guestId: null, + userId: userId, + }, + }), - tx.comment.updateMany({ - where: { - guestId: { - in: guestIds, + tx.comment.updateMany({ + where: { + guestId: { + in: guestIds, + }, }, - }, - data: { - guestId: null, - userId: userId, - }, - }), - ]); - }); -}; - -export const temporarilyMigrateData = async ( - providerId: string, - guestIds: string[], -) => { - return await prisma.$transaction(async (tx) => { - await Promise.all([ - tx.poll.updateMany({ - where: { - guestId: { - in: guestIds, - }, - }, - data: { - guestId: providerId, - }, - }), - - tx.participant.updateMany({ - where: { - guestId: { - in: guestIds, - }, - }, - data: { - guestId: providerId, - }, - }), - - tx.comment.updateMany({ - where: { - guestId: { - in: guestIds, - }, - }, - data: { - guestId: providerId, - }, - }), - ]); - }); + data: { + guestId: null, + userId: userId, + }, + }), + ]); + }); + } catch (error) { + Sentry.captureException(error); + } };