import { defineMiddleware } from 'astro:middleware'; import { getDb } from './lib/db'; import { getSessionUser, SESSION_COOKIE, canAccessPath, landingFor, isProtectedPath } from './lib/auth'; /** * Tutta l'applicazione è riservata: si entra dal /login di quest'app, con gli utenti di * quest'app. ⚠️ Una sessione aperta sul sito (insanitylab.it) qui non vale — cookie diverso, * dominio diverso, database diverso. È la separazione, non un difetto. * * ⚠️ Le rotte /api rispondono con uno stato, non con un redirect: mandare un 302 verso una * pagina di login a chi ha chiesto del JSON produce un 200 con dentro dell'HTML, cioè un * errore che il chiamante scopre provando a leggerlo. */ export const onRequest = defineMiddleware((context, next) => { const { pathname } = context.url; if (!isProtectedPath(pathname)) return next(); const json = (status: number, error: string) => new Response(JSON.stringify({ error }), { status, headers: { 'Content-Type': 'application/json' } }); const token = context.cookies.get(SESSION_COOKIE)?.value; const user = token ? getSessionUser(getDb(), token) : null; if (!user) { if (pathname.startsWith('/api/')) return json(401, 'Non autorizzato'); return context.redirect(`/login?next=${encodeURIComponent(pathname)}`); } if (!canAccessPath(user.role, pathname)) { if (pathname.startsWith('/api/')) return json(403, 'Permessi insufficienti'); // Loggato ma senza i permessi per QUESTA sezione: si torna a casa propria, non si // mostra una porta chiusa a chi una casa ce l'ha. return context.redirect(landingFor(user.role)); } context.locals.user = user; return next(); });