Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
states.guard.ts 1.67 KiB
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,
      );
    }
  }
}