From f2ec81b2d0b081def9a0800c568712a84e9fc2b9 Mon Sep 17 00:00:00 2001 From: liuyi Date: Wed, 13 Mar 2024 09:28:52 +0000 Subject: [PATCH] feat(server): user connected accounts migration (#6103) --- .../data/migrations/1710319359062-oauth.ts | 39 +++++++++++++++++++ .../server/src/data/migrations/utils/loop.ts | 13 +++++++ .../server/src/plugins/oauth/controller.ts | 11 +++++- 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 packages/backend/server/src/data/migrations/1710319359062-oauth.ts create mode 100644 packages/backend/server/src/data/migrations/utils/loop.ts diff --git a/packages/backend/server/src/data/migrations/1710319359062-oauth.ts b/packages/backend/server/src/data/migrations/1710319359062-oauth.ts new file mode 100644 index 0000000000..457cdc1f99 --- /dev/null +++ b/packages/backend/server/src/data/migrations/1710319359062-oauth.ts @@ -0,0 +1,39 @@ +import { PrismaClient } from '@prisma/client'; + +import { loop } from './utils/loop'; + +export class Oauth1710319359062 { + // do the migration + static async up(db: PrismaClient) { + await loop(async (skip, take) => { + const oldRecords = await db.deprecatedNextAuthAccount.findMany({ + skip, + take, + orderBy: { + providerAccountId: 'asc', + }, + }); + + await db.connectedAccount.createMany({ + data: oldRecords.map(record => ({ + userId: record.userId, + provider: record.provider, + scope: record.scope, + providerAccountId: record.providerAccountId, + accessToken: record.access_token, + refreshToken: record.refresh_token, + expiresAt: record.expires_at + ? new Date(record.expires_at * 1000) + : null, + })), + }); + + return oldRecords.length; + }, 10); + } + + // revert the migration + static async down(db: PrismaClient) { + await db.connectedAccount.deleteMany({}); + } +} diff --git a/packages/backend/server/src/data/migrations/utils/loop.ts b/packages/backend/server/src/data/migrations/utils/loop.ts new file mode 100644 index 0000000000..2beb886435 --- /dev/null +++ b/packages/backend/server/src/data/migrations/utils/loop.ts @@ -0,0 +1,13 @@ +export async function loop( + batchFn: (skip: number, take: number) => Promise, + chunkSize: number = 100 +) { + let turn = 0; + let last = chunkSize; + + while (last === chunkSize) { + last = await batchFn(chunkSize * turn, chunkSize); + + turn++; + } +} diff --git a/packages/backend/server/src/plugins/oauth/controller.ts b/packages/backend/server/src/plugins/oauth/controller.ts index 29c17c78a1..8be8d69a5a 100644 --- a/packages/backend/server/src/plugins/oauth/controller.ts +++ b/packages/backend/server/src/plugins/oauth/controller.ts @@ -160,8 +160,17 @@ export class OAuthController { } await this.user.fulfillUser(externalAccount.email, { + emailVerifiedAt: new Date(), registered: true, }); + await this.db.connectedAccount.create({ + data: { + userId: user.id, + provider, + providerAccountId: externalAccount.id, + ...tokens, + }, + }); return user; } else { @@ -191,7 +200,7 @@ export class OAuthController { ) { return this.user.createUser({ email: externalAccount.email, - name: 'Unnamed', + name: externalAccount.email.split('@')[0], avatarUrl: externalAccount.avatarUrl, emailVerifiedAt: new Date(), connectedAccounts: {