import { NextResponse } from 'next/server'; import { auth } from '@/lib/auth'; /** * The single choke point for administrative access. * * Every /admin page and every /api/admin route passes through here, so no * individual page can forget to check. Pages get a redirect to the sign-in * screen; API routes get a status code, because a fetch that receives an HTML * login page is a confusing way to learn you are signed out. * * Write access is enforced here too: a `viewer` may read anything and change * nothing. Doing it at the edge means a read-only account cannot reach a * handler that mutates, whatever that handler remembers to check. * * The device API (/api/setup, /api/display, /api/log) is deliberately outside * this matcher: the panel cannot sign in, and carries its own bearer token. */ export default auth((request) => { const { pathname } = request.nextUrl; const isApi = pathname.startsWith('/api/admin'); const session = request.auth; if (!session?.user) { if (isApi) { return NextResponse.json({ error: 'Non authentifié' }, { status: 401 }); } const target = new URL('/login', request.nextUrl.origin); target.searchParams.set('from', pathname); return NextResponse.redirect(target); } const isRead = request.method === 'GET' || request.method === 'HEAD'; if (!isRead && session.user.role !== 'admin') { return NextResponse.json( { error: 'Compte en lecture seule' }, { status: 403 }, ); } return NextResponse.next(); }); export const config = { matcher: ['/admin/:path*', '/api/admin/:path*'], };