import 'server-only'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; import { randomBytes } from 'node:crypto'; import { db } from './db'; export { hashPassword, verifyPassword } from '@/lib/password'; export const SESSION_COOKIE = 'w4c_session'; const TTL_MS = 30 * 24 * 60 * 60 * 1000; export type SessionUser = { id: string; email: string; name: string | null; role: string; }; /** Create a session row and set the httpOnly cookie (works in Route Handlers and Server Actions). */ export async function createSession(userId: string): Promise { const token = randomBytes(32).toString('hex'); const expiresAt = new Date(Date.now() + TTL_MS); await db.session.create({ data: { token, userId, expiresAt } }); const store = await cookies(); store.set(SESSION_COOKIE, token, { httpOnly: true, sameSite: 'lax', secure: process.env.NODE_ENV === 'production', path: '/', expires: expiresAt, }); return token; } export async function destroySession(): Promise { const store = await cookies(); const token = store.get(SESSION_COOKIE)?.value; if (token) await db.session.deleteMany({ where: { token } }); store.delete(SESSION_COOKIE); } export async function getCurrentUser(): Promise { const store = await cookies(); const token = store.get(SESSION_COOKIE)?.value; if (!token) return null; const session = await db.session.findUnique({ where: { token }, include: { user: true } }); if (!session || session.expiresAt < new Date()) return null; const { id, email, name, role } = session.user; return { id, email, name, role }; } /** Page guard: redirect to /login when unauthenticated. */ export async function requireUser(): Promise { const user = await getCurrentUser(); if (!user) redirect('/login'); return user; } /** Page guard: require the admin role. */ export async function requireAdmin(): Promise { const user = await requireUser(); if (user.role !== 'admin') redirect('/dashboard'); return user; }