'use server'; import { revalidatePath } from 'next/cache'; import { cookies } from 'next/headers'; import { redirect } from 'next/navigation'; import { ADMIN_COOKIE, ADMIN_COOKIE_MAX_AGE, adminToken, cookieValueFor, isAdminAuthed, verifyToken } from '@/lib/admin-auth'; import { adminApi, adminErrorMessage } from '@/lib/admin-api'; import { routes } from '@/lib/site'; const secure = process.env.NODE_ENV === 'production' && (process.env.NEXT_PUBLIC_SITE_URL ?? '').startsWith('https://'); export async function loginAction(formData: FormData): Promise { const input = String(formData.get('token') ?? ''); const next = String(formData.get('next') ?? routes.admin()); const token = adminToken(); if (!token || !verifyToken(input)) redirect(`${routes.adminLogin()}?error=1`); const store = await cookies(); store.set(ADMIN_COOKIE, cookieValueFor(token!), { httpOnly: true, sameSite: 'lax', secure, path: '/admin', maxAge: ADMIN_COOKIE_MAX_AGE }); redirect(next.startsWith('/admin') ? next : routes.admin()); } export async function logoutAction(): Promise { const store = await cookies(); store.delete(ADMIN_COOKIE); redirect(routes.adminLogin()); } async function guard(): Promise { if (!(await isAdminAuthed())) redirect(routes.adminLogin()); } export async function refreshAction(): Promise { await guard(); let msg: string; let ok = true; try { const r = await adminApi.refresh(); msg = `${r.signal} → pid ${r.pid} at ${r.sent_at}`; } catch (e) { ok = false; msg = adminErrorMessage(e); } revalidatePath(routes.admin()); redirect(`${routes.admin()}?${ok ? 'ok' : 'err'}=${encodeURIComponent(msg)}`); } export async function clearCacheAction(): Promise { await guard(); let msg: string; let ok = true; try { const r = await adminApi.clearCache(); msg = `cache cleared (${Object.entries(r.before) .map(([k, v]) => `${k}=${v}`) .join(', ')})`; } catch (e) { ok = false; msg = adminErrorMessage(e); } revalidatePath(routes.admin()); redirect(`${routes.admin()}?${ok ? 'ok' : 'err'}=${encodeURIComponent(msg)}`); }