import {requireAppAccess} from '../admin/admin.middleware.js'; /** * This file is the ONLY place in the feedback module that knows how admin * authentication works. No route handler and no service outside this file may * read session headers or resolve a user itself. * * Today: the shared admin identity in `src/models/admin/`. A session cookie * set by /admin/auth on admin.nachklang.art, plus a `feedback` permission on * the account. Both are re-checked on every request, so disabling a user or * taking their feedback permission away takes effect immediately. * * Before 2026-09-06 this was a header session against the calendar users * table, and any activated @nachklang.art account could administer feedback. * That is why the swap is a one-line binding: everything downstream only ever * saw `requireAdminAuth` and `res.locals.admin`, and both still mean what * they meant. What changed is that access is now granted per user rather than * implied by having an account. * * Explicitly forbidden: accepting session credentials from query parameters, * even "temporarily". That is the exact mistake documented in * DEFERRED_SECURITY.md item 1 for the Calendar domain, where credentials end * up in access logs, browser history, proxy logs, and Referer headers. */ // The only thing the rest of the feedback module knows about an admin. The // shared middleware puts a superset of this on res.locals.admin. export interface AdminIdentity { id: string; email: string; displayName: string; } // Express middleware used by every admin route. On success: // res.locals.admin = AdminAccess (an AdminIdentity plus permissions), calls // next(). On failure: 401 when not signed in, 403 when signed in without the // feedback permission. export const requireAdminAuth = requireAppAccess('feedback');