-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Routing-Controllers + class-validator bug? #384
Comments
Having same issue. Validation isn't running implicitly in the controller. |
I think I might be seeing similar issue too. Tried running a version of the auto validation based on the example in the README: @JsonController()
class UserController {
@Post('/login')
login(@Body({validate: true}) user: User) {
console.log('this is a valid body');
return 'success!!!';
}
}
class User {
@IsEmail()
email: string;
@MinLength(6)
password: string;
}
createExpressServer({
controllers: [UserController]
}).listen(3000); No matter what I send in the POST request I get a success back. Not sure if I've missed something in the above code but for the life of me I can't get it to validate and throw an error. Validating manually through the class-validator does work though. |
The problem might not be in |
Exactly. I have similar issue. Parameters of my actions are custom classes (not interfaces) annotated with attributes like @minlength ... The problem is that parameters that I received are pure literal objects and not instances of my classes. So problem seems to be I force options (that normally default to true) during creation of express server :
|
Same for me. Group.tsimport { IsNotEmpty, IsUppercase, MaxLength } from 'class-validator';
import { Column, Entity, Index, OneToMany, PrimaryGeneratedColumn } from 'typeorm';
import { SubGroup } from './SubGroup';
@Entity({
name: 'pss_groups',
})
export class Group {
@PrimaryGeneratedColumn()
public id: number;
@Column({
length: 1,
name: 'name',
})
@Index({ unique: true })
@IsNotEmpty()
@MaxLength(1)
@IsUppercase()
public name: string;
@Column({
name: 'description',
})
public description: string;
@OneToMany(type => SubGroup, subGroup => subGroup.group)
public subGroups: SubGroup[];
} And here's my controller GroupController.tsimport { Body, HttpCode, JsonController, Post } from 'routing-controllers';
import { Service } from 'typedi';
import { Group } from '../models/Group';
import { GroupService } from '../services/GroupService';
@JsonController('/groups')
export class GroupController {
constructor(@Service() private groupService: GroupService) {
}
@HttpCode(201)
@Post('')
public async createGroup(@Body({ required: true, validate: true }) group: Group): Promise<Group> {
return this.groupService.createGroup(group);
}
} In result action is not validating data at all, even if I include validate function and use it on My app initialization app.tsconst expressApp = express();
expressApp.use(json({ limit: '50mb' }));
expressApp.use(urlencoded({ extended: true }));
useExpressServer(expressApp, {
cors: true,
routePrefix: env.app.routePrefix,
defaultErrorHandler: false,
classTransformer: true,
validation: true,
controllers: env.app.dirs.controllers,
middlewares: env.app.dirs.middlewares,
}); Any thoughts? |
Any News about this issue? |
The issue is caused because the version of class-validator that you have installed does not match the version of class-validator that routing-controllers is using. (see issue #424 and typestack/class-validator#166) For a temporary fix you can run the following commands:
Edit: This will not work if you are using class-transformer. If you are using class-transformer read below for a solution |
I've tried your solution, still same issue, @Body is not validated. |
@Andrew5569 Nope, doesn't work... |
I created an example: https://github.com/Andrew5569/rc-body-validation This is working for me |
Yup, that works @Andrew5569 but I have basically the exact same setup but with controller and the model in a separate file and it just doesn't want to work. |
@Andrew5569 |
So I have done few test and this is what I found:
So it seems to be a mix of class-validation / routing-controller changes breaking the validation, as the newer version of class-transformer works with routing-controller 0.7.6 and class-validator 0.7.3 @pleerock @NoNameProvided would you have any chance looking at this issue as it makes the stack (routing controller, class validator, class transfomers) non useable with latest version? Thanks again 👍 |
@nolazybits I don't think you will have a fix soon, looking at latest commit date. I forked it and just updated package.json versions to latest and it seems to work. This is the modified version you can use from npm until official release: https://www.npmjs.com/package/@mardari/routing-controllers |
@MardariG Im sorry but your changes doesnt work on my project. Sample: import { Body, Post, Controller } from '@mardari/routing-controllers';
import { MinLength, IsDefined, IsNotEmpty } from '../../../node_modules/class-validator';
export class User {
@IsNotEmpty({message: 'is empty'})
@IsDefined({message: 'is not defined'})
@MinLength(5, { message: 'FIRST NAME '})
public firstName: string;
public lastName: string;
public getName(): string {
return this.lastName + ' ' + this.firstName;
}
}
// tslint:disable-next-line:max-classes-per-file
@Controller('/user')
export class UserController {
@Post()
public post(@Body({required: true, validate: true}) user: User): number {
console.log('saving user ' + user.getName());
return 1;
}
} accepts
|
@konraddysput
Request: {email: "admin@admin.com", password: "admin"} gives validation error:
note: all classes are separate files, not sure if this can be problems; |
I think the problem isn't in class-validation or routing-controllers. Can you provide your |
|
Ok. Current version working well with:
Validation start working on my side and working really well. Key part is to use class-validator from version Following example showing how my express changes works: |
import {ActionParameterHandler} from "routing-controllers/ActionParameterHandler";
import {validateOrReject as validate, ValidationError} from "class-validator";
import {BadRequestError} from "routing-controllers";
/**
* issue https://github.com/typestack/routing-controllers/issues/384
* a copy of https://github.com/typestack/routing-controllers/blob/4a56d176db77bc081dfcd3d8550e8433b5bc476e/src/ActionParameterHandler.ts#L179-L199
* @param value
* @param paramMetadata
*/
ActionParameterHandler.prototype["validateValue"] = function (this: any, value: any, paramMetadata: any) {
const isValidationEnabled = (paramMetadata.validate instanceof Object || paramMetadata.validate === true)
|| (this.driver.enableValidation === true && paramMetadata.validate !== false);
const shouldValidate = paramMetadata.targetType
&& (paramMetadata.targetType !== Object)
&& (value instanceof paramMetadata.targetType);
if (isValidationEnabled && shouldValidate) {
const options = paramMetadata.validate instanceof Object ? paramMetadata.validate : this.driver.validationOptions;
return validate(value, options)
.then(() => value)
.catch((validationErrors: ValidationError[]) => {
const error: any = new BadRequestError(`Invalid ${paramMetadata.type}, check 'errors' property for more info.`);
error.errors = validationErrors;
error.paramName = paramMetadata.name;
throw error;
});
}
return value;
}; Temporarily solved this problem. I don't know why it works. |
What i did to fix it was to look in |
where exactly? Thanks in advance :) |
A temporary fix that's working for me is to remove
|
I found that it is sufficient to declare the dependency to class-validator to the same version as in routing-controllers: |
Worked for me tks !! |
I have similar issue and found that it could be caused by usage of |
I think the reason for the bug is that A proposed solution to A proposed solution to people who declare contracts in their api project: A proposed solution to people who keep contracts in a separate package that gets installed to their api: |
Anyone have better solution than this ? so far this is the only working solution for me. Dependencies are
|
Any better solution? Only import |
I've published To use it: I've sent a PR back to this abandoned lib, but doubt it'll ever be merged |
@adenhertog thank you very much for your solution. Maybe you could create a smaller PR with just that change and it would be merged. I'll be happy to poke them :) |
@adenhertog I've merged your changes in the |
that's great @jotamorais, thanks for reviving this lib! |
Published to NPM, the pre-release including your changes (tagged as 0.8.1-alpha.2 off of next branch). Please, update your package.json and try it out before I merge into master and publish v0.8.1 to NPM. |
I will close this issue as we made |
Hi there! controller method
EntityPostRequest definition
BaseCoreEntity
Employee entity
I don't know what the hell I'm doing worong, but for example, I can't even get 'age' key of Employee to get validates. I'm inserting ages of values higher than 120 and It doesn't thhrow an error, actually it inserts the entity into the database. So no validation exists. Can anyone guide me? |
Hi @juanitopons, if I'm right, the class-validator doesn't work with generics or unions, because it isn't possible to detect their types during the gathering metadata process of decorators. Therefore I would suggest you to simply split your code into two endpoints for a single record and for an array of records. if you want to have a single endpoint, then you need to change body structure to be for example: {
@ValidateNested()
item?: Employee,
@ValidateNested()
items?: Array<Employee>
} then it should work as you want. |
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
When using the automatic validation from routing-controllers for some reason the email "patch@patch" is valid when we are using these validators and the "patch" validator group
Doing it the manual way like so works however
The text was updated successfully, but these errors were encountered: