27 lines
983 B
TypeScript
27 lines
983 B
TypeScript
/**
|
|
* Admin allowlist (Session 18).
|
|
*
|
|
* Server-side check ONLY. The client-side `useAuth()` redirect on
|
|
* `/admin` is for UX (so non-admins don't see a 401 screen) — the
|
|
* security boundary lives in `/api/admin/stats/route.ts`, which calls
|
|
* this helper against the bearer token's email before returning any
|
|
* data. Anyone can spoof a client-side check; they can't spoof the
|
|
* Supabase token verification on the server.
|
|
*
|
|
* To add an admin: append their email here. Lowercase. The check is
|
|
* case-insensitive on inputs but the registry is canonical.
|
|
*/
|
|
|
|
const ADMIN_EMAILS: ReadonlySet<string> = new Set([
|
|
'kevdevelops@gmail.com',
|
|
]);
|
|
|
|
export function isAdmin(email: string | null | undefined): boolean {
|
|
if (!email) return false;
|
|
return ADMIN_EMAILS.has(String(email).trim().toLowerCase());
|
|
}
|
|
|
|
// Exported for tests + the rare debug page that wants to show how
|
|
// many admins are configured without enumerating them.
|
|
export const adminCount = ADMIN_EMAILS.size;
|