feat: add admin module
This commit is contained in:
@@ -1 +1,2 @@
|
||||
export const IS_PUBLIC_KEY = 'isPublic';
|
||||
export const ROLES_KEY = 'roles';
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import { Role } from '@/common/enums/roles.enum';
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
import { ROLES_KEY } from '../constants';
|
||||
|
||||
export const Roles = (...roles: Array<Role>) => SetMetadata(ROLES_KEY, roles);
|
||||
@@ -1,8 +1,14 @@
|
||||
import { IS_PUBLIC_KEY } from '../constants';
|
||||
import { Role } from '@/common/enums/roles.enum';
|
||||
import { IS_PUBLIC_KEY, ROLES_KEY } from '../constants';
|
||||
import { JwtAuthGuard } from './jwt-auth.guard';
|
||||
import { ExecutionContext, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ExecutionContext,
|
||||
ForbiddenException,
|
||||
Injectable,
|
||||
} from '@nestjs/common';
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import type { Request } from 'express';
|
||||
import { User } from '@/modules/users/entities/user.entity';
|
||||
|
||||
@Injectable()
|
||||
export class GlobalAuthGuard extends JwtAuthGuard {
|
||||
@@ -15,9 +21,7 @@ export class GlobalAuthGuard extends JwtAuthGuard {
|
||||
super();
|
||||
}
|
||||
|
||||
canActivate(
|
||||
context: ExecutionContext,
|
||||
): boolean | Promise<boolean> | Observable<boolean> {
|
||||
async canActivate(context: ExecutionContext): Promise<boolean> {
|
||||
const isPublic = this.reflector.getAllAndOverride<boolean>(IS_PUBLIC_KEY, [
|
||||
context.getHandler(),
|
||||
context.getClass(),
|
||||
@@ -27,6 +31,24 @@ export class GlobalAuthGuard extends JwtAuthGuard {
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.canActivate(context);
|
||||
await super.canActivate(context);
|
||||
|
||||
const requiredRoles = this.reflector.getAllAndOverride<Array<Role>>(
|
||||
ROLES_KEY,
|
||||
[context.getHandler(), context.getClass()],
|
||||
);
|
||||
|
||||
if (requiredRoles && requiredRoles.length > 0) {
|
||||
const request = context.switchToHttp().getRequest<Request>();
|
||||
const user = request.user as User;
|
||||
|
||||
const hasRole = requiredRoles.includes(user.role);
|
||||
|
||||
if (!hasRole) {
|
||||
throw new ForbiddenException('auth.errors.accessDenied');
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,5 @@ lang: fa
|
||||
|
||||
{
|
||||
"phone": "09333026363",
|
||||
"password": "rad1.3.5"
|
||||
"password": "Password1@"
|
||||
}
|
||||
@@ -1,6 +1,11 @@
|
||||
POST http://localhost:3000/auth/refresh
|
||||
Content-Type: application/json
|
||||
|
||||
// {
|
||||
// "access": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJwaG9uZSI6IjA5MzMzMDI2MzYzIiwiaWF0IjoxNzgwMjIzNDExLCJleHAiOjE3ODAyMjcwMTEsImF1ZCI6ImxvY2FsaG9zdCIsImlzcyI6ImxvY2FsaG9zdCJ9.FNTIrk6FKO8P88yKnRCybZ6E5N3KlJaCHqZt5DMVgds",
|
||||
// "refresh": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJqdGkiOiJmZDRjZGViYS1iMjUzLTQ5MjgtOGIxYS0yZTJhZDMwOTIzYzMiLCJpYXQiOjE3ODAyMjM0MTEsImV4cCI6MTc4MTA4NzQxMSwiYXVkIjoibG9jYWxob3N0IiwiaXNzIjoibG9jYWxob3N0In0.EO0OpjQix794Y7yVZ8pjLH5HngYfCTwu3lonEfXtLIQ"
|
||||
// }
|
||||
|
||||
{
|
||||
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjksImp0aSI6IjljOTY5OWRhLWI0NTgtNDc0Ny04YTRkLTQyODQxMDllOTVkZCIsImlhdCI6MTc3ODMwNDMyNSwiZXhwIjoxNzc5MTY4MzI1LCJhdWQiOiJsb2NhbGhvc3QiLCJpc3MiOiJsb2NhbGhvc3QifQ.oiHuj3vJRQl7rG8H0fFEfU9cG91KrLGdXqNAYFGTXVA"
|
||||
"refreshToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOjEwLCJqdGkiOiIyZjQ1YzcxMi01ZGQzLTRhY2ItYjExYS04ZDA5YTc3YTVmYTciLCJpYXQiOjE3Nzk5NTY1OTksImV4cCI6MTc4MDgyMDU5OSwiYXVkIjoibG9jYWxob3N0IiwiaXNzIjoibG9jYWxob3N0In0.GX4kSCUCIvBVq9l4lQ8dkETvFZ1NwBIm9NGOIjBsQCc"
|
||||
}
|
||||
|
||||
@@ -2,6 +2,6 @@ POST http://localhost:3000/auth/verify-otp
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"phone": "09121111114",
|
||||
"otp": "99696"
|
||||
"phone": "09333026363",
|
||||
"otp": "44875"
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
RefreshTokenPayload,
|
||||
} from '../interfaces/jwt.interface';
|
||||
import { AuthRedisProvider } from './auth-redis.provider';
|
||||
import { AppResponse } from '@/common/responses';
|
||||
|
||||
@Injectable()
|
||||
export class GenerateTokenProvider {
|
||||
@@ -75,6 +76,6 @@ export class GenerateTokenProvider {
|
||||
),
|
||||
]);
|
||||
|
||||
return { access, refresh };
|
||||
return new AppResponse({ access, refresh });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { HashingProvider } from '@/common/modules/hashing/providers/hashing.prov
|
||||
import { GenerateTokenProvider } from './generate-token.provider';
|
||||
import { randomUUID } from 'crypto';
|
||||
import { I18nService } from 'nestjs-i18n';
|
||||
import { AppResponse } from '@/common/responses';
|
||||
|
||||
@Injectable()
|
||||
export class LoginProvider {
|
||||
@@ -57,10 +58,10 @@ export class LoginProvider {
|
||||
}
|
||||
|
||||
if (!password) {
|
||||
return {
|
||||
newUser: false,
|
||||
message: this.i18nService.translate('auth.messages.sendPass'),
|
||||
};
|
||||
return new AppResponse(
|
||||
{ newUser: false },
|
||||
this.i18nService.translate('auth.messages.sendPass'),
|
||||
);
|
||||
}
|
||||
|
||||
const isPasswordCorrect = await this.hashingProvider.compare(
|
||||
|
||||
Reference in New Issue
Block a user