mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-30 10:46:35 +02:00
🐛 Fix issues with merging guest user data (#1478)
This commit is contained in:
parent
f72f713946
commit
00548ab763
3 changed files with 63 additions and 95 deletions
|
@ -24,7 +24,7 @@ import { getValueByPath } from "@/utils/get-value-by-path";
|
||||||
import { decryptToken } from "@/utils/session";
|
import { decryptToken } from "@/utils/session";
|
||||||
|
|
||||||
import { CustomPrismaAdapter } from "./auth/custom-prisma-adapter";
|
import { CustomPrismaAdapter } from "./auth/custom-prisma-adapter";
|
||||||
import { mergeGuestsIntoUser, temporarilyMigrateData } from "./auth/merge-user";
|
import { mergeGuestsIntoUser } from "./auth/merge-user";
|
||||||
|
|
||||||
const providers: Provider[] = [
|
const providers: Provider[] = [
|
||||||
// When a user registers, we don't want to go through the email verification process
|
// When a user registers, we don't want to go through the email verification process
|
||||||
|
@ -170,7 +170,14 @@ if (
|
||||||
|
|
||||||
const getAuthOptions = (...args: GetServerSessionParams) =>
|
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,
|
secret: process.env.SECRET_PASSWORD,
|
||||||
session: {
|
session: {
|
||||||
strategy: "jwt",
|
strategy: "jwt",
|
||||||
|
@ -238,24 +245,18 @@ const getAuthOptions = (...args: GetServerSessionParams) =>
|
||||||
if (isUnregisteredUser) {
|
if (isUnregisteredUser) {
|
||||||
return false;
|
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
|
// merge guest user into newly logged in user
|
||||||
const session = await getServerSession(...args);
|
const session = await getServerSession(...args);
|
||||||
if (session && session.user.email === null) {
|
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]);
|
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]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,10 +13,14 @@ import { PrismaAdapter } from "@auth/prisma-adapter";
|
||||||
import type { ExtendedPrismaClient, PrismaClient } from "@rallly/database";
|
import type { ExtendedPrismaClient, PrismaClient } from "@rallly/database";
|
||||||
import type { Adapter, AdapterAccount } from "next-auth/adapters";
|
import type { Adapter, AdapterAccount } from "next-auth/adapters";
|
||||||
|
|
||||||
export function CustomPrismaAdapter(client: ExtendedPrismaClient): Adapter {
|
export function CustomPrismaAdapter(
|
||||||
|
client: ExtendedPrismaClient,
|
||||||
|
options: { migrateData: (userId: string) => Promise<void> },
|
||||||
|
): Adapter {
|
||||||
return {
|
return {
|
||||||
...PrismaAdapter(client as PrismaClient),
|
...PrismaAdapter(client as PrismaClient),
|
||||||
linkAccount: (data) => {
|
linkAccount: async (data) => {
|
||||||
|
await options.migrateData(data.userId);
|
||||||
return client.account.create({
|
return client.account.create({
|
||||||
data: {
|
data: {
|
||||||
userId: data.userId,
|
userId: data.userId,
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
import { prisma } from "@rallly/database";
|
import { prisma } from "@rallly/database";
|
||||||
|
import * as Sentry from "@sentry/nextjs";
|
||||||
|
|
||||||
export const mergeGuestsIntoUser = async (
|
export const mergeGuestsIntoUser = async (
|
||||||
userId: string,
|
userId: string,
|
||||||
guestIds: string[],
|
guestIds: string[],
|
||||||
) => {
|
) => {
|
||||||
|
try {
|
||||||
return await prisma.$transaction(async (tx) => {
|
return await prisma.$transaction(async (tx) => {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
tx.poll.updateMany({
|
tx.poll.updateMany({
|
||||||
|
@ -43,46 +45,7 @@ export const mergeGuestsIntoUser = async (
|
||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
};
|
} catch (error) {
|
||||||
|
Sentry.captureException(error);
|
||||||
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,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue