import { Injectable, CanActivate, ExecutionContext, Scope, Logger, UnauthorizedException, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { Observable } from 'rxjs'; import { SessionService, UsersSession } from 'src/core/sessions'; import { UNPROTECTED_URL } from '../constants'; import { PrivilegeService } from './services/privilege.service'; @Injectable({ scope: Scope.REQUEST }) export class JWTGuard implements CanActivate { constructor( protected readonly session: SessionService, protected readonly reflector: Reflector, protected readonly privilege: PrivilegeService, ) {} protected isPublic = false; protected userSession: UsersSession; canActivate( context: ExecutionContext, ): boolean | Promise | Observable { /** * Check if access url is protected or not * By default `isUnprotected` equals `false` */ const isUnprotected = this.reflector.getAllAndOverride( UNPROTECTED_URL, [context.getHandler(), context.getClass()], ); this.isPublic = isUnprotected; this.session.setPublic(isUnprotected); 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', }); } } }