forked from Shared/esg
46 lines
1.5 KiB
TypeScript
46 lines
1.5 KiB
TypeScript
import { CanActivate, ExecutionContext, ForbiddenException, Injectable } from '@nestjs/common';
|
|
import { Reflector } from '@nestjs/core';
|
|
import { Request } from 'express';
|
|
import { ADMIN_ROLES } from '../../common/enums/role.enum';
|
|
import { InquiryType } from '../../common/enums/inquiry-type.enum';
|
|
import { INQUIRY_ACCESS_KEY } from '../constants/auth.constants';
|
|
import { AuthenticatedUser } from '../interfaces/authenticated-user.interface';
|
|
|
|
/**
|
|
* Validates that the user may call a specific inquiry endpoint.
|
|
* ADMIN / SUPER_ADMIN bypass — external USER clients need allowedInquiries.
|
|
*/
|
|
@Injectable()
|
|
export class InquiryAccessGuard implements CanActivate {
|
|
constructor(private readonly reflector: Reflector) {}
|
|
|
|
canActivate(context: ExecutionContext): boolean {
|
|
const requiredInquiry = this.reflector.getAllAndOverride<InquiryType>(INQUIRY_ACCESS_KEY, [
|
|
context.getHandler(),
|
|
context.getClass(),
|
|
]);
|
|
|
|
if (!requiredInquiry) {
|
|
return true;
|
|
}
|
|
|
|
const request = context.switchToHttp().getRequest<Request & { user: AuthenticatedUser }>();
|
|
const user = request.user;
|
|
|
|
if (!user) {
|
|
throw new ForbiddenException('Authentication required');
|
|
}
|
|
|
|
if (ADMIN_ROLES.includes(user.role)) {
|
|
return true;
|
|
}
|
|
|
|
const inquiryKey = requiredInquiry as string;
|
|
if (!user.allowedInquiries.includes(inquiryKey)) {
|
|
throw new ForbiddenException(`Access denied for inquiry: ${inquiryKey}`);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|