typestack/routing-controllers

fix: class-validator does not work on last version of RC

cellezam opened this issue · 10 comments

Description

Using the latest version of routing-controller, it seems that input validation is not working anymore. Here is my code and my setup

Minimal code-snippet showcasing the problem

export class GenerateIdentificationByEmailCommand {

  @Expose()
  @IsEmail()
  email: string;

  static setProperties(cmd: GenerateIdentificationByEmailCommand):  GenerateIdentificationByEmailCommand {
    return plainToClass( GenerateIdentificationByEmailCommand, cmd, { excludeExtraneousValues: true });
  }
}

@Post('/email')
  async generateIdentificationByEmail(
    @Res() res: Response,
    @Body({validate: true}) cmd: GenerateIdentificationByEmailCommand
  ) {
    const body = GenerateIdentificationByEmailCommand.setProperties(cmd);
    const result = await this._generateIdentification.execute({
      provider: {
        mode: AuthMode.BASIC,
        email: body.email,
      }
    })
    return res.status(201).send(result);
  }
  
  useExpressServer(app, {
    defaultErrorHandler: true,
    defaults: {
      nullResultCode: 400,
      undefinedResultCode: 204,
      paramOptions: {
        required: true,
      },
    },
    classTransformer: true,
    validation: true,
    routePrefix: "/oks",
    controllers: [
      UserController,
      CompanyController,
      MentorController,
      CommonController,
    ],
  });
 

Expected behavior

I expect when request api endpoint to throw if input validation failed

Actual behavior

It does not throw when i made http request. It returns a 201 response.

I cannot reproduce this with your example. Here is the snippet I'm running:

import 'reflect-metadata';
import {Expose, plainToClass} from "class-transformer";
import {IsEmail} from "class-validator";
import {Body, createExpressServer, JsonController, Post, Res} from "routing-controllers";
import {Response} from 'express';

export class GenerateIdentificationByEmailCommand {
    @Expose()
    @IsEmail()
    email!: string;

    static setProperties(cmd: GenerateIdentificationByEmailCommand): GenerateIdentificationByEmailCommand {
        return plainToClass(GenerateIdentificationByEmailCommand, cmd, {excludeExtraneousValues: true});
    }
}

@JsonController('')
export class TestController {
    @Post('/email')
    async generateIdentificationByEmail(
        @Res() res: Response,
        @Body({validate: true}) cmd: GenerateIdentificationByEmailCommand
    ) {
        const body = GenerateIdentificationByEmailCommand.setProperties(cmd);
        return res.status(201).send('test');
    }
}

const server = createExpressServer({
    defaultErrorHandler: true,
    defaults: {
        nullResultCode: 400,
        undefinedResultCode: 204,
        paramOptions: {
            required: true,
        },
    },
    classTransformer: true,
    validation: true,
    routePrefix: "/oks",
    controllers: [
        TestController
    ],
});

server.listen(8080, () => console.log('started'));

Running POST request to /oks/email with body

{
    "email2": "asd@asd.com"
}

Getting back an error:

{
  "errors": [
        {
            "target": {
                "email2": "asd@asd.com"
            },
            "property": "email",
            "children": [],
            "constraints": {
                "isEmail": "email must be an email"
            }
        }
    ]
}

Dependencies installed:

"dependencies": {
    "@types/express": "^4.17.17",
    "class-transformer": "^0.5.1",
    "class-validator": "^0.14.0",
    "routing-controllers": "^0.10.4",
    "ts-node": "^10.9.1",
    "typedi": "^0.10.0",
    "typescript": "^4.8.4"
  }

Could you please include more details?

I cannot get errors when passing an invalid request body. It seems like the validator not working

@magiskboy could you include an example that is not working?

Yep
This is to create application and express
image

and then I setup a controller called User with a route /login
image

I use httpie to call to localhost:3000/api/users/login
image

@magiskboy Do you have reflect-metadata imported?

yep, I imported reflect-metadata on top

@magiskboy how do you transpile ts? Using tsc or something else?

sorry, I setup the project incorrectly, my problem was solved

I have the same problem, could you tell me where you configured the project wrong?

I had problems with class-validator not working as well. In my case, I was running my project with tsx, which does not support emitDecoratorMetadata. I replaced it with ts-node, and everything works fine now!