import { setCookie } from 'h3' import { getDb } from '../../utils/db.js' import { verifyPassword } from '../../utils/password.js' import { getSessionMaxAgeDays } from '../../utils/constants.js' export default defineEventHandler(async (event) => { const body = await readBody(event) const identifier = body?.identifier?.trim() const password = body?.password if (!identifier || typeof password !== 'string') { throw createError({ statusCode: 400, message: 'identifier and password required' }) } const { get, run } = await getDb() const user = await get('SELECT id, identifier, role, password_hash FROM users WHERE identifier = ?', [identifier]) if (!user || !user.password_hash || !verifyPassword(password, user.password_hash)) { throw createError({ statusCode: 401, message: 'Invalid credentials' }) } // Invalidate all existing sessions for this user to prevent session fixation await run('DELETE FROM sessions WHERE user_id = ?', [user.id]) const sessionDays = getSessionMaxAgeDays() const sid = crypto.randomUUID() const now = new Date() const expires = new Date(now.getTime() + sessionDays * 24 * 60 * 60 * 1000) await run( 'INSERT INTO sessions (id, user_id, created_at, expires_at) VALUES (?, ?, ?, ?)', [sid, user.id, now.toISOString(), expires.toISOString()], ) setCookie(event, 'session_id', sid, { httpOnly: true, sameSite: 'strict', path: '/', maxAge: sessionDays * 24 * 60 * 60, secure: process.env.NODE_ENV === 'production', }) return { user: { id: user.id, identifier: user.identifier, role: user.role } } })