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-enterprise-ops-")); 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-27T18:00:00+08:00"; state.adminCompanies = [ { companyId: "tenant-a", name: "Tenant A", status: "active", ownerAccount: "admin@tenant-a.com", createdAt: now, updatedAt: now, }, ]; state.authAccounts = [ { id: "account-owner", account: "owner@platform.com", passwordHash: data.hashPassword("OwnerPass123"), displayName: "平台老板", role: "highest_admin", createdAt: now, updatedAt: now, }, { id: "account-admin", account: "admin@tenant-a.com", passwordHash: data.hashPassword("OldPass123"), displayName: "客户管理员", role: "admin", companyId: "tenant-a", createdAt: now, updatedAt: now, }, { id: "account-worker", account: "worker@tenant-a.com", passwordHash: data.hashPassword("WorkerPass123"), displayName: "客户成员", role: "member", companyId: "tenant-a", createdAt: now, updatedAt: now, }, ]; state.authSessions = []; state.permissionAuditLogs = []; await data.writeState(state); }); async function authedRequest(body: Record, extraHeaders: Record = {}) { const session = await data.createAuthSession({ account: "owner@platform.com", role: "highest_admin", displayName: "平台老板", 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}`, ...extraHeaders, }, body: JSON.stringify(body), }); } async function adminPost(body: Record) { return postAdminAccess(await authedRequest(body)); } async function adminPostWithHeaders(body: Record, headers: Record) { return postAdminAccess(await authedRequest(body, headers)); } test("bulk import preview reports create and update rows without mutating accounts", async () => { const response = await adminPost({ action: "preview_bulk_import_accounts", companyId: "tenant-a", accounts: [ { account: "worker@tenant-a.com", displayName: "现有成员", role: "member" }, { account: "new@tenant-a.com", displayName: "新成员", role: "admin" }, ], }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.preview.summary.create, 1); assert.equal(payload.preview.summary.update, 1); assert.deepEqual( payload.preview.rows.map((row: { account: string; operation: string }) => [row.account, row.operation]), [ ["worker@tenant-a.com", "update"], ["new@tenant-a.com", "create"], ], ); const state = await data.readState(); assert.equal(state.authAccounts.some((account) => account.account === "new@tenant-a.com"), false); }); test("highest admin can reset a child account password and revoke old sessions", async () => { const oldSession = await data.loginAccount({ account: "worker@tenant-a.com", password: "WorkerPass123", method: "password", }); const response = await adminPostWithHeaders( { action: "reset_account_password", account: "worker@tenant-a.com", password: "NewWorkerPass456", }, { "x-forwarded-for": "203.0.113.10, 10.0.0.1", "user-agent": "BossAdminTest/1.0", "x-request-id": "req-reset-001", }, ); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.account.account, "worker@tenant-a.com"); assert.equal(payload.account.passwordHash, undefined); await assert.rejects( data.loginAccount({ account: "worker@tenant-a.com", password: "WorkerPass123", method: "password" }), /INVALID_ACCOUNT_OR_PASSWORD/, ); const login = await data.loginAccount({ account: "worker@tenant-a.com", password: "NewWorkerPass456", method: "password", }); assert.equal(login.account, "worker@tenant-a.com"); assert.equal(await data.getAuthSession(oldSession.sessionToken), null); const audit = (await data.readState()).permissionAuditLogs.at(0); assert.equal(audit?.action, "account.password_reset"); assert.equal(audit?.ipAddress, "203.0.113.10"); assert.equal(audit?.userAgent, "BossAdminTest/1.0"); assert.equal(audit?.requestId, "req-reset-001"); assert.deepEqual(audit?.beforeJson, { account: "worker@tenant-a.com", status: "active", activeSessions: 1 }); assert.deepEqual(audit?.afterJson, { account: "worker@tenant-a.com", status: "active", revokedSessions: 1 }); }); test("disabling a company disables child accounts and revokes their sessions", async () => { const workerSession = await data.createAuthSession({ account: "worker@tenant-a.com", role: "member", displayName: "客户成员", loginMethod: "password", }); const response = await adminPost({ action: "set_company_status", companyId: "tenant-a", status: "disabled", }); assert.equal(response.status, 200); const payload = await response.json(); assert.equal(payload.company.status, "disabled"); assert.equal(payload.disabledAccounts, 2); const state = await data.readState(); assert.equal(state.adminCompanies.find((company) => company.companyId === "tenant-a")?.status, "disabled"); assert.equal( state.authAccounts .filter((account) => account.companyId === "tenant-a") .every((account) => account.status === "disabled"), true, ); assert.equal( state.authSessions.find((session) => session.sessionToken === workerSession.sessionToken)?.revokedAt !== undefined, true, ); assert.equal(state.permissionAuditLogs.at(0)?.action, "company.status_updated"); });