Files
Jyotisha/frontend/tests/admin-users-contract.test.ts
T
linmeng 1b8d6fcce6
Staging Backend Quality Gate (push the reviewed main SHA to staging to auto-deploy) / validate (push) Failing after 5m10s
Staging Backend Quality Gate (push the reviewed main SHA to staging to auto-deploy) / publish-and-deploy (push) Has been skipped
feat: add configurable payments and Gitea staging delivery
Add database-backed administrators, configurable Alipay packages, idempotent payment settlement and platform reporting. Standardize Gitea workflows on the xiaoxin runner so reviewed staging commits are tested, packaged, and deployed by immutable image digest.
2026-07-27 20:19:05 +08:00

48 lines
2.5 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 layoutSource = readFileSync(new URL("src/app/admin/layout.tsx", root), "utf8");
const codesSource = readFileSync(new URL("src/app/api/admin/codes/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(adminSource, /configured/);
assert.match(adminSource, /split\(\",\"\)/);
assert.match(adminSource, /toLowerCase/);
assert.match(adminSource, /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(layoutSource, /await isAdminUser\(user\)/);
assert.match(codesSource, /await isAdminUser\(user\)/);
assert.match(accountSource, /isAdmin: await isAdminUser\(user\)/);
});
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 guarded list, add, and soft revoke contracts", () => {
assert.match(usersSource, /export async function GET/);
assert.match(usersSource, /export async function POST/);
assert.match(usersSource, /export async function DELETE/);
assert.match(usersSource, /auth\.admin\.listUsers/);
assert.match(usersSource, /upsert\(\{ user_id: target\.id, created_by: auth\.user\.id/);
assert.match(usersSource, /revoked_at: new Date\(\)\.toISOString\(\)/);
assert.match(usersSource, /环境配置管理员不可撤销/);
});