import { TRPCError } from "@trpc/server"; import { isAdminOrManager } from "@capakraken/shared"; import type { TRPCContext } from "../trpc.js"; export type OwnedResourceReadContext = Pick; export function canManageOwnedResourceReads(ctx: { dbUser: { systemRole: string } | null }): boolean { return isAdminOrManager(ctx.dbUser?.systemRole); } export async function findOwnedReadResourceId( ctx: OwnedResourceReadContext, ): Promise { 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; } export async function assertCanReadOwnedResource( ctx: OwnedResourceReadContext, resourceId: string, forbiddenMessage: string, ): Promise { if (canManageOwnedResourceReads(ctx)) { return; } const ownedResourceId = await findOwnedReadResourceId(ctx); if (!ownedResourceId || ownedResourceId !== resourceId) { throw new TRPCError({ code: "FORBIDDEN", message: forbiddenMessage, }); } } export async function resolveOwnedResourceReadFilter( ctx: OwnedResourceReadContext, requestedResourceId: string | undefined, forbiddenMessage: string, ): Promise { if (canManageOwnedResourceReads(ctx)) { return requestedResourceId; } const ownedResourceId = await findOwnedReadResourceId(ctx); if (requestedResourceId && requestedResourceId !== ownedResourceId) { throw new TRPCError({ code: "FORBIDDEN", message: forbiddenMessage, }); } return ownedResourceId; }