/** * Authorisation for React server actions. * * A server action POSTs to the URL of the page it sits on, so the edge * middleware cannot tell a form that changes the shop's hours from a form that * signs someone out. It therefore only authenticates page requests, and every * action that writes states its own requirement here. */ import { auth } from './index'; import type { Role } from './roles'; import { canWrite } from './roles'; export type Caller = { email: string; role: Role }; export type ActionResult = { ok: true; value: T } | { ok: false; error: string }; export async function currentCaller(): Promise { const session = await auth(); if (!session?.user) { return null; } return { // The subject is the e-mail address, which is what the audit trail records. email: session.user.email ?? 'inconnu', role: session.user.role, }; } /** * Resolves the caller, or an error to show the user. * * Returns rather than throws: an action that throws renders the Next error * overlay, and "you do not have permission" is a normal outcome, not a crash. */ export async function requireAdmin(): Promise> { const caller = await currentCaller(); if (!caller) { return { ok: false, error: 'Session expirée. Reconnectez-vous.' }; } if (!canWrite(caller.role)) { return { ok: false, error: `Ce compte est en lecture seule. Demandez à être ajouté au groupe d’administration.`, }; } return { ok: true, value: caller }; }