Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | 20x 20x 20x 20x 90x 90x 23x 23x 1x 22x 22x 22x 1x 1x 21x 21x 1x 1x 20x 32x 20x 2x 2x 18x | import { Injectable, CanActivate, ExecutionContext, ForbiddenException, Logger } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { GqlExecutionContext } from '@nestjs/graphql';
@Injectable()
export class RolesGuard implements CanActivate {
private readonly logger = new Logger(RolesGuard.name);
constructor(private readonly reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const requiredRoles = this.reflector.getAllAndOverride<string[]>('roles', [
context.getHandler(),
context.getClass(),
]);
// No roles required - allow access
if (!requiredRoles || requiredRoles.length === 0) {
return true;
}
// Extract user from context (support both HTTP and GraphQL)
const request = context.getType() === 'http'
? context.switchToHttp().getRequest()
: GqlExecutionContext.create(context).getContext().req;
const user = request.user;
// User must be authenticated
if (!user) {
this.logger.warn('RolesGuard: No user found in request context');
throw new ForbiddenException('Authentication required');
}
// Normalize to an array of roles
// Support both `user.role` (string) and `user.roles` (string[])
const userRoles: string[] = Array.isArray(user.roles)
? user.roles
: (user.role ? [String(user.role)] : []);
// User must have at least one role
if (userRoles.length === 0) {
this.logger.warn(`RolesGuard: User ${user.id} has no roles assigned`);
throw new ForbiddenException('User has no roles assigned');
}
// Check if user has any of the required roles
const normalizedRequired = requiredRoles.map(String);
const hasRole = normalizedRequired.some((role) => userRoles.includes(role));
if (!hasRole) {
this.logger.warn(
`RolesGuard: User ${user.id} with roles [${userRoles.join(', ')}] ` +
`attempted to access resource requiring roles [${requiredRoles.join(', ')}]`
);
throw new ForbiddenException(
`Insufficient permissions. Required roles: ${requiredRoles.join(' or ')}`
);
}
return true;
}
} |