import test from "node:test"; import assert from "node:assert/strict"; import os from "node:os"; import path from "node:path"; import { mkdtemp, rm } from "node:fs/promises"; import { NextRequest } from "next/server"; let runtimeRoot = ""; let data: typeof import("../src/lib/boss-data"); let authCookie = ""; let postAdminAccess: (typeof import("../src/app/api/v1/admin/access/route"))["POST"]; let baseState: Awaited>; async function setup() { if (runtimeRoot) return; runtimeRoot = await mkdtemp(path.join(os.tmpdir(), "boss-admin-account-status-")); process.env.BOSS_RUNTIME_ROOT = runtimeRoot; process.env.BOSS_STATE_FILE = path.join(runtimeRoot, "boss-state.json"); const [dataModule, authModule, routeModule] = await Promise.all([ import("../src/lib/boss-data.ts"), import("../src/lib/boss-auth.ts"), import("../src/app/api/v1/admin/access/route.ts"), ]); data = dataModule; authCookie = authModule.AUTH_SESSION_COOKIE; postAdminAccess = routeModule.POST; baseState = structuredClone(await data.readState()); } test.after(async () => { if (runtimeRoot) await rm(runtimeRoot, { recursive: true, force: true }); }); test.beforeEach(async () => { await setup(); const state = structuredClone(baseState); const now = "2026-04-27T12:00:00+08:00"; state.authAccounts = [ { id: "account-owner", account: "owner@acme.com", passwordHash: "secret", displayName: "Acme 老板", role: "highest_admin", createdAt: now, updatedAt: now, }, { id: "account-worker", account: "worker@acme.com", passwordHash: "secret", displayName: "Worker", role: "member", createdAt: now, updatedAt: now, }, ]; state.authSessions = []; state.permissionAuditLogs = []; await data.writeState(state); }); async function authedRequest( account: string, role: "member" | "admin" | "highest_admin", body: Record, ) { const session = await data.createAuthSession({ account, role, displayName: account, loginMethod: "password", }); return new NextRequest("http://127.0.0.1:3000/api/v1/admin/access", { method: "POST", headers: { "content-type": "application/json", cookie: `${authCookie}=${session.sessionToken}`, }, body: JSON.stringify(body), }); } async function adminPost(body: Record) { return postAdminAccess(await authedRequest("owner@acme.com", "highest_admin", body)); } test("highest admin can disable a child account and revoke its active sessions", async () => { const workerSession = await data.createAuthSession({ account: "worker@acme.com", role: "member", displayName: "Worker", loginMethod: "password", }); const response = await adminPost({ action: "set_account_status", account: "worker@acme.com", status: "disabled", }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.account.status, "disabled"); assert.equal(payload.account.passwordHash, undefined); const state = await data.readState(); assert.equal(state.authAccounts.find((account) => account.account === "worker@acme.com")?.status, "disabled"); assert.equal( state.authSessions.find((session) => session.sessionToken === workerSession.sessionToken)?.revokedAt !== undefined, true, ); assert.equal(await data.getAuthSession(workerSession.sessionToken), null); assert.equal(state.permissionAuditLogs.at(0)?.action, "account.updated"); }); test("highest admin can re-enable a disabled child account", async () => { await adminPost({ action: "set_account_status", account: "worker@acme.com", status: "disabled", }); const response = await adminPost({ action: "set_account_status", account: "worker@acme.com", status: "active", }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.account.status, "active"); const state = await data.readState(); assert.equal(state.authAccounts.find((account) => account.account === "worker@acme.com")?.status, "active"); }); test("highest admin cannot disable a highest admin account", async () => { const response = await adminPost({ action: "set_account_status", account: "owner@acme.com", status: "disabled", }); assert.equal(response.status, 400); const payload = await response.json(); assert.equal(payload.message, "CANNOT_DISABLE_HIGHEST_ADMIN"); });