Files
CapaKraken/packages/api/src/router/resource-identifier-read.ts
T

149 lines
5.0 KiB
TypeScript

import { TRPCError } from "@trpc/server";
import { z } from "zod";
import { findUniqueOrThrow } from "../db/helpers.js";
import { ROLE_BRIEF_SELECT } from "../db/selects.js";
import {
anonymizeResource,
getAnonymizationDirectory,
} from "../lib/anonymization.js";
import { assertCanReadResource } from "../lib/resource-access.js";
import { protectedProcedure } from "../trpc.js";
import {
mapResourceDetail,
readResourceByIdentifierDetailSnapshot,
resolveResourceIdentifierSnapshot,
} from "./resource-read-shared.js";
export const resourceIdentifierReadProcedures = {
resolveByIdentifier: protectedProcedure
.input(z.object({ identifier: z.string() }))
.query(async ({ ctx, input }) => {
const resource = await resolveResourceIdentifierSnapshot(
ctx,
input.identifier,
"You can only resolve your own resource unless you have staff access",
);
if ("error" in resource) {
throw new TRPCError({ code: "NOT_FOUND", message: "Resource not found" });
}
return resource;
}),
getHoverCard: protectedProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const resource = await findUniqueOrThrow(
ctx.db.resource.findUnique({
where: { id: input.id },
select: {
id: true,
displayName: true,
eid: true,
email: true,
chapter: true,
lcrCents: true,
ucrCents: true,
currency: true,
chargeabilityTarget: true,
skills: true,
availability: true,
isActive: true,
areaRole: { select: ROLE_BRIEF_SELECT },
country: { select: { name: true, code: true } },
managementLevel: { select: { name: true } },
resourceType: true,
},
}),
"Resource",
);
await assertCanReadResource(
ctx,
resource.id,
"You can only view hover details for your own resource unless you have staff access",
);
const directory = await getAnonymizationDirectory(ctx.db);
const anon = anonymizeResource(resource, directory);
return {
id: anon.id,
displayName: anon.displayName ?? "",
eid: anon.eid ?? "",
chapter: resource.chapter,
lcrCents: resource.lcrCents,
ucrCents: resource.ucrCents,
currency: resource.currency,
chargeabilityTarget: resource.chargeabilityTarget,
skills: resource.skills as Record<string, unknown>[],
isActive: resource.isActive,
resourceType: resource.resourceType,
areaRole: resource.areaRole,
country: resource.country,
managementLevel: resource.managementLevel,
};
}),
getByIdentifier: protectedProcedure
.input(z.object({ identifier: z.string() }))
.query(async ({ ctx, input }) => resolveResourceIdentifierSnapshot(ctx, input.identifier)),
getByIdentifierDetail: protectedProcedure
.input(z.object({ identifier: z.string() }))
.query(async ({ ctx, input }) => {
const resource = await readResourceByIdentifierDetailSnapshot(ctx, input.identifier);
if ("error" in resource) {
return resource;
}
return mapResourceDetail(resource);
}),
getById: protectedProcedure
.input(z.object({ id: z.string() }))
.query(async ({ ctx, input }) => {
const resource = await findUniqueOrThrow(
ctx.db.resource.findUnique({
where: { id: input.id },
include: {
blueprint: true,
resourceRoles: {
include: { role: { select: ROLE_BRIEF_SELECT } },
},
areaRole: { select: { id: true, name: true } },
},
}),
"Resource",
);
await assertCanReadResource(
ctx,
resource.id,
"You can only view your own resource unless you have staff access",
);
const directory = await getAnonymizationDirectory(ctx.db);
return {
...anonymizeResource(resource, directory),
isOwnedByCurrentUser: Boolean(resource.userId && ctx.dbUser?.id && resource.userId === ctx.dbUser.id),
};
}),
getByEid: protectedProcedure
.input(z.object({ eid: z.string() }))
.query(async ({ ctx, input }) => {
const directory = await getAnonymizationDirectory(ctx.db);
let resource = await ctx.db.resource.findUnique({ where: { eid: input.eid } });
if (!resource && directory) {
const resourceId = directory.byAliasEid.get(input.eid.trim().toLowerCase());
if (resourceId) {
resource = await ctx.db.resource.findUnique({ where: { id: resourceId } });
}
}
if (!resource) {
throw new TRPCError({ code: "NOT_FOUND", message: "Resource not found" });
}
await assertCanReadResource(
ctx,
resource.id,
"You can only view your own resource unless you have staff access",
);
return anonymizeResource(resource, directory);
}),
};