/** * admin-relay-panel.ts — Serves the relay admin dashboard HTML at /admin/relay. * * This page is registered directly in app.ts at /admin/relay (NOT under /api) * so the route is accessible at a clean URL. * * Auth gate: on first visit the user is prompted for ADMIN_TOKEN, stored in * localStorage, sent as Bearer Authorization header on every /api/admin call. * * Tabs: * Queue — Pending events list with content preview, Approve/Reject; 15s auto-refresh * Accounts — Whitelist table with Revoke; pubkey grant form * * Stats bar: pending, approved today, total accounts, live relay connections. */ import { Router, type Request, type Response } from "express"; const router = Router(); // Gate: in production the panel returns 403 when ADMIN_TOKEN is not configured. // In development (no token set), the auth gate still renders and the API uses // localhost-only fallback, so ops can still access the panel locally. const ADMIN_TOKEN = process.env["ADMIN_TOKEN"] ?? process.env["ADMIN_SECRET"] ?? ""; const IS_PROD = process.env["NODE_ENV"] === "production"; router.get("/admin/relay", (_req: Request, res: Response) => { if (IS_PROD && !ADMIN_TOKEN) { res.status(403).send("Relay admin panel disabled: ADMIN_TOKEN is not configured."); return; } res.setHeader("Content-Type", "text/html"); res.send(ADMIN_PANEL_HTML); }); export default router; // ───────────────────────────────────────────────────────────────────────────── // Inline HTML — no build step required, served directly by Express. // ───────────────────────────────────────────────────────────────────────────── const ADMIN_PANEL_HTML = ` Relay Admin — Timmy Tower World

🔒 Admin Access

Enter the ADMIN_TOKEN to access the relay dashboard. It will be remembered in this browser.

Incorrect token — please try again.

⚡ Timmy Relay Admin OPERATOR

Pending review
Approved today
Accounts
Relay connections

Pending events

auto-refreshes every 15s

Relay accounts

whitelist
`;