From 3afff6733655e9bde8255959f8e9260e80c6e671 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Sat, 25 Jul 2026 12:31:54 +0330 Subject: [PATCH] YARA-1147 --- src/expert-claim/expert-claim.service.ts | 35 ++++++++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/expert-claim/expert-claim.service.ts b/src/expert-claim/expert-claim.service.ts index 3b9281a..02cf412 100644 --- a/src/expert-claim/expert-claim.service.ts +++ b/src/expert-claim/expert-claim.service.ts @@ -3716,14 +3716,19 @@ export class ExpertClaimService { let claims: any[] = []; if (actor.role === RoleEnum.FIELD_EXPERT) { const expertOid = new Types.ObjectId(actor.sub); + // Exclude V4/V5 blame files — same rule as getFieldExpertClaimListV2. const expertBlameIds = await this.blameRequestDbService .find( - { expertInitiated: true, initiatedByFieldExpertId: expertOid }, + { + expertInitiated: true, + initiatedByFieldExpertId: expertOid, + isMadeByFileMaker: { $ne: true }, + }, { select: "_id", lean: true }, ) .then((docs) => docs.map((d) => (d as { _id: unknown })._id)); const claimOr: Record[] = [ - { initiatedByFieldExpertId: expertOid }, + { initiatedByFieldExpertId: expertOid, requiresFileMakerApproval: { $ne: true } }, ]; if (expertBlameIds.length > 0) { claimOr.push({ blameRequestId: { $in: expertBlameIds } }); @@ -4052,15 +4057,22 @@ export class ExpertClaimService { query: ListQueryV2Dto = {}, ): Promise { const expertOid = new Types.ObjectId(actor.sub); + // Exclude V4/V5 blame files (isMadeByFileMaker=true) — those belong to + // the FILE_MAKER/FILE_REVIEWER flows, not the V3 field-expert flow. const expertBlameIds = await this.blameRequestDbService .find( - { expertInitiated: true, initiatedByFieldExpertId: expertOid }, + { + expertInitiated: true, + initiatedByFieldExpertId: expertOid, + isMadeByFileMaker: { $ne: true }, + }, { select: "_id", lean: true }, ) .then((docs) => docs.map((d) => (d as { _id: unknown })._id)); const claimOr: Record[] = [ - { initiatedByFieldExpertId: expertOid }, + // Direct claim link: exclude V5 claims that require FileMaker approval + { initiatedByFieldExpertId: expertOid, requiresFileMakerApproval: { $ne: true } }, ]; if (expertBlameIds.length > 0) { claimOr.push({ blameRequestId: { $in: expertBlameIds } }); @@ -4738,8 +4750,19 @@ export class ExpertClaimService { "This file has been taken by another reviewer.", ); } - } else if (!claimCaseInitiatedByFieldExpert(claim, actor, linkedBlame)) { - throw new ForbiddenException("This claim is not accessible to you."); + } else { + // FIELD_EXPERT: V3 flow only. Reject V4/V5 files (isMadeByFileMaker) + // even if their ID matches initiatedByFieldExpertId on the blame — + // those are FILE_MAKER files, accessible via the FILE_MAKER role only. + const isV4V5Blame = !!(linkedBlame as any)?.isMadeByFileMaker; + if (isV4V5Blame) { + throw new ForbiddenException( + "Field experts can only access V3 expert-initiated files.", + ); + } + if (!claimCaseInitiatedByFieldExpert(claim, actor, linkedBlame)) { + throw new ForbiddenException("This claim is not accessible to you."); + } } // Fall through to the detail build below (skip the damage-expert gate) } else if (actor.role !== RoleEnum.FILE_MAKER) {