Files

61 lines
3.5 KiB
JavaScript

import assert from "node:assert/strict";
const api = process.env.AI_DRAMA_API_BASE || "http://127.0.0.1:8787";
async function request(path, headers, options = {}) {
const response = await fetch(`${api}${path}`, {
...options,
headers: { "content-type": "application/json", ...(headers || {}), ...(options.headers || {}) }
});
const contentType = response.headers.get("content-type") || "";
const payload = contentType.includes("json") ? await response.json().catch(() => ({})) : await response.text();
return { response, payload };
}
async function login(email) {
const result = await request("/api/auth/login", null, { method: "POST", body: JSON.stringify({ email, password: "Demo@123456" }) });
assert.equal(result.response.status, 200, `${email} 登录失败`);
return { authorization: `Bearer ${result.payload.session.token}` };
}
const systemAdmin = await login("producer@local.test");
const organizationAdmin = await login("producer2@local.test");
const ordinaryUser = await login("writer@local.test");
const globalList = await request("/api/audit?page=1&pageSize=2&result=ok", systemAdmin);
assert.equal(globalList.response.status, 200, "系统管理员读取审计列表失败");
assert.equal(globalList.payload.scope.mode, "global", "系统管理员应获得全局审计范围");
assert.equal(globalList.payload.auditLog.length, 2, "服务端分页未按 pageSize 返回");
assert.ok(globalList.payload.pagination.total > 2 && globalList.payload.pagination.hasMore, "审计分页元数据不完整");
const auditId = globalList.payload.auditLog[0]?.id;
assert.ok(auditId, "审计列表缺少事件 ID");
const detail = await request(`/api/audit/${encodeURIComponent(auditId)}`, systemAdmin);
assert.equal(detail.response.status, 200, "系统管理员读取审计详情失败");
assert.equal(detail.payload.event.id, auditId, "审计详情 ID 不一致");
assert.ok(Array.isArray(detail.payload.relatedAudit), "审计详情缺少关联审计列表");
assert.ok(Array.isArray(detail.payload.relatedSecurityEvents), "审计详情缺少安全事件列表");
const exported = await request("/api/audit/export?query=project&pageSize=5", systemAdmin);
assert.equal(exported.response.status, 200, "审计 JSON 导出失败");
assert.ok(Array.isArray(exported.payload.auditLog), "审计 JSON 导出缺少事件数组");
assert.ok(Number.isInteger(exported.payload.total), "审计 JSON 导出缺少总数");
const csv = await request("/api/audit/export?format=csv&pageSize=2", systemAdmin);
assert.equal(csv.response.status, 200, "审计 CSV 导出失败");
assert.match(csv.response.headers.get("content-type") || "", /text\/csv/);
assert.match(csv.response.headers.get("content-disposition") || "", /audit-/);
assert.match(csv.payload, /id,|"id"/);
const orgList = await request("/api/audit?page=1&pageSize=5", organizationAdmin);
assert.equal(orgList.response.status, 200, "组织管理员读取审计列表失败");
assert.equal(orgList.payload.scope.mode, "organization", "组织管理员应限制在组织范围");
assert.equal(orgList.payload.scope.organizationId, "org-northstar", "组织管理员组织范围错误");
const crossOrganization = await request("/api/audit?organizationId=org-studio-lab", organizationAdmin);
assert.equal(crossOrganization.response.status, 403, "组织管理员不应读取其他组织审计");
const denied = await request("/api/audit", ordinaryUser);
assert.equal(denied.response.status, 403, "普通用户不应读取审计中心");
console.log(`audit smoke passed: ${api}`);