2dac8bc47b
Deploy staging to test server / deploy (push) Successful in 3m11s
Use persisted self-hosted roles and the isolated admin origin so authorized staging accounts can discover the protected admin surface.
48 lines
2.6 KiB
TypeScript
48 lines
2.6 KiB
TypeScript
import assert from "node:assert/strict";
|
|
import { readFileSync } from "node:fs";
|
|
import test from "node:test";
|
|
|
|
const root = new URL("../", import.meta.url);
|
|
const adminSource = readFileSync(new URL("src/lib/supabase/admin.ts", root), "utf8");
|
|
const adminCoreSource = readFileSync(new URL("src/lib/supabase/admin-client-core.ts", root), "utf8");
|
|
const codesSource = readFileSync(new URL("src/app/api/admin/codes/route.ts", root), "utf8");
|
|
const sessionSource = readFileSync(new URL("src/app/api/admin/session/route.ts", root), "utf8");
|
|
const accountSource = readFileSync(new URL("src/app/api/account/route.ts", root), "utf8");
|
|
const usersSource = readFileSync(new URL("src/app/api/admin/users/route.ts", root), "utf8");
|
|
const migration = readFileSync(new URL("supabase/migrations/20260727010000_admin_users.sql", root), "utf8");
|
|
|
|
test("ADMIN_EMAILS remains a case-insensitive comma-separated allowlist", () => {
|
|
assert.match(adminCoreSource, /configured/);
|
|
assert.match(adminCoreSource, /split\(","\)/);
|
|
assert.match(adminCoreSource, /toLowerCase/);
|
|
assert.match(adminCoreSource, /export function isAdminEmail/);
|
|
});
|
|
|
|
test("admin surfaces await database-backed administrator checks", () => {
|
|
assert.match(adminSource, /export async function isAdminUser/);
|
|
assert.match(adminSource, /from\("admin_users"\)/);
|
|
assert.match(sessionSource, /await requireAdminSession\(\)/);
|
|
assert.match(codesSource, /await requireAdminSession\("write"\)/);
|
|
assert.match(accountSource, /const isAdmin = await isAdminUser\(user\)/);
|
|
assert.match(accountSource, /isAdmin,/);
|
|
});
|
|
|
|
test("admin_users migration is service-role-only and auditable", () => {
|
|
assert.match(migration, /user_id uuid primary key references auth\.users\(id\)/);
|
|
assert.match(migration, /created_at timestamptz/);
|
|
assert.match(migration, /created_by uuid/);
|
|
assert.match(migration, /revoked_at timestamptz/);
|
|
assert.match(migration, /revoked_by uuid/);
|
|
assert.match(migration, /enable row level security/);
|
|
assert.match(migration, /revoke all on table public\.admin_users from anon, authenticated/);
|
|
assert.match(migration, /grant select, insert, update on table public\.admin_users to service_role/);
|
|
});
|
|
|
|
test("admin users route exposes a guarded list and rejects mutations", () => {
|
|
assert.match(usersSource, /export async function GET/);
|
|
assert.match(usersSource, /await requireAdminSession\(\)/);
|
|
assert.match(usersSource, /export const POST = readonlyAdminMutation/);
|
|
assert.match(usersSource, /export const PATCH = readonlyAdminMutation/);
|
|
assert.match(usersSource, /export const DELETE = readonlyAdminMutation/);
|
|
});
|