diff --git a/packages/api/src/__tests__/system-role-config-router.test.ts b/packages/api/src/__tests__/system-role-config-router.test.ts new file mode 100644 index 0000000..c0e1856 --- /dev/null +++ b/packages/api/src/__tests__/system-role-config-router.test.ts @@ -0,0 +1,83 @@ +import { SystemRole } from "@capakraken/shared"; +import { describe, expect, it, vi } from "vitest"; +import { systemRoleConfigRouter } from "../router/system-role-config.js"; +import { createCallerFactory } from "../trpc.js"; + +const createCaller = createCallerFactory(systemRoleConfigRouter); + +function createAdminCaller(db: Record) { + return createCaller({ + session: { + user: { email: "admin@example.com", name: "Admin", image: null }, + expires: "2099-01-01T00:00:00.000Z", + }, + db: db as never, + dbUser: { + id: "admin_1", + systemRole: SystemRole.ADMIN, + permissionOverrides: null, + }, + }); +} + +function createProtectedCaller(db: Record) { + return createCaller({ + session: { + user: { email: "user@example.com", name: "User", image: null }, + expires: "2099-01-01T00:00:00.000Z", + }, + db: db as never, + dbUser: { + id: "user_1", + systemRole: SystemRole.USER, + permissionOverrides: null, + }, + }); +} + +describe("system role config router authorization", () => { + it("requires admin access for listing role configs", async () => { + const caller = createProtectedCaller({}); + + await expect(caller.list()).rejects.toThrow( + expect.objectContaining({ + code: "FORBIDDEN", + message: "Admin role required", + }), + ); + }); + + it("allows admins to list role configs", async () => { + const db = { + systemRoleConfig: { + findMany: vi.fn().mockResolvedValue([ + { + role: SystemRole.ADMIN, + label: "Admin", + description: "System administrator", + color: "#000000", + sortOrder: 0, + defaultPermissions: [], + }, + ]), + }, + }; + + const caller = createAdminCaller(db); + const result = await caller.list(); + + expect(db.systemRoleConfig.findMany).toHaveBeenCalledWith({ + orderBy: { sortOrder: "asc" }, + }); + expect(result).toEqual([ + { + role: SystemRole.ADMIN, + label: "Admin", + description: "System administrator", + color: "#000000", + sortOrder: 0, + defaultPermissions: [], + }, + ]); + }); +}); diff --git a/packages/api/src/router/system-role-config.ts b/packages/api/src/router/system-role-config.ts index 897cd25..770f22d 100644 --- a/packages/api/src/router/system-role-config.ts +++ b/packages/api/src/router/system-role-config.ts @@ -1,10 +1,10 @@ import { z } from "zod"; -import { adminProcedure, createTRPCRouter, invalidateRoleDefaultsCache, protectedProcedure } from "../trpc.js"; +import { adminProcedure, createTRPCRouter, invalidateRoleDefaultsCache } from "../trpc.js"; import { createAuditEntry } from "../lib/audit.js"; export const systemRoleConfigRouter = createTRPCRouter({ /** List all role configs (sorted by sortOrder) */ - list: protectedProcedure.query(async ({ ctx }) => { + list: adminProcedure.query(async ({ ctx }) => { return ctx.db.systemRoleConfig.findMany({ orderBy: { sortOrder: "asc" }, });