feat: implement JWT guard

master
shancheas 2023-02-09 17:28:20 +07:00
parent e2e031a0fc
commit 5bbe9b2970
5 changed files with 110 additions and 0 deletions

View File

@ -0,0 +1 @@
export const UNPROTECTED_URL = 'unprotected_url';

View File

@ -0,0 +1,13 @@
import { SetMetadata } from '@nestjs/common';
import { UNPROTECTED_URL } from '../../constants';
/**
* This decorator will exclude the request from token check
*
* NOTE:
* Because the request does'nt provide token,
* the side effect are, function can't access `UserProvider`
* or `UserProvider` will return null
*/
export const Unprotected = (isUnprotected = true) =>
SetMetadata(UNPROTECTED_URL, isUnprotected);

View File

@ -0,0 +1,70 @@
import {
Injectable,
CanActivate,
ExecutionContext,
UnauthorizedException,
Scope,
Logger,
} from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Observable } from 'rxjs';
import { SessionService, UsersSession } from 'src/core/sessions';
import { UNPROTECTED_URL } from '../constants';
@Injectable({ scope: Scope.REQUEST })
export class JWTGuard implements CanActivate {
constructor(
protected readonly session: SessionService,
protected readonly reflector: Reflector,
) {}
protected userSession: UsersSession;
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
/**
* Check if access url is protected or not
* By default `isUnprotected` equals `false`
*/
const isUnprotected = this.reflector.getAllAndOverride<boolean>(
UNPROTECTED_URL,
[context.getHandler(), context.getClass()],
);
if (isUnprotected) return true;
/**
* Check if request give the token or not
* If there is not token in request, the transaction is failed
* and return 401 `Unauthorize`
*/
const request = context.switchToHttp().getRequest();
const authorization = request.headers['authorization'];
if (!authorization)
throw new UnauthorizedException({
code: 10002,
message: 'Access denied, please login first!',
error: 'TOKEN_NOT_PROVIDE',
});
const [, token] = authorization.split(' ');
/**
* Verify if token is valid token from login
* if the token is'nt valid token, the transaction is failed
* and return 401
*/
try {
this.userSession = this.session.verifyToken(token);
Logger.log(`Access from ${this.userSession.name}`, 'AuthGuard');
return true;
} catch (error) {
throw new UnauthorizedException({
code: 10001,
message:
'You cant access this endpoint, because authentication inst valid',
error: 'INVALID_TOKEN',
});
}
}
}

View File

@ -0,0 +1,23 @@
import { Injectable, ExecutionContext } from '@nestjs/common';
import { Observable } from 'rxjs';
import { JWTGuard } from './jwt.guard';
@Injectable()
export class RolesGuard extends JWTGuard {
canActivate(
context: ExecutionContext,
): boolean | Promise<boolean> | Observable<boolean> {
super.canActivate(context);
/**
* Create function to check if `this.userSession` have access
* to Read / Create / Update / and Other Action
*/
/**
* Assign rules to session, So Query can take the rules and give
* the data base on user request
*/
return true;
}
}

3
src/core/guards/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './domain/jwt.guard';
export * from './constants';
export * from './domain/decorators/unprotected.guard';