Files
ai-drama-platform/scripts/smoke-security-events.mjs
T

58 lines
3.1 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, options = {}) {
const response = await fetch(`${api}${path}`, {
...options,
headers: { "content-type": "application/json", ...(options.headers || {}) }
});
const payload = await response.json().catch(() => ({}));
return { response, payload };
}
async function login(email, password = "Demo@123456") {
const result = await request("/api/auth/login", {
method: "POST",
body: JSON.stringify({ email, password })
});
assert.equal(result.response.status, 200, `${email} 登录失败`);
assert.ok(result.payload.session?.token, `${email} 未返回登录会话`);
return { authorization: `Bearer ${result.payload.session.token}` };
}
const ownerHeaders = await login("producer@local.test");
const writerHeaders = await login("writer@local.test");
const badLogin = await request("/api/auth/login", {
method: "POST",
body: JSON.stringify({ email: "writer@local.test", password: "security-smoke-invalid-password" })
});
assert.equal(badLogin.response.status, 401, "错误密码必须被拒绝");
const ownEvents = await request("/api/auth/security-events", { headers: writerHeaders });
assert.equal(ownEvents.response.status, 200, "普通用户无法读取自己的安全事件");
assert.ok(Array.isArray(ownEvents.payload.events), "个人安全事件接口必须返回 events 数组");
assert.ok(ownEvents.payload.events.some((event) => event.eventType === "login.success"), "个人安全事件缺少登录成功记录");
assert.ok(ownEvents.payload.events.some((event) => event.eventType === "login.failure"), "个人安全事件缺少登录失败记录");
assert.ok(!JSON.stringify(ownEvents.payload.events).includes("security-smoke-invalid-password"), "安全事件不能记录密码");
const eventKeys = new Set();
for (const event of ownEvents.payload.events) {
for (const key of Object.keys(event.metadata || {})) eventKeys.add(key);
}
assert.ok(![...eventKeys].some((key) => /(sessionToken|challengeToken|password|otp|secret|api.?key)/i.test(key)), "安全事件不能返回敏感字段");
const ordinarySystemDenied = await request("/api/system/security-events", { headers: writerHeaders });
assert.equal(ordinarySystemDenied.response.status, 403, "普通用户不能查看全局安全事件");
assert.equal(ordinarySystemDenied.payload.error, "system_admin_required", "系统安全事件权限错误码不稳定");
const systemEvents = await request("/api/system/security-events?userId=u-writer", { headers: ownerHeaders });
assert.equal(systemEvents.response.status, 200, "系统管理员无法查看指定用户安全事件");
assert.ok(systemEvents.payload.events.some((event) => event.userId === "u-writer"), "系统安全事件未按指定用户过滤");
const detail = await request("/api/system/users/u-writer", { headers: ownerHeaders });
assert.equal(detail.response.status, 200, "系统管理员无法读取用户详情");
assert.ok(Array.isArray(detail.payload.securityEvents), "用户详情缺少账号安全事件台账");
console.log(`security events smoke passed: ${api}`);