import { Injectable, CanActivate, ExecutionContext, HttpException, HttpStatus, } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { Validator } from 'class-validator'; import { GameEntity } from '../game/game.entity'; @Injectable() export class StatesGuard implements CanActivate { constructor( private readonly reflector: Reflector, @InjectRepository(GameEntity) private gameRepository: Repository<GameEntity>, ) {} // Checks the state for gameId and grants access if it matches the criteria // allowed states are CREATED, STARTED, PAUSED, ENDED async canActivate(context: ExecutionContext): Promise<boolean> { // get game states that are allowed access, identified by @GameStates('state') decorators in controllers const states = this.reflector.get<string[]>('states', context.getHandler()); if (!states) { return true; } const request = context.switchToHttp().getRequest(); const gameId = request.params.id; // create a valifator const validator = new Validator(); // verify UUID if (!validator.isUUID(gameId)) { throw new HttpException('Game not found', HttpStatus.BAD_REQUEST); } const gameRef = await this.gameRepository.findOne({ id: gameId, }); // check that the gameState matches the criteria if (gameRef && states.includes(gameRef.state)) { return true; } else { throw new HttpException( `Game is set to ${ gameRef.state }, operation only valid in states ${states.join(', ')}`, HttpStatus.BAD_REQUEST, ); } } }