61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
vi.mock("@hivegrid/db/audit-events.server", () => ({ createAuditEvent: vi.fn() }));
|
|
vi.mock("@hivegrid/db/admin-sso.server", () => ({ appendPreauthAdminSsoAuditEvent: vi.fn() }));
|
|
vi.mock("@hivegrid/db/rls-context.server", () => ({ getRlsExecutionContext: vi.fn() }));
|
|
vi.mock("~/utils/server/IpUtils", () => ({ getTrustedClientIpOrNull: vi.fn(() => "192.0.2.1") }));
|
|
|
|
import { appendPreauthAdminSsoAuditEvent } from "@hivegrid/db/admin-sso.server";
|
|
import { createAuditEvent } from "@hivegrid/db/audit-events.server";
|
|
import { getRlsExecutionContext } from "@hivegrid/db/rls-context.server";
|
|
import { writeAdminSsoAuditEvent } from "./audit.server";
|
|
|
|
describe("Admin SSO audit RLS boundary", () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
vi.mocked(getRlsExecutionContext).mockReturnValue(null);
|
|
});
|
|
|
|
it("uses the narrow platform append capability before an operator identity exists", async () => {
|
|
await writeAdminSsoAuditEvent({
|
|
action: "admin.login.sso.failure",
|
|
request: new Request("https://admin.example.test/auth/admin/callback", { headers: { "user-agent": "test-agent" } }),
|
|
meta: { stage: "claims" },
|
|
});
|
|
|
|
expect(appendPreauthAdminSsoAuditEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
action: "admin.login.sso.failure",
|
|
actorType: "admin",
|
|
sourceModule: "admin-sso",
|
|
outcome: "failure",
|
|
})
|
|
);
|
|
expect(createAuditEvent).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("uses the regular operator-scoped chain once app.user_id is bound", async () => {
|
|
vi.mocked(getRlsExecutionContext).mockReturnValue({ userId: "admin_1" });
|
|
|
|
await writeAdminSsoAuditEvent({
|
|
action: "admin.login.sso.success",
|
|
actorAdminUserId: "admin_1",
|
|
});
|
|
|
|
expect(createAuditEvent).toHaveBeenCalledWith(
|
|
expect.objectContaining({
|
|
action: "admin.login.sso.success",
|
|
actorId: "admin_1",
|
|
outcome: "success",
|
|
})
|
|
);
|
|
expect(appendPreauthAdminSsoAuditEvent).not.toHaveBeenCalled();
|
|
});
|
|
|
|
it("keeps audit failures non-blocking for the login flow", async () => {
|
|
vi.mocked(appendPreauthAdminSsoAuditEvent).mockRejectedValueOnce(new Error("database unavailable"));
|
|
|
|
await expect(writeAdminSsoAuditEvent({ action: "admin.login.sso.failure" })).resolves.toBeUndefined();
|
|
});
|
|
});
|