forked from Yara724/api
Initial commit after migration to gitea
This commit is contained in:
63
src/auth/guards/actor-local.guard.ts
Normal file
63
src/auth/guards/actor-local.guard.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import {
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { JwtService } from "@nestjs/jwt";
|
||||
import { AuthGuard } from "@nestjs/passport";
|
||||
import { ActorAuthService } from "src/auth/auth-services/actor.auth.service";
|
||||
import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||
|
||||
@Injectable()
|
||||
export class LocalActorAuthGuard extends AuthGuard("actor") {
|
||||
constructor(
|
||||
private readonly actorAuthService: ActorAuthService,
|
||||
private readonly jwtService: JwtService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const token = this.extractTokenFromHeader(request);
|
||||
const path = request.url;
|
||||
|
||||
if (!token) {
|
||||
if (path === "/actor/login") {
|
||||
const loginData = await this.actorAuthService.loginActors(request.body);
|
||||
request.user = loginData;
|
||||
request.identity = request;
|
||||
return true;
|
||||
} else {
|
||||
throw new UnauthorizedException("Token not found");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = await this.jwtService.verifyAsync(token, {
|
||||
secret: `${process.env.SECRET}`,
|
||||
});
|
||||
|
||||
if (
|
||||
![RoleEnum.EXPERT, RoleEnum.DAMAGE_EXPERT, RoleEnum.COMPANY].includes(
|
||||
payload.role,
|
||||
)
|
||||
) {
|
||||
throw new UnauthorizedException("User role is not authorized");
|
||||
}
|
||||
|
||||
request.user = payload;
|
||||
request.identity = request.user;
|
||||
} catch {
|
||||
throw new UnauthorizedException("Invalid token");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
//@ts-ignore
|
||||
const [type, token] = request.headers.authorization?.split(" ") ?? [];
|
||||
return type === "Bearer" ? token : undefined;
|
||||
}
|
||||
}
|
||||
127
src/auth/guards/claim-access.guard.ts
Normal file
127
src/auth/guards/claim-access.guard.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
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.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;
|
||||
}
|
||||
}
|
||||
|
||||
44
src/auth/guards/global.guard.ts
Normal file
44
src/auth/guards/global.guard.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
} from "@nestjs/common";
|
||||
import { JwtService } from "@nestjs/jwt";
|
||||
import { Request } from "express";
|
||||
import { RoleEnum } from "src/Types&Enums/role.enum";
|
||||
|
||||
@Injectable()
|
||||
export class GlobalGuard implements CanActivate {
|
||||
constructor(private readonly jwtService: JwtService) {}
|
||||
|
||||
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.SECRET}`,
|
||||
});
|
||||
if (payload.role !== RoleEnum.USER) {
|
||||
console.log(
|
||||
"🚀 ~ GlobalGuard ~ canActivate ~ request.user.role:",
|
||||
request.user.role,
|
||||
);
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
request.user = payload;
|
||||
request.identity = request.user;
|
||||
} catch {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
const [type, token] = request.headers.authorization?.split(" ") ?? [];
|
||||
return type === "Bearer" ? token : undefined;
|
||||
}
|
||||
}
|
||||
24
src/auth/guards/role.guard.ts
Normal file
24
src/auth/guards/role.guard.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Injectable, CanActivate, ExecutionContext } from "@nestjs/common";
|
||||
import { Reflector } from "@nestjs/core";
|
||||
|
||||
@Injectable()
|
||||
export class RolesGuard implements CanActivate {
|
||||
constructor(private readonly reflector: Reflector) {}
|
||||
canActivate(context: ExecutionContext): boolean {
|
||||
// get the roles required
|
||||
const roles = this.reflector.getAllAndOverride<string[]>("role", [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
]);
|
||||
if (!roles) {
|
||||
return false;
|
||||
}
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const userRoles = request.user?.role?.split(",");
|
||||
return this.validateRoles(roles, userRoles);
|
||||
}
|
||||
|
||||
validateRoles(roles: string[], userRoles: string[]) {
|
||||
return roles.some((role) => userRoles.includes(role));
|
||||
}
|
||||
}
|
||||
27
src/auth/guards/user-local.guard.ts
Normal file
27
src/auth/guards/user-local.guard.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import {
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
NotAcceptableException,
|
||||
} from "@nestjs/common";
|
||||
import { AuthGuard } from "@nestjs/passport";
|
||||
import { UserAuthService } from "src/auth/auth-services/user.auth.service";
|
||||
|
||||
@Injectable()
|
||||
export class LocalUserAuthGuard extends AuthGuard("local") {
|
||||
constructor(private readonly userAuthService: UserAuthService) {
|
||||
super();
|
||||
}
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const { username, password } = request.body;
|
||||
let isValidUser = await this.userAuthService.validateUser(
|
||||
username,
|
||||
password,
|
||||
);
|
||||
if (!isValidUser) {
|
||||
throw new NotAcceptableException("otp is wrong");
|
||||
}
|
||||
request["user"] = isValidUser;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user