spb/cancerindex
Public
TypeScript 97.2%
SQL 1.5%
CSS 0.6%
JavaScript 0.5%
1import 'server-only';2import { cookies } from 'next/headers';3import { createHash, timingSafeEqual } from 'node:crypto';45export const ADMIN_COOKIE = 'ci_admin';67function expected(): string | null {8 const t = process.env.ADMIN_TOKEN;9 return t && t.length > 0 ? t : null;10}1112/** Cookie value = sha256(token) so the raw token never sits in the browser. */13export function cookieValueFor(token: string): string {14 return createHash('sha256').update(token).digest('hex');15}1617function safeEqual(a: string, b: string): boolean {18 const ab = Buffer.from(a);19 const bb = Buffer.from(b);20 return ab.length === bb.length && timingSafeEqual(ab, bb);21}2223export function tokenMatches(token: string | null | undefined): boolean {24 const exp = expected();25 return !!exp && !!token && safeEqual(token, exp);26}2728/** True when the request carries a valid admin cookie (§140-141). */29export async function isAdmin(): Promise<boolean> {30 const exp = expected();31 if (!exp) return false;32 const c = (await cookies()).get(ADMIN_COOKIE)?.value;33 return !!c && safeEqual(c, cookieValueFor(exp));34}3536export function adminConfigured(): boolean {37 return expected() != null;38}39