forked from Yara724/api
72 lines
2.0 KiB
TypeScript
72 lines
2.0 KiB
TypeScript
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 expert–initiated 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.",
|
||
);
|
||
}
|
||
}
|