- Remove `type` modifier from imports used as DI constructor params across ~235 files (@Injectable, @Controller, @Module, @Catch, @CommandHandler, @QueryHandler, @EventsHandler, @WebSocketGateway). TypeScript emitDecoratorMetadata strips type-only imports, leaving Reflect.metadata with Function placeholder and breaking Nest DI. - Fix controllers: DTOs used with @Body/@Query/@Param must be runtime imports so ValidationPipe can whitelist properties. Previously returned 400 "property X should not exist" on every request. - Register ProjectsModule in AppModule (was defined but never wired). - Add approve()/reject() methods to TransferListingEntity referenced by ModerateTransferListingHandler. - Export BankTransferConfirmedEvent from payments barrel for subscription activation handler. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
42 lines
1.3 KiB
TypeScript
42 lines
1.3 KiB
TypeScript
import { Injectable, type CanActivate, type ExecutionContext } from '@nestjs/common';
|
|
import { Reflector } from '@nestjs/core';
|
|
import { type UserRole } from '@prisma/client';
|
|
import { LoggerService } from '@modules/shared';
|
|
import { ROLES_KEY } from '../decorators/roles.decorator';
|
|
|
|
@Injectable()
|
|
export class RolesGuard implements CanActivate {
|
|
constructor(
|
|
private readonly reflector: Reflector,
|
|
private readonly logger: LoggerService,
|
|
) {}
|
|
|
|
canActivate(context: ExecutionContext): boolean {
|
|
const requiredRoles = this.reflector.getAllAndOverride<UserRole[]>(ROLES_KEY, [
|
|
context.getHandler(),
|
|
context.getClass(),
|
|
]);
|
|
|
|
if (!requiredRoles || requiredRoles.length === 0) {
|
|
return true;
|
|
}
|
|
|
|
const request = context.switchToHttp().getRequest();
|
|
const user = request.user;
|
|
const hasRole = requiredRoles.includes(user?.role);
|
|
|
|
if (!hasRole) {
|
|
const ip = request.ip || request.headers?.['x-forwarded-for'] || 'unknown';
|
|
const handler = context.getHandler().name;
|
|
const controller = context.getClass().name;
|
|
this.logger.warn(
|
|
`Access denied: userId=${user?.sub ?? 'unknown'}, role=${user?.role ?? 'none'}, ` +
|
|
`required=${requiredRoles.join(',')}, action=${controller}.${handler}, ip=${ip}`,
|
|
'RolesGuard',
|
|
);
|
|
}
|
|
|
|
return hasRole;
|
|
}
|
|
}
|