feat(server): 日志模块——任务 / 定时与自动 / 登录 / 审计合并查询与 SSE 流,登录失败留审计

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 17:58:08 +08:00
1 parent 01c68f9771
commit 744252b969
8 files changed
+823 -2

No files matched your search

@@ -81,6 +81,12 @@ describe.skipIf(!hasPg)("管理员登录门禁(真实 PG)", () => {
it("登录:错密码 401;正确密码下发 cookie;会话可访问 admin 端点;未登录 401", async () => {
const b = new Browser(h.app);
expect((await login(b, "wrong-password-1")).status).toBe(401);
// 日志模块「登录」类:失败也留一条审计(用户名、IP、原因,不含密码)
const failed = await sql<{ actor_type: string; payload: Record<string, unknown> }>`
select actor_type, payload from audit_event where action = 'admin.login_failed'`.execute(h.db);
expect(failed.rows).toHaveLength(1);
expect(failed.rows[0]!.payload).toMatchObject({ username: "admin", ip: "203.0.113.10" });
expect(JSON.stringify(failed.rows[0]!.payload)).not.toContain("wrong-password-1");
expect((await b.req("GET", "/settings")).status).toBe(401);
const res = await login(b);
expect(res.status).toBe(200);