Nest: Invalid behaviors in Multipart-form transform and validation

Created on 27 Feb 2020  路  4Comments  路  Source: nestjs/nest

Bug Report

I encountered a couple of validation and transformation issues using multipart-forms. I collected them in the following points and an isolated sample project.

Current behavior

  1. if the content type is multipart-form then transform for the nested object doesn't work. (nested property postalAddress must be either object or array).
  2. As the multipart-form conversion doesn't happen automatically. I manually add the transform (CreateUser.dto.ts line 35), but then the validation doesn't work in the nested object (I have tried to post an empty field that was required and it passed the validation)
  3. If I force the Type for a number field (CreateUser.dto.ts line 28) then the empty value will be transformed to "0" that prevents from validate after if the parameter was empty or not.
  4. I can't validate the file in the DTO if it was empty, because the file is not part of the @Body.

Input Code

https://github.com/andras-danko-dh/nest-swagger-multipart-form

```CreateUser.dto.ts
export class CreateUser {

@ApiProperty({
description: 'The name of the user',
example: 'Who Knows'
})
@IsString()
@IsNotEmpty() //TODO: Why it is needed if its a required field?
readonly name: string;

@ApiProperty({
description: 'The email address of the owner',
example: '[email protected]'
})
@IsEmail()
readonly email: string;

@ApiPropertyOptional({
description: 'Age of the user',
example: 25
})
// @Type(() => Number) //TODO: Why should we do manually the type conversion?
@IsInt()
readonly age: number;

@ApiProperty({
description: 'Postal address'
})
// @Transform(value => JSON.parse(value)) //If we add it the transform works, but the validation didn't
@Type(() => Address) //TODO: Type conversion didn't work if we have multipart-form
@ValidateNested()
@IsNotEmptyObject() //TODO: Why it is needed if its a required field
readonly postalAddress: Address

@ApiProperty({
description: 'Avatar image of the user',
type: 'string',
format: 'binary'
})
@IsNotEmpty()
readonly avatar: any;

};
```

Expected behavior

  1. If in the Swagger descriptor a field type is an object then it should be converted to a json object automatically and validate based on the object type apart from the content type.
  2. The validation should also work on nested objects in case it was converted (maybe the first point resolved this too?)
  3. @Type conversion should keep the value as NaN/Null/Undefined if the field had no value
  4. Be able to validate that the file is not empty

Possible Solution

Environment


Nest version: 6.14.1

For Tooling issues:
- Node version: 12
- Platform:  Linux

Others:

needs triage

Most helpful comment

Dear @kamilmysliwiec, has any document to explain what to validate the file is not empty?

All 4 comments

@IsNotEmptyObject() //TODO: Why it is needed if its a required field

Because empty object is a value.

If in the Swagger descriptor a field type is an object then it should be converted to a json object automatically and validate based on the object type apart from the content type.

This issue/feature request can be reported here https://github.com/scottie1984/swagger-ui-express

@Type conversion should keep the value as NaN/Null/Undefined if the field had no value

The conversion is performed by the class-transformer library and I believe there is a reasoning behind this decision. Anyway, you can report an issue here https://github.com/typestack/class-transformer

// @Type(() => Number) //TODO: Why should we do manually the type conversion?

This is disabled by default. You can enable this though, see here https://github.com/typestack/class-transformer#implicit-type-conversion

This issue is not related to Nest specifically, but rather to class-transformer + class-validator

Hi,

Under the opening post, number 4 of Expected behaviour isn't addressed:
"Be able to validate that the file is not empty".

How can this be done, I have tried the following and it does not work:

    @Post()
    @UseInterceptors(FileInterceptor('image'))
    public async create(@Body() body: CreateImageDto, @UploadedFile() image: FileUploadDto ) {
        console.log({ image, body });
        console.log(typeof image);
        return 'hello';
    }
import {IsNotEmpty, IsNumber, IsString} from 'class-validator';
import {ApiProperty} from "@nestjs/swagger";

export abstract class FileUploadDto {

    @IsNotEmpty()
    @IsString()
    fieldname: string;

    @IsString()
    originalname: string;

    @IsString()
    encoding: string;

    @IsString()
    mimetype: string;

    @IsNumber()
    size: number;

    buffer: Buffer;
}
// FileUpload.dto.ts

Hi @kamilmysliwiec , could you comment on how @UploadedFile () works with dto and the use of class-validator and how @numman mentioned. I have seen that the fileFilter property of multer exists would that be the correct option?

Dear @kamilmysliwiec, has any document to explain what to validate the file is not empty?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ZenSoftware picture ZenSoftware  路  35Comments

fmeynard picture fmeynard  路  45Comments

szkumorowski picture szkumorowski  路  62Comments

xmlking picture xmlking  路  28Comments

j picture j  路  32Comments