import { TRPCError } from "@trpc/server"; import { PermissionKey, SystemRole, resolvePermissions, type PermissionOverrides, } from "@capakraken/shared"; import type { TRPCContext } from "../trpc.js"; export type ResourceReadContext = Pick; export function resolveResourcePermissions(ctx: Pick): Set { if (!ctx.dbUser) { return new Set(); } return resolvePermissions( ctx.dbUser.systemRole as SystemRole, ctx.dbUser.permissionOverrides as PermissionOverrides | null, ctx.roleDefaults ?? undefined, ); } export function canReadAllResources(ctx: Pick): boolean { const permissions = resolveResourcePermissions(ctx); return permissions.has(PermissionKey.VIEW_ALL_RESOURCES) || permissions.has(PermissionKey.MANAGE_RESOURCES); } export async function findOwnedResourceId(ctx: ResourceReadContext): 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 assertCanReadResource( ctx: ResourceReadContext, resourceId: string, message = "You can only view your own resource data", ): Promise { if (canReadAllResources(ctx)) { return; } const ownedResourceId = await findOwnedResourceId(ctx); if (!ownedResourceId || ownedResourceId !== resourceId) { throw new TRPCError({ code: "FORBIDDEN", message, }); } }