From 8db56d38be205ee9263fd0a5170821876417dd68 Mon Sep 17 00:00:00 2001 From: SepehrYahyaee <7heycallmegray@gmail.com> Date: Mon, 26 Jan 2026 11:50:34 +0330 Subject: [PATCH] YARA-725 --- src/expert-blame/expert-blame.service.ts | 35 ++++++++++-- src/expert-claim/expert-claim.service.ts | 72 ++++++++++++++++++++---- 2 files changed, 90 insertions(+), 17 deletions(-) diff --git a/src/expert-blame/expert-blame.service.ts b/src/expert-blame/expert-blame.service.ts index eed9b1a..3a66091 100644 --- a/src/expert-blame/expert-blame.service.ts +++ b/src/expert-blame/expert-blame.service.ts @@ -263,14 +263,30 @@ export class ExpertBlameService { } // 2. Initial validation to ensure the expert has access - if (String(request?.actorLocked?.actorId) === actorId && request.lockFile) { + // Check if locked by current expert and lock is still active + const isLockedByCurrentExpert = + String(request?.actorLocked?.actorId) === actorId && request.lockFile; + + // Check if lock has expired + let isLockExpired = false; + if (request.unlockTime) { + const unlockTime = new Date(request.unlockTime).getTime(); + const now = Date.now(); + isLockExpired = now >= unlockTime; + } + + if (isLockedByCurrentExpert && !isLockExpired) { // This is the correct expert, and the file is locked to them, which is fine. + // They can access it even if they closed the browser and came back. } else if ( - request.lockFile || + (request.lockFile && !isLockExpired) || request.blameStatus === ReqBlameStatus.ReviewRequest ) { - // The file is locked, but not by the current expert. - throw new BadRequestException("Request is locked by another expert"); + // The file is locked by someone else, or lock expired but status hasn't updated yet + // Only block if lock is still active and not by current expert + if (request.lockFile && !isLockExpired && !isLockedByCurrentExpert) { + throw new BadRequestException("Request is locked by another expert"); + } } // 3. Populate the resend links if the data exists @@ -474,9 +490,18 @@ export class ExpertBlameService { "Access denied to this request. You are not the locked expert.", ); } - if (request.unlockTime == null) { + + // Check if lock has expired (unlockTime has passed) + if (request.unlockTime) { + const unlockTime = new Date(request.unlockTime).getTime(); + const now = Date.now(); + if (now >= unlockTime) { + throw new ForbiddenException("Your lock time has expired."); + } + } else if (request.unlockTime == null) { throw new ForbiddenException("Your lock time has expired."); } + if (!request.lockFile) { throw new ForbiddenException( "You must lock the request before submitting a reply.", diff --git a/src/expert-claim/expert-claim.service.ts b/src/expert-claim/expert-claim.service.ts index 956f35a..f12700b 100644 --- a/src/expert-claim/expert-claim.service.ts +++ b/src/expert-claim/expert-claim.service.ts @@ -818,7 +818,8 @@ export class ExpertClaimService { return new ClaimPerIdRs(requestUpdated); } - if (this.isRequestLocked(requestUpdated)) { + // Check if locked by someone else (allow if locked by current user) + if (this.isRequestLocked(requestUpdated, currentUser)) { throw new HttpException( { responseCode: 1007, message: "Request is locked" }, HttpStatus.FORBIDDEN, @@ -846,7 +847,7 @@ export class ExpertClaimService { if (this.isCurrentUserAllowed(request, currentUser)) { return (await this.claimRequestManagementDbService.findOne(requestId)) .imageRequired; - } else if (this.isRequestLocked(requestId)) { + } else if (this.isRequestLocked(request, currentUser)) { throw new HttpException( { responseCode: 1007, message: "Request is locked" }, HttpStatus.FORBIDDEN, @@ -889,8 +890,8 @@ export class ExpertClaimService { ); } - // Perform authorization checks - if (this.isRequestLocked(request) && !this.isCurrentUserAllowed(request, currentUser)) { + // Perform authorization checks - allow if locked by current user + if (this.isRequestLocked(request, currentUser)) { throw new HttpException( { responseCode: 1007, message: "Request is locked" }, HttpStatus.FORBIDDEN, @@ -933,16 +934,54 @@ export class ExpertClaimService { } private isCurrentUserAllowed(request: any, currentUser: any): boolean { - return ( + // Check if locked by current user and lock is still active + const isLockedByCurrentUser = String(request?.actorLocked?.actorId) === currentUser.sub && - request.lockFile - ); + request.lockFile; + + if (!isLockedByCurrentUser) { + return false; + } + + // Also check if lock has expired (unlockTime has passed) + if (request.unlockTime) { + const unlockTime = new Date(request.unlockTime).getTime(); + const now = Date.now(); + if (now >= unlockTime) { + // Lock has expired, but still allow access if they were the one who locked it + // The unlockApi will handle the cleanup + return true; + } + } + + return true; } - private isRequestLocked(request: any): boolean { - return ( - request.lockFile && request.claimStatus === ReqClaimStatus.ReviewRequest - ); + private isRequestLocked(request: any, currentUser?: any): boolean { + if (!request.lockFile || request.claimStatus !== ReqClaimStatus.ReviewRequest) { + return false; + } + + // Check if lock has expired + if (request.unlockTime) { + const unlockTime = new Date(request.unlockTime).getTime(); + const now = Date.now(); + if (now >= unlockTime) { + // Lock has expired, treat as not locked + return false; + } + } + + // If currentUser is provided, allow access if they are the one who locked it + if (currentUser) { + const isLockedByCurrentUser = + String(request?.actorLocked?.actorId) === currentUser.sub; + // Return false (not locked) if locked by current user, true if locked by someone else + return !isLockedByCurrentUser; + } + + // If no currentUser provided, treat as locked + return true; } async submitReplyRequest( @@ -963,9 +1002,18 @@ export class ExpertClaimService { ) { throw new ForbiddenException("Access denied to this request"); } - if (request?.unlockTime == null && !request?.objection) { + + // Check if lock has expired (unlockTime has passed) + if (request?.unlockTime && !request?.objection) { + const unlockTime = new Date(request.unlockTime).getTime(); + const now = Date.now(); + if (now >= unlockTime) { + throw new ForbiddenException("Your time has expired"); + } + } else if (request?.unlockTime == null && !request?.objection) { throw new ForbiddenException("Your time has expired"); } + if (!request.lockFile && !request?.objection) { throw new ForbiddenException( "For submit reply you must lock the request",