import { describe, expect, it, vi, afterEach } from "vitest"; import { buildApp } from "../src/app.js"; import { loadConfig } from "../src/config.js"; import * as auditPortalPush from "../src/services/audit-portal-push.js"; describe("audit log", () => { afterEach(() => { vi.restoreAllMocks(); }); it("GET /api/v1/audit returns local entries", async () => { const pushSpy = vi .spyOn(auditPortalPush, "pushAuditEvents") .mockResolvedValue(undefined); const app = await buildApp({ config: { ...loadConfig(), staticDir: null, authAuditIngestSecret: null, }, memory: true, }); const login = await app.inject({ method: "POST", url: "/api/v1/auth/login", payload: { username: "admin", password: "admin" }, }); expect(login.statusCode).toBe(200); const token = (login.json() as { token: string }).token; const create = await app.inject({ method: "POST", url: "/api/v1/groups", headers: { authorization: `Bearer ${token}` }, payload: { name: "Audit Test", slug: "audit-test" }, }); expect(create.statusCode).toBe(200); const list = await app.inject({ method: "GET", url: "/api/v1/audit?action=group.create", headers: { authorization: `Bearer ${token}` }, }); expect(list.statusCode).toBe(200); const entries = list.json() as { action: string; source_app: string }[]; expect(entries.length).toBeGreaterThanOrEqual(1); expect(entries[0]?.action).toBe("group.create"); expect(entries[0]?.source_app).toBe("cfdm"); expect(pushSpy).not.toHaveBeenCalled(); await app.close(); }); it("recordAudit pushes to portal when secret configured", async () => { const pushSpy = vi .spyOn(auditPortalPush, "pushAuditEvents") .mockResolvedValue(undefined); const app = await buildApp({ config: { ...loadConfig(), staticDir: null, authPortalUrl: "http://portal.test", authAuditIngestSecret: "test-ingest-secret", }, memory: true, }); const login = await app.inject({ method: "POST", url: "/api/v1/auth/login", payload: { username: "admin", password: "admin" }, }); const token = (login.json() as { token: string }).token; await app.inject({ method: "POST", url: "/api/v1/groups", headers: { authorization: `Bearer ${token}` }, payload: { name: "Portal Push", slug: "portal-push" }, }); await vi.waitFor(() => { expect(pushSpy).toHaveBeenCalledOnce(); }); const [portalUrl, secret, events] = pushSpy.mock.calls[0]!; expect(portalUrl).toBe("http://portal.test"); expect(secret).toBe("test-ingest-secret"); expect(events[0]?.source_app).toBe("cfdm"); expect(events[0]?.action).toBe("group.create"); await app.close(); }); });