Files
yara724api/src/helpers/tenant-scope.ts
2026-04-18 17:04:19 +03:30

72 lines
2.0 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BadRequestException, ForbiddenException } from "@nestjs/common";
/** Insurance company tenant id on the actor JWT (Mongo ObjectId string). */
export function requireActorClientKey(actor: { clientKey?: string }): string {
const ck = actor?.clientKey;
if (!ck || typeof ck !== "string") {
throw new BadRequestException(
"Client scope is missing for this account. Insurer/expert users must be bound to an insurance company.",
);
}
return ck;
}
export function blameCaseTouchesClient(doc: any, clientKey: string): boolean {
const id = String(clientKey);
return (doc?.parties ?? []).some(
(p: any) => String(p?.person?.clientId ?? "") === id,
);
}
export function claimCaseTouchesClient(doc: any, clientKey: string): boolean {
const id = String(clientKey);
const owner = doc?.owner as
| { clientId?: unknown; userClientKey?: unknown }
| undefined;
const tenantId = owner?.clientId ?? owner?.userClientKey;
return String(tenantId ?? "") === id;
}
/**
* Field expertinitiated cases may not yet have party clientId filled; the
* initiating expert is always scoped to their insurer via JWT.
*/
export function blameCaseAccessibleToExpert(
doc: any,
actor: { sub: string; clientKey?: string },
): boolean {
if (
doc.expertInitiated &&
doc.initiatedByFieldExpertId &&
String(doc.initiatedByFieldExpertId) === actor.sub
) {
return true;
}
const ck = actor?.clientKey;
if (!ck) return false;
return blameCaseTouchesClient(doc, ck);
}
export function assertBlameCaseForExpertTenant(
doc: any,
actor: { sub: string; clientKey?: string },
): void {
if (!blameCaseAccessibleToExpert(doc, actor)) {
throw new ForbiddenException(
"This blame case does not belong to your organization.",
);
}
}
export function assertClaimCaseForTenant(
doc: any,
actor: { clientKey?: string },
): void {
const ck = requireActorClientKey(actor);
if (!claimCaseTouchesClient(doc, ck)) {
throw new ForbiddenException(
"This claim does not belong to your organization.",
);
}
}