import { SystemRole } from "@capakraken/shared"; import { VacationType } from "@capakraken/db"; import { describe, expect, it, vi } from "vitest"; import { vacationRouter } from "../router/vacation.js"; import { createCallerFactory } from "../trpc.js"; const createCaller = createCallerFactory(vacationRouter); function createContext( db: Record, options: { role?: SystemRole; session?: boolean; } = {}, ) { const { role = SystemRole.USER, session = true } = options; return { session: session ? { user: { email: "user@example.com", name: "User", image: null }, expires: "2099-01-01T00:00:00.000Z", } : null, db: db as never, dbUser: session ? { id: role === SystemRole.ADMIN ? "user_admin" : role === SystemRole.MANAGER ? "user_mgr" : "user_1", systemRole: role, permissionOverrides: null, } : null, }; } function previewInput(resourceId: string) { return { resourceId, type: VacationType.ANNUAL, startDate: new Date("2026-08-10T00:00:00.000Z"), endDate: new Date("2026-08-12T00:00:00.000Z"), }; } describe("vacation router authorization", () => { it("requires authentication for preview requests", async () => { const resourceFindFirst = vi.fn(); const resourceFindUnique = vi.fn(); const caller = createCaller(createContext({ resource: { findFirst: resourceFindFirst, findUnique: resourceFindUnique, }, vacation: { findMany: vi.fn(), }, }, { session: false })); await expect(caller.previewRequest(previewInput("res_1"))).rejects.toMatchObject({ code: "UNAUTHORIZED", message: "Authentication required", }); expect(resourceFindFirst).not.toHaveBeenCalled(); expect(resourceFindUnique).not.toHaveBeenCalled(); }); it("forbids regular users from previewing another resource's request", async () => { const resourceFindUnique = vi.fn(); const vacationFindMany = vi.fn(); const caller = createCaller(createContext({ resource: { findFirst: vi.fn().mockResolvedValue({ id: "res_own" }), findUnique: resourceFindUnique, }, vacation: { findMany: vacationFindMany, }, })); await expect(caller.previewRequest(previewInput("res_other"))).rejects.toMatchObject({ code: "FORBIDDEN", message: "You can only view vacation data for your own resource", }); expect(resourceFindUnique).not.toHaveBeenCalled(); expect(vacationFindMany).not.toHaveBeenCalled(); }); it("allows regular users to preview their own requests", async () => { const resourceFindUnique = vi.fn().mockResolvedValue({ federalState: "BY", countryId: "country_de", metroCityId: null, country: { code: "DE", name: "Germany" }, metroCity: null, }); const vacationFindMany = vi.fn().mockResolvedValue([]); const caller = createCaller(createContext({ resource: { findFirst: vi.fn().mockResolvedValue({ id: "res_own" }), findUnique: resourceFindUnique, }, holidayCalendar: { findMany: vi.fn().mockResolvedValue([]), }, vacation: { findMany: vacationFindMany, }, })); const result = await caller.previewRequest(previewInput("res_own")); expect(result.requestedDays).toBe(3); expect(resourceFindUnique).toHaveBeenCalledWith({ where: { id: "res_own" }, select: { federalState: true, countryId: true, metroCityId: true, country: { select: { code: true, name: true } }, metroCity: { select: { name: true } }, }, }); }); it("allows managers to preview requests for other resources", async () => { const resourceFindFirst = vi.fn(); const resourceFindUnique = vi.fn().mockResolvedValue({ federalState: "BY", countryId: "country_de", metroCityId: null, country: { code: "DE", name: "Germany" }, metroCity: null, }); const caller = createCaller(createContext({ resource: { findFirst: resourceFindFirst, findUnique: resourceFindUnique, }, holidayCalendar: { findMany: vi.fn().mockResolvedValue([]), }, vacation: { findMany: vi.fn().mockResolvedValue([]), }, }, { role: SystemRole.MANAGER })); const result = await caller.previewRequest(previewInput("res_other")); expect(result.requestedDays).toBe(3); expect(resourceFindFirst).not.toHaveBeenCalled(); expect(resourceFindUnique).toHaveBeenCalledWith({ where: { id: "res_other" }, select: { federalState: true, countryId: true, metroCityId: true, country: { select: { code: true, name: true } }, metroCity: { select: { name: true } }, }, }); }); });