From 4c7ca7db0667a6de01a51af7efc38e50c95f0a27 Mon Sep 17 00:00:00 2001 From: sk1982 Date: Wed, 20 Mar 2024 18:53:04 -0400 Subject: [PATCH] auth: fetch new user data on session --- src/auth.ts | 61 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/auth.ts b/src/auth.ts index 6d487ae..19bf802 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,18 +1,30 @@ import NextAuth from 'next-auth'; import CredentialsProvider from 'next-auth/providers/credentials'; -import { db } from '@/db'; +import { db, GeneratedDB } from '@/db'; import bcrypt from 'bcrypt'; import { DBUserPayload } from '@/types/user'; +import React from 'react'; +import { SelectQueryBuilder } from 'kysely'; +import { AimeUser } from '@/types/db'; let basePath = process.env.BASE_PATH ?? ''; if (basePath.endsWith('/')) basePath = basePath.slice(0, -1); -export const { - handlers: { GET, POST }, - auth, - signIn, - signOut -} = NextAuth({ +const selectUserProps = (builder: SelectQueryBuilder) => builder.leftJoin( + eb => eb.selectFrom('chuni_profile_data as chuni') + .where(({ eb, selectFrom }) => eb('chuni.version', '=', selectFrom('chuni_static_music') + .select(({ fn }) => fn.max('version').as('latest')))) + .selectAll() + .as('chuni'), + join => join.onRef('chuni.user', '=', 'u.id')) + .select(({ fn }) => [ + 'u.username', 'u.password', 'u.id', 'u.email', 'u.permissions', 'u.created_date', 'u.last_login_date', + 'u.suspend_expire_time', + fn('not isnull', ['chuni.id']).as('chuni') + ]) + .executeTakeFirst(); + +const nextAuth = NextAuth({ pages: { signIn: `${basePath}/auth/login` }, @@ -22,8 +34,16 @@ export const { }, trustHost: true, callbacks: { - jwt({ token, user }) { + async jwt({ token, user }) { token.user ??= user; + const dbUser = await selectUserProps(db.selectFrom('aime_user as u') + .where('u.id', '=', (token.user as any).id)); + + if (dbUser) { + const { password, ...payload } = dbUser; + token.user = { ...(token.user as any), ...payload }; + } + return token; }, session({ session, token, user }) { @@ -41,22 +61,9 @@ export const { if (typeof username !== 'string' || typeof password !== 'string') return null; - const user = await db.selectFrom('aime_user as u') + const user = await selectUserProps(db.selectFrom('aime_user as u') .where(({ eb, fn }) => - eb(fn('lower', ['u.username']), '=', username.toLowerCase().trim())) - .leftJoin( - eb => eb.selectFrom('chuni_profile_data as chuni') - .where(({ eb, selectFrom }) => eb('chuni.version', '=', selectFrom('chuni_static_music') - .select(({ fn }) => fn.max('version').as('latest')))) - .selectAll() - .as('chuni'), - join => join.onRef('chuni.user', '=', 'u.id')) - .select(({ fn }) => [ - 'u.username', 'u.password', 'u.id', 'u.email', 'u.permissions', 'u.created_date', 'u.last_login_date', - 'u.suspend_expire_time', - fn('not isnull', ['chuni.id']).as('chuni') - ]) - .executeTakeFirst(); + eb(fn('lower', ['u.username']), '=', username.toLowerCase().trim()))); if (!user?.password || !await bcrypt.compare(password.trim(), user.password)) return null; @@ -67,3 +74,11 @@ export const { } })] }); + +export const auth = React.cache(nextAuth.auth); + +export const { + handlers: { GET, POST }, + signIn, + signOut +} = nextAuth;