Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesDiscussionsWikiPull RequestsProjectsCommitsActionsReleasesContributorsPulse● GatesSecuritySettingsDeploymentsPipelineInsightsAgents✨ Explain✨ Ask AI✨ Workspace✨ Spec✨ Tests▓ Debt Map✨ NL Search🏛 Archaeology
Blame · Line-by-line history

admin.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

admin.tsBlame52 lines · 1 contributor
a4f3e24Claude1/**
2 * Admin middleware — blocks non-admin users.
3 * Must be used AFTER softAuth or requireAuth.
36cc17aClaude4 *
5 * "Admin" means EITHER:
6 * - the user is in the `site_admins` table (explicit grant), OR
7 * - the `site_admins` table is empty and this user is the oldest
8 * row in `users` (bootstrap rule from src/lib/admin.ts).
9 *
10 * The legacy `users.is_admin` column is ALSO honoured for backward
11 * compatibility with accounts that pre-date the site_admins table.
12 *
13 * Until 2026-05-14 this middleware only checked `users.is_admin`,
14 * which broke /import + every other requireAdmin-gated route for any
15 * user who only had bootstrap-rule admin status (which is the case
16 * after running scripts/reset-admin-password.ts).
a4f3e24Claude17 */
18
19import { createMiddleware } from "hono/factory";
20import type { AuthEnv } from "./auth";
36cc17aClaude21import { isSiteAdmin } from "../lib/admin";
c63b860Claude22// BLOCK O2 — polished 403 page renderer (standalone HTML, DB-free).
23import { renderStandaloneErrorPage } from "../views/error-page";
a4f3e24Claude24
25export const requireAdmin = createMiddleware<AuthEnv>(async (c, next) => {
26 const user = c.get("user");
27
28 if (!user) {
29 return c.redirect(`/login?redirect=${encodeURIComponent(c.req.path)}`);
30 }
31
36cc17aClaude32 const admin = user.isAdmin === true || (await isSiteAdmin(user.id));
33 if (!admin) {
c63b860Claude34 // BLOCK O2 — polished 403 page (was inline 80s-era markup). The
35 // standalone renderer returns a self-contained <!doctype html>
36 // document so this middleware has no Layout dependency.
a4f3e24Claude37 return c.html(
c63b860Claude38 renderStandaloneErrorPage({
39 code: "403",
40 eyebrow: "Forbidden",
41 title: "Admin access required.",
42 body:
43 "This area is restricted to site admins. If you think this is " +
44 "a mistake, contact a site admin or sign in as a different user.",
45 signedIn: true,
46 }),
a4f3e24Claude47 403
48 );
49 }
50
51 return next();
52});