fix(holiday-calendar): scope resource holiday reads

This commit is contained in:
2026-03-30 12:10:52 +02:00
parent c7434c968e
commit 016f862405
4 changed files with 226 additions and 3 deletions
+42 -1
View File
@@ -14,7 +14,7 @@ import { asHolidayResolverDb, getResolvedCalendarHolidays } from "../lib/holiday
import { createTRPCRouter, adminProcedure, protectedProcedure, type TRPCContext } from "../trpc.js";
type HolidayCalendarScope = HolidayCalendarScopeInput;
type HolidayReadContext = Pick<TRPCContext, "db">;
type HolidayReadContext = Pick<TRPCContext, "db" | "dbUser">;
const HOLIDAY_SCOPE = {
COUNTRY: "COUNTRY",
@@ -119,6 +119,45 @@ function formatHolidayCalendarDetail(calendar: {
};
}
function canManageHolidayResourceReads(ctx: { dbUser: { systemRole: string } | null }): boolean {
const role = ctx.dbUser?.systemRole;
return role === "ADMIN" || role === "MANAGER";
}
async function findOwnedHolidayResourceId(ctx: HolidayReadContext): Promise<string | null> {
if (!ctx.dbUser?.id) {
return null;
}
if (!ctx.db.resource || typeof ctx.db.resource.findFirst !== "function") {
return null;
}
const resource = await ctx.db.resource.findFirst({
where: { userId: ctx.dbUser.id },
select: { id: true },
});
return resource?.id ?? null;
}
async function assertCanReadHolidayResource(
ctx: HolidayReadContext,
resourceId: string,
): Promise<void> {
if (canManageHolidayResourceReads(ctx)) {
return;
}
const ownedResourceId = await findOwnedHolidayResourceId(ctx);
if (!ownedResourceId || ownedResourceId !== resourceId) {
throw new TRPCError({
code: "FORBIDDEN",
message: "You can only view holiday data for your own resource",
});
}
}
function formatResolvedHolidayDetail(holiday: {
date: string;
name: string;
@@ -396,6 +435,8 @@ async function readResolvedResourceHolidaysSnapshot(
ctx: HolidayReadContext,
input: z.infer<typeof ResolveResourceHolidaysInputSchema>,
) {
await assertCanReadHolidayResource(ctx, input.resourceId);
const resource = await findUniqueOrThrow(
ctx.db.resource.findUnique({
where: { id: input.resourceId },