Crud: Exclude() at entity is also exclude data at inserting to database

Created on 24 Mar 2020  路  5Comments  路  Source: nestjsx/crud

Hello. I'm Happy to using CRUD.

I have some question about using Exclude().

The wiki tells us to use Exclude() to exclude the value when returning the entity's value to the user.

However, if Exclude() is Annotated on an entity column, the data is excluded during the process of inserting data and marked as DEFAULT at TypeOrm Logging. Therefore, an error occurs on a column without a DEFAULT value.

Is this intended? Is it a bug?

I can replace it using the DTO and Serialize options, but I think you should be able to use the usage from the wiki as well.

My understanding is Annotated Exclude() is hide data to User when serialized. and not banning data when inserting. Is it correct?

Entity

import { Column, Entity } from "typeorm";
import { Exclude } from 'class-transformer';

@Entity("flag", { schema: "crypto" })
export class Flag {
  // ...
  @Exclude()
  @Column("int", { primary: true, name: "id" })
  id: number;

  @Column("int", { name: "idn", nullable: true })
  idn: number | null;
  // ...
}

DTO

export class FlagDto {
   // ...
    @IsNumber()
    id: number;
    idn: number;
  //...
}

Controller

@Crud({
    model: {
        type: Flag
    },
    dto: {
        create: FlagDto
    }
})
@UseGuards(AuthGuard)
@Controller('flags')

request body*

{
    "id": 15,
    "idn": 159123,
    "defaultUse": 1,
    "apiUse": 0,
    "officeUse": 0
}

typeorm log

query: START TRANSACTION
query: INSERT INTO `flag`(`id`, `idn`, `default_use`, `default_use_change_at`, `api_use`, `api_use_change_at`, `office_use`, `office_use_change_at`, `updated_at`, `created_at`)
VALUES (DEFAULT, ?, ?, DEFAULT, ?, DEFAULT, ?, DEFAULT, DEFAULT, DEFAULT)
-- PARAMETERS: [159123,1,0,0]
query failed: INSERT INTO `flag`(`id`, `idn`, `default_use`, `default_use_change_at`, `api_use`, `api_use_change_at`, `office_use`, `office_use_change_at`, `updated_at`, `created_at`)
VALUES (DEFAULT, ?, ?, DEFAULT, ?, DEFAULT, ?, DEFAULT, DEFAULT, DEFAULT)
-- PARAMETERS: [159123,1,0,0]
error: Error: ER_NO_DEFAULT_FOR_FIELD: Field 'id' doesn't have a default value

Most helpful comment

solution for this issue without "serialize option" is this.

import {Exclude} from "class-transformer";

export class User {

    id: number;

    email: string;

    @Exclude({ toPlainOnly: true })
    password: string;
}

when CRUD serlizing entity, it excluded by class-transformer only when entity is responsed,

All 5 comments

Hi, thanks. I'm happy you find this lib useful.
According to the wiki, you can exclude properties from a response in query options or in your entity - that's correct.
But also you can use serialize options. I think that is what you need.

solution for this issue without "serialize option" is this.

import {Exclude} from "class-transformer";

export class User {

    id: number;

    email: string;

    @Exclude({ toPlainOnly: true })
    password: string;
}

when CRUD serlizing entity, it excluded by class-transformer only when entity is responsed,

Hello, I have same issue here.I know serialize may be a useful method. but in my project, there is some addtional route, like that:

@Crud({
  model: {
    type: Admin,
  },
  query: {
    exclude: ['pwd'] // is only works for crud route
  },
})
@Controller('admin')
export class AdminController {
  constructor(public service: AdminService) {}

  get base(): CrudController<Admin> {
    return this
  }

  @Post('login')
  @ValidatePipe()
  login(@Body() loginDto: LoginDto) {
    return this.service.login(loginDto)
  }
}

I want add /login route, if success, return this admin and a token

I want to exclude the pwd either, so I add @Exclude() at the entity

part of my entity:

{
  ...

  @Exclude()
  @IsOptional({ groups: [UPDATE] })
  // @IsString({ always: true })
  // @Length(8, 20, { always: true })
  @Column()
  pwd: string

  @BeforeInsert()
  hashPassword() {
    console.log(this.pwd)  // when use @Exclude(), seems this.pwd was seted to undefined
    this.pwd = crypto.createHmac('sha256', this.pwd).digest('hex')
  }
}

It will recieve some error

So, can I use Exclude here?

Hello, I have same issue here.I know serialize may be a useful method. but in my project, there is some addtional route, like that:

@Crud({
  model: {
    type: Admin,
  },
  query: {
    exclude: ['pwd'] // is only works for crud route
  },
})
@Controller('admin')
export class AdminController {
  constructor(public service: AdminService) {}

  get base(): CrudController<Admin> {
    return this
  }

  @Post('login')
  @ValidatePipe()
  login(@Body() loginDto: LoginDto) {
    return this.service.login(loginDto)
  }
}

I want add /login route, if success, return this admin and a token

I want to exclude the pwd either, so I add @exclude() at the entity

part of my entity:

{
  ...

  @Exclude()
  @IsOptional({ groups: [UPDATE] })
  // @IsString({ always: true })
  // @Length(8, 20, { always: true })
  @Column()
  pwd: string

  @BeforeInsert()
  hashPassword() {
    console.log(this.pwd)  // when use @Exclude(), seems this.pwd was seted to undefined
    this.pwd = crypto.createHmac('sha256', this.pwd).digest('hex')
  }
}

It will recieve some error

So, can I use Exclude here?

adding {toPlainOnly: true} to@Exclude()`.
it means "when i class DTO transforming to plain json string, i exclude this property."

if this not work, adding interceptor ClassSerializerInterceptor at route.
@UseInterceptors(ClassSerializerInterceptor)

https://docs.nestjs.com/techniques/serialization

@aim-leo you should see this and @si-hyeon-ee has already posted an answer before your comment

Was this page helpful?
0 / 5 - 0 ratings

Related issues

terapepo picture terapepo  路  3Comments

btd1337 picture btd1337  路  4Comments

basvdijk picture basvdijk  路  5Comments

rainercedric23 picture rainercedric23  路  3Comments

MeMeMax picture MeMeMax  路  4Comments