Add permissions handling to AdminAuthGuard and RoleController; refactor DatabaseSeeder to utilize enums for permissions
This commit is contained in:
@@ -5,6 +5,7 @@ import { CreateRoleDto } from '../dto/create-role.dto';
|
||||
import { UpdateRoleDto } from '../dto/update-role.dto';
|
||||
import { FindRolesDto } from '../dto/find-roles.dto';
|
||||
import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
||||
import { Permissions } from 'src/modules/auth/decorators/permissions.decorator';
|
||||
|
||||
@UseGuards(AdminAuthGuard)
|
||||
@ApiBearerAuth()
|
||||
@@ -13,6 +14,7 @@ import { AdminAuthGuard } from 'src/modules/auth/guards/adminAuth.guard';
|
||||
export class RoleController {
|
||||
constructor(private readonly roleService: RoleService) {}
|
||||
|
||||
@Permissions('create-role')
|
||||
@Post()
|
||||
@ApiOperation({ summary: 'Create a new role' })
|
||||
@ApiBody({ type: CreateRoleDto })
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
|
||||
export const PERMISSIONS_KEY = 'permissions';
|
||||
|
||||
export const Permissions = (...permissions: string[]) =>
|
||||
SetMetadata(PERMISSIONS_KEY, permissions);
|
||||
@@ -1,8 +1,19 @@
|
||||
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException, Inject } from '@nestjs/common';
|
||||
import {
|
||||
CanActivate,
|
||||
ExecutionContext,
|
||||
Injectable,
|
||||
UnauthorizedException,
|
||||
Inject,
|
||||
Logger,
|
||||
ForbiddenException,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Request } from 'express';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { IAdminTokenPayload } from '../interfaces/IToken-payload';
|
||||
import { PERMISSIONS_KEY } from '../decorators/permissions.decorator';
|
||||
import { AdminService } from 'src/modules/admin/providers/admin.service';
|
||||
|
||||
export interface AdminAuthRequest extends Request {
|
||||
adminId: string;
|
||||
@@ -11,11 +22,17 @@ export interface AdminAuthRequest extends Request {
|
||||
|
||||
@Injectable()
|
||||
export class AdminAuthGuard implements CanActivate {
|
||||
private readonly logger = new Logger(AdminAuthGuard.name);
|
||||
|
||||
constructor(
|
||||
@Inject(JwtService)
|
||||
private readonly jwtService: JwtService,
|
||||
@Inject(ConfigService)
|
||||
private readonly configService: ConfigService,
|
||||
@Inject(ConfigService)
|
||||
|
||||
private readonly adminService: AdminService,
|
||||
private readonly reflector: Reflector,
|
||||
) {}
|
||||
|
||||
async canActivate(context: ExecutionContext) {
|
||||
@@ -28,21 +45,39 @@ export class AdminAuthGuard implements CanActivate {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
try {
|
||||
const payload = await this.jwtService.verifyAsync<IAdminTokenPayload>(token, {
|
||||
const payload = await this.jwtService
|
||||
.verifyAsync<IAdminTokenPayload>(token, {
|
||||
secret,
|
||||
})
|
||||
.catch(err => {
|
||||
this.logger.error('error in AdminAuthGuard', err);
|
||||
throw new UnauthorizedException('Invalid or expired token');
|
||||
});
|
||||
request['adminId'] = payload.adminId;
|
||||
request['restId'] = payload.restId;
|
||||
} catch {
|
||||
throw new UnauthorizedException();
|
||||
request['adminId'] = payload.adminId;
|
||||
request['restId'] = payload.restId;
|
||||
|
||||
// check if the user has the required permissions
|
||||
const requiredPermissions =
|
||||
this.reflector.getAllAndOverride<string[]>(PERMISSIONS_KEY, [context.getHandler(), context.getClass()]) ?? [];
|
||||
|
||||
if (!requiredPermissions || requiredPermissions.length === 0) return true;
|
||||
|
||||
const adminPermission = await this.adminService.getAdminPermissions(payload.adminId, payload.restId);
|
||||
if (!adminPermission || !Array.isArray(adminPermission)) {
|
||||
this.logger.error('No permissions found');
|
||||
throw new ForbiddenException('No permissions found');
|
||||
}
|
||||
|
||||
const hasPermission = requiredPermissions.every(p => adminPermission.includes(p));
|
||||
|
||||
if (!hasPermission) throw new ForbiddenException('You are not authorized to access this resource');
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log('error in AuthGuard', err);
|
||||
this.logger.error('error in AdminAuthGuard', err);
|
||||
throw new UnauthorizedException('Invalid or expired token');
|
||||
}
|
||||
}
|
||||
|
||||
private extractTokenFromHeader(request: Request): string | undefined {
|
||||
const [type, token] = request.headers.authorization?.split(' ') ?? [];
|
||||
return type === 'Bearer' ? token : undefined;
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CanActivate, ExecutionContext, Injectable, UnauthorizedException, Injec
|
||||
import { Request } from 'express';
|
||||
import { JwtService } from '@nestjs/jwt';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import { IAdminTokenPayload, ITokenPayload } from '../interfaces/IToken-payload';
|
||||
import { ITokenPayload } from '../interfaces/IToken-payload';
|
||||
|
||||
export interface AdminAuthRequest extends Request {
|
||||
adminId: string;
|
||||
@@ -37,6 +37,7 @@ export class AuthGuard implements CanActivate {
|
||||
} catch {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
console.log('error in AuthGuard', err);
|
||||
|
||||
Reference in New Issue
Block a user