import { createHash, randomUUID } from 'node:crypto' import { parseCookies } from './helpers.js' const ADMIN_SESSION_COOKIE = 'vbn_admin_session' const ADMIN_SESSION_TTL_MS = 7 * 24 * 60 * 60 * 1000 const ADMIN_PASSWORD = process.env.ADMIN_PASSWORD const adminSessions = new Map() function cookieFlags() { return process.env.NODE_ENV === 'production' ? '; Secure' : '' } export function sha256(value) { return createHash('sha256').update(String(value)).digest('hex') } export function isAdminPasswordConfigured() { return Boolean(ADMIN_PASSWORD) } export function validateAdminPasswordSetup() { if (!isAdminPasswordConfigured() && process.env.NODE_ENV === 'production') { throw new Error('ADMIN_PASSWORD is required in production.') } if (!isAdminPasswordConfigured()) { console.warn('ADMIN_PASSWORD is not configured; admin routes will remain disabled until the environment is configured.') } } export function isAdminPasswordValid(password) { if (!isAdminPasswordConfigured()) return false return sha256(password) === sha256(ADMIN_PASSWORD) } export function createAdminSession() { const token = randomUUID() adminSessions.set(token, Date.now() + ADMIN_SESSION_TTL_MS) return token } export function deleteAdminSession(token) { if (token) { adminSessions.delete(token) } } export function isValidAdminSession(req) { if (!isAdminPasswordConfigured()) return false const cookies = parseCookies(req.headers.cookie) const sessionToken = cookies[ADMIN_SESSION_COOKIE] if (!sessionToken) return false const expiresAt = adminSessions.get(sessionToken) if (!expiresAt || expiresAt <= Date.now()) { adminSessions.delete(sessionToken) return false } adminSessions.set(sessionToken, Date.now() + ADMIN_SESSION_TTL_MS) return true } export function setAdminSessionCookie(res, token) { res.append( 'Set-Cookie', `${ADMIN_SESSION_COOKIE}=${encodeURIComponent(token)}; Max-Age=${Math.floor(ADMIN_SESSION_TTL_MS / 1000)}; Path=/; HttpOnly; SameSite=Lax${cookieFlags()}`, ) } export function clearAdminSessionCookie(res) { res.append( 'Set-Cookie', `${ADMIN_SESSION_COOKIE}=; Max-Age=0; Path=/; HttpOnly; SameSite=Lax${cookieFlags()}`, ) } export function requireAdminAuth(req, res, next) { if (!isValidAdminSession(req)) { res.status(401).json({ message: 'Unauthorized' }) return } next() }