在更新MongoDB中的现有行时,如何在nestjs中防止来自客户端的不需要的对象属性

ulydmbyx  于 2022-10-22  发布在  Go
关注(0)|答案(5)|浏览(159)

创建新用户将忽略create-user.dto.ts中的非指定对象
但是,当我更新用户时,它会添加不需要的字段,如下所示:

// update-user.dto.ts
import { IsEmail } from 'class-validator';
import { Address } from '../model/address';

export class UpdateUserDto {
  firstName: string;

  lastName: string;

  @IsEmail(undefined, { message: 'Not a valid e-mail' })
  email: string;

  username: string;

  password: string;

  addresses: Address[];
}

这是来自用户服务的更新操作

// user.service.ts
  async update(data: UpdateUserDto) {
    try {
      this.logger.log(data);
      const id = '5c6dd9852d4f441638c2df86';
      const user = await this.userRepository.update(id, data);

      return { message: 'Updated your information' };
    } catch (error) {
      this.logger.log(error);
      throw new HttpException('', HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

这里是用户.Controler.ts

@Patch()
  @UsePipes(CustomValidationPipe)
  async update(@Body() data: UpdateUserDto) {
    return this.userService.update(data);
  }

客户端补丁数据:

// Unwanted junk from client
{
  "email": "newemail@gmail.com",
  "junk": "junk"
}

email将正确更新,但该行将具有值为junk的新的不需要的属性junk

wpcxdonn

wpcxdonn1#

我假设您在CustomValidationPipe中使用的是class-transformervalidate方法。
当您将whitelist选项传递给它时,validate将去除所有未知(->DTO类中没有注解)属性:

validate(userUpdate, { whitelist: true })

如果您希望抛出验证错误,而不是仅仅删除未知属性,则可以另外传递forbidNonWhitelisted选项。

validate(userUpdate, { whitelist: true, forbidNonWhitelisted: true });

在更新的情况下,您可能还希望使用skipMissingProperties: true,这样,当lastName不是更新的一部分时,验证将不会抛出错误。
请注意,您应该注解dto类中的所有属性,以使验证正常工作:

@IsString()
lastName: string;

@ValidateNested()
@Type(() => Address)
address: Address
yftpprvb

yftpprvb2#

不确定此行为/选项何时添加到NestJS中(可能是在原始问题和接受的答案之后添加的),但实现未知属性剥离的最佳方法是:

app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true,
  }),
);

就是这样。只要确保您的配置中有whitelist: true,您就不会得到任何未知/无效的属性。
还可以通过将另一个名为forbidNonWhitelisted的属性设置为true来完全停止请求。
更多信息请点击此处:https://docs.nestjs.com/techniques/validation#stripping-properties

dtcbnfnu

dtcbnfnu3#

对于像我这样仍在疑惑的新手,这里有一些实现它的简单方法:

@UsePipes(new ValidationPipe({ whitelist: true }))

将修饰器放在方法修饰器下(@Post、@Put等)
UsePipeValidationPipe都是导入的@nestjs/common

tzdcorbm

tzdcorbm4#

如果您还想为意外属性抛出错误,可以按如下方式进行配置:

app.useGlobalPipes(
 new ValidationPipe({
  whitelist: true,
  forbidNonWhitelisted: true,
  forbidUnknownValues: true
 })
);

意外的属性将导致

{
 "statusCode": 400,
 "message": [
    "property XXX should not exist"
 ],
 "error": "Bad Request"
}

有关讨论可在此处找到

bqujaahr

bqujaahr5#

我找到了解决方案:
以下是user.service.ts update()应该是什么样子:

const user = await this.userRepository.create(data);

在此之前需要添加

await this.userRepository.update(id, user);

以下是完整的user.service.ts更新()

async update(data: UpdateUserDto) {
    this.logger.log(data);

    // added for testing purposes (id should be based on active user)
    const id = '5c6ef2c823bf4e3414d65cd0';
    const user = await this.userRepository.create(data);
    await this.userRepository.update(id, user);

    return { message: 'Updated your information' };
  }

现在,任何不需要的属性都不会添加到行中

相关问题