Files
yara724api/src/auth/guards/claim-access.guard.ts
2026-05-30 10:37:23 +03:30

130 lines
3.7 KiB
TypeScript

import {
CanActivate,
ExecutionContext,
Injectable,
UnauthorizedException,
ForbiddenException,
} from "@nestjs/common";
import { JwtService } from "@nestjs/jwt";
import { RoleEnum } from "src/Types&Enums/role.enum";
import { ClaimRequestManagementDbService } from "src/claim-request-management/entites/db-service/claim-request-management.db.service";
import { Types } from "mongoose";
/**
* Guard that allows:
* - Users to access their own claim files
* - Experts to access IN_PERSON claim files they initiated
*/
@Injectable()
export class ClaimAccessGuard implements CanActivate {
constructor(
private readonly jwtService: JwtService,
private readonly claimDbService: ClaimRequestManagementDbService,
) {}
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const token = this.extractTokenFromHeader(request);
if (!token) {
throw new UnauthorizedException();
}
try {
const payload = await this.jwtService.verifyAsync(token, {
secret: `${process.env.JWT_SECRET}`,
});
// Allow users to pass through (they will be checked by service methods)
if (payload.role === RoleEnum.USER) {
request.user = payload;
request.identity = request.user;
return true;
}
// For experts, check if they're accessing an IN_PERSON claim file they initiated
if (
payload.role === RoleEnum.EXPERT ||
payload.role === RoleEnum.DAMAGE_EXPERT
) {
// Extract claimRequestId from route params
const claimRequestId =
request.params?.claimRequestId ||
request.params?.claimRequestID ||
request.params?.id;
if (!claimRequestId) {
// If no claim ID in params, allow access (e.g., for listing endpoints)
// The service will filter appropriately
request.user = payload;
request.actor = payload;
request.identity = payload;
return true;
}
// Verify expert has access to this specific claim file
const hasAccess = await this.verifyExpertClaimAccess(
claimRequestId,
payload.sub,
);
if (!hasAccess) {
throw new ForbiddenException(
"You can only access IN_PERSON claim files that you initiated",
);
}
request.user = payload;
request.actor = payload;
request.identity = payload;
return true;
}
throw new UnauthorizedException("Invalid role");
} catch (error) {
if (
error instanceof ForbiddenException ||
error instanceof UnauthorizedException
) {
throw error;
}
throw new UnauthorizedException();
}
}
private async verifyExpertClaimAccess(
claimRequestId: string,
expertId: string,
): Promise<boolean> {
try {
const claim = await this.claimDbService.findOne(claimRequestId);
if (!claim) {
return false;
}
const blameFile = claim.blameFile;
if (!blameFile) {
return false;
}
// Check if it's an expert-initiated IN_PERSON file
if (
blameFile.expertInitiated &&
blameFile.creationMethod === "IN_PERSON" &&
blameFile.initiatedBy
) {
// Verify the expert is the one who initiated it
return String(blameFile.initiatedBy) === expertId;
}
return false;
} catch (error) {
return false;
}
}
private extractTokenFromHeader(request: any): string | undefined {
const [type, token] = request.headers.authorization?.split(" ") ?? [];
return type === "Bearer" ? token : undefined;
}
}