import { randomUUID } from 'node:crypto' import type { H3Event } from 'h3' import { deleteCookie, getCookie, getRequestURL, setCookie } from 'h3' import { randomToken } from './base64url' import { getRedisClient } from './redis' const DEFAULT_SESSION_TTL_SECONDS = 60 * 60 * 24 * 7 const SHORT_SESSION_TTL_SECONDS = 60 * 60 * 24 interface StoredSession { id: string userId: string remember: boolean createdAt: string } function getSessionCookieName() { const config = useRuntimeConfig() return config.sessionCookieName || 'dinner_ticket_session' } function getSessionStorageKey(token: string) { return `auth:session:${token}` } function shouldUseSecureCookies(event: H3Event) { const url = getRequestURL(event) return url.protocol === 'https:' } function getSessionTtl(remember: boolean) { return remember ? DEFAULT_SESSION_TTL_SECONDS : SHORT_SESSION_TTL_SECONDS } export async function createUserSession(event: H3Event, input: { userId: string remember: boolean }) { const token = randomToken(32) const session: StoredSession = { id: randomUUID(), userId: input.userId, remember: input.remember, createdAt: new Date().toISOString() } const redis = await getRedisClient() const ttl = getSessionTtl(input.remember) await redis.set(getSessionStorageKey(token), JSON.stringify(session), { expiration: { type: 'EX', value: ttl } }) setCookie(event, getSessionCookieName(), token, { httpOnly: true, sameSite: 'lax', secure: shouldUseSecureCookies(event), path: '/', maxAge: ttl }) return session } export async function getUserSession(event: H3Event): Promise { const token = getCookie(event, getSessionCookieName()) if (!token) { return null } const redis = await getRedisClient() const raw = await redis.get(getSessionStorageKey(token)) if (!raw) { deleteCookie(event, getSessionCookieName(), { path: '/' }) return null } try { return JSON.parse(raw) as StoredSession } catch { await redis.del(getSessionStorageKey(token)) deleteCookie(event, getSessionCookieName(), { path: '/' }) return null } } export async function destroyUserSession(event: H3Event) { const token = getCookie(event, getSessionCookieName()) if (token) { const redis = await getRedisClient() await redis.del(getSessionStorageKey(token)) } deleteCookie(event, getSessionCookieName(), { path: '/' }) }