import useDatabase from '~/composables/useDatabase'; import { schema } from '~/schemas/login'; import type { User, UserExtendedData, UserRawData, UserSession, UserSessionRequired } from '~/types/auth'; import { ZodError } from 'zod'; import { checkSession, logSession } from '~/server/utils/user'; import { usersTable } from '~/db/schema'; import { eq, or, sql } from 'drizzle-orm'; import type { BunSQLiteDatabase } from 'drizzle-orm/bun-sqlite'; interface SuccessHandler { success: true; session: UserSession; } interface ErrorHandler { success: false; error: Error | ZodError<{ usernameOrEmail: string; password: string; }>; } type Return = SuccessHandler | ErrorHandler; export default defineEventHandler(async (e): Promise => { try { const session = await getUserSession(e); const db = useDatabase(); const checkedSession = await checkSession(e, session); if(checkedSession !== undefined) return checkedSession; const body = await readValidatedBody(e, schema.safeParse); if (!body.success) { await clearUserSession(e); setResponseStatus(e, 406); return { success: false, error: body.error }; } const hash = await Bun.password.hash(body.data.password); const id = db.select({ id: usersTable.id, hash: usersTable.hash }).from(usersTable).where(or(eq(usersTable.username, sql.placeholder('username')), eq(usersTable.email, sql.placeholder('username')))).prepare().get({ username: body.data.usernameOrEmail }); if(!id || !id.id || !id.hash) { await clearUserSession(e); setResponseStatus(e, 401); return { success: false, error: new ZodError([{ code: 'custom', path: ['username'], message: 'Identifiant inconnu' }]) }; } const valid = await Bun.password.verify(body.data.password, id.hash); if(!valid) { await clearUserSession(e); setResponseStatus(e, 401); return { success: false, error: new ZodError([{ code: 'custom', path: ['password'], message: 'Mot de passe incorrect' }]) }; } const user = db.query.usersTable.findFirst({ columns: { id: true, email: true, username: true, state: true, }, with: { data: true, permission: true, }, where: (table) => eq(table.id, sql.placeholder('id')) }).prepare().get({ id: id.id }); if(!user) { setResponseStatus(e, 401); return { success: false, error: new Error('Données utilisateur introuvable') }; } const data = logSession(e, await setUserSession(e, { user: { ...user.data, email: user.email, username: user.username, state: user.state, permissions: user.permission.map(e => e.permission), } }) as UserSessionRequired); setResponseStatus(e, 201); return { success: true, session: data }; } catch(err: any) { console.error(err); await clearUserSession(e); return { success: false, error: err as Error }; } });