diff --git a/src/features/housekeeping/foundation/capability-context.test.ts b/src/features/housekeeping/foundation/capability-context.test.ts index fe504c3fed..4cba25111c 100644 --- a/src/features/housekeeping/foundation/capability-context.test.ts +++ b/src/features/housekeeping/foundation/capability-context.test.ts @@ -65,6 +65,32 @@ describe("housekeeping capability context", () => { ).toBe(true); }); + it("bypasses meaningful requirements without consulting permission methods", () => { + const permissions: PermissionSet = { + isSuperAdmin: true, + has: vi.fn(() => false), + hasAny: vi.fn(() => false), + hasAll: vi.fn(() => false), + }; + const context = createHousekeepingCapabilityContext(actor, permissions); + + expect( + satisfiesCapability( + context, + anyCapability("admin.users.view", "admin.logs.view"), + ), + ).toBe(true); + expect( + satisfiesCapability( + context, + allCapabilities("admin.users.view", "admin.logs.view"), + ), + ).toBe(true); + expect(permissions.has).not.toHaveBeenCalled(); + expect(permissions.hasAny).not.toHaveBeenCalled(); + expect(permissions.hasAll).not.toHaveBeenCalled(); + }); + it("delegates capability checks without applying rank logic", () => { const permissions: PermissionSet = { isSuperAdmin: false, diff --git a/src/features/housekeeping/foundation/server-capability-context.test.ts b/src/features/housekeeping/foundation/server-capability-context.test.ts index 55066bc632..4cfb864116 100644 --- a/src/features/housekeeping/foundation/server-capability-context.test.ts +++ b/src/features/housekeeping/foundation/server-capability-context.test.ts @@ -1,18 +1,28 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; -const { getAdminContext } = vi.hoisted(() => ({ getAdminContext: vi.fn() })); +const { auth, getAdminContext, staleActor } = vi.hoisted(() => ({ + auth: vi.fn(), + getAdminContext: vi.fn(), + staleActor: { id: 9, username: "stale-session", rank: 1 }, +})); vi.mock("react", () => ({ cache: unknown>(callback: T) => callback, })); +vi.mock("@/lib/auth", () => ({ auth })); +vi.mock("@/lib/db", () => { + throw new Error("server capability context must not access the database"); +}); vi.mock("@/lib/permissions", () => ({ getAdminContext })); +import { auth as mockedAuth } from "@/lib/auth"; import { getHousekeepingCapabilityContext } from "./server-capability-context"; describe("getHousekeepingCapabilityContext", () => { beforeEach(() => { vi.clearAllMocks(); + auth.mockResolvedValue({ user: staleActor }); getAdminContext.mockResolvedValue({ session: { user: { @@ -31,7 +41,7 @@ describe("getHousekeepingCapabilityContext", () => { }); }); - it("uses the refreshed administrator actor and forwarded permissions", async () => { + it("uses the refreshed administrator actor instead of the stale auth actor", async () => { const context = await getHousekeepingCapabilityContext(); expect(context).toMatchObject({ @@ -41,5 +51,6 @@ describe("getHousekeepingCapabilityContext", () => { expect(context.has("admin.users.view")).toBe(true); expect(context.has("admin.logs.view")).toBe(false); expect(getAdminContext).toHaveBeenCalledTimes(1); + expect(mockedAuth).not.toHaveBeenCalled(); }); });