Search code examples
nestjs

how to properly set up the guards in nestJs?


need some help. I'm getting data from the front. here's my controller in nestjs:

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Post()
  @UseGuards(ValidationGuard)
  @UseInterceptors(FileInterceptor('photo'))
  async create(
    @Body() createUserDto: CreateUserDto,
    @UploadedFile(
      new ParseFilePipe({
        fileIsRequired: true,
        validators: [
          new FileTypeValidator({ fileType: 'image/jpeg' }),
          new MaxFileSizeValidator({ maxSize: 5120 }),
        ],
      }),
    )
    file: Express.Multer.File,
  ) {
    console.log('createUserDto', createUserDto);
    console.log('file', file);
    // return this.userService.create(createUserDto, file);
  }
}

here's my guard at nestjs:

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { UserService } from '../../user/user.service';
import { isEmail, length } from 'class-validator';
import { FailedValidatorException } from '../exeptions/exceptions';

@Injectable()
export class ValidationGuard implements CanActivate {
  constructor(private usersService: UserService) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const req = context.switchToHttp().getRequest<any>();

    console.log('req.file', req.file);
    console.log('req.body', req.body);

    const { name, email } = req.body;

    if (!length(name, 2, 60)) {
      throw new FailedValidatorException({
        name: ['The name must be at least 2 characters.'],
      });
    }

    if (!isEmail(email)) {
      throw new FailedValidatorException({
        email: ['The email must be a valid email address.'],
      });
    }

    return true;
  }
}

Guard "ValidationGuard" doesn't let it go any further. Says there's no data.In consoles: console.log('req.file', req.file); - undefined console.log('req.body', req.body); - {}

If I disable guard, then in the consoles. console.log('createUserDto', createUserDto); console.log('file', file); the data is there. Can you tell me what I'm doing wrong?


Solution

  • You are sending FormData, which is read by nestJS only when @UseInterceptors(FileInterceptor('photo')) is called. My suggestion would be to use class-validator validations with nestJS to validate the request body fields instead of guards.

    And yes, by the rules of NestJS, guards are interpreted before interceptors.

    If you have any questions or want a specific implementation, let`s discuss them in the comments so you resolve your problem.