/* eslint-disable @typescript-eslint/no-explicit-any */ import { prisma } from '@/server/lib/prisma' import { jwt as jwtPlugin, type JWTPayloadSpec } from '@elysiajs/jwt' import Elysia, { t, type Cookie, type HTTPHeaders, type StatusMap } from 'elysia' import { type ElysiaCookie } from 'elysia/cookies' const secret = process.env.JWT_SECRET if (!secret) { throw new Error('Missing JWT_SECRET in environment variables') } const isProd = process.env.NODE_ENV === 'production' const NINETY_YEARS = 60 * 60 * 24 * 365 * 90 type JWT = { sign(data: Record & JWTPayloadSpec): Promise verify( jwt?: string ): Promise & JWTPayloadSpec)> } type COOKIE = Record> type SET = { headers: HTTPHeaders status?: number | keyof StatusMap redirect?: string cookie?: Record } async function issueToken({ jwt, cookie, userId, role, expiresAt, }: { jwt: JWT cookie: COOKIE userId: string role: 'host' | 'user' expiresAt: number }) { const token = await jwt.sign({ sub: userId, aud: role, exp: expiresAt, }) cookie.token?.set({ value: token, httpOnly: true, secure: isProd, // aktifkan hanya di production (HTTPS) sameSite: 'strict', maxAge: NINETY_YEARS, path: '/', }) return token } async function login({ body, cookie, set, jwt, }: { body: { email: string; password: string } cookie: COOKIE set: SET jwt: JWT }) { try { const { email, password } = body const user = await prisma.user.findUnique({ where: { email }, select: { id: true, password: true, Role: { select: { permissions: true } } } }) if (!user) { set.status = 401 return { message: 'User not found' } } if (user.password !== password) { set.status = 401 return { message: 'Invalid password' } } const rawPermissions = user.Role?.permissions; const akses = Array.isArray(rawPermissions) ? rawPermissions[0]?.toString() : undefined; const token = await issueToken({ jwt, cookie, userId: user.id, role: 'user', expiresAt: Math.floor(Date.now() / 1000) + NINETY_YEARS, }) return { token, akses } } catch (error) { console.error('Error logging in:', error) return { message: 'Login failed', error: error instanceof Error ? error.message : JSON.stringify(error ?? null), } } } const Auth = new Elysia({ prefix: '/auth', tags: ["auth"], }) .use( jwtPlugin({ name: 'jwt', secret, }) ) .post( '/login', async ({ jwt, body, cookie, set }) => { return await login({ jwt: jwt as JWT, body, cookie: cookie as any, set: set as any, }) }, { body: t.Object({ email: t.String(), password: t.String(), }), detail: { summary: 'login', description: 'Login with phone; auto-register if not found', }, } ) .delete( '/logout', ({ cookie }) => { cookie.token?.remove() return { message: 'Logout successful' } }, { detail: { summary: 'logout', description: 'Logout (clear token cookie)', }, } ) export default Auth