如何在插入之前对密码进行哈希处理?

问题描述 投票:0回答:3

我正在将Nest.Js与TypeORM一起使用,并且我想先将密码哈希后再保存到数据库中。

我尝试使用事件装饰器@ BeforeInsert(),但是它对我不起作用,但是后来我发现它不起作用,因为我将DTO作为输入。

user.controller.ts

  @Post()
  async create(@Body() data: CreateUserDto, @Res() res) {

    // if user already exist
    const isUserExist = await this.service.findByEmail(data.email);
    if (isUserExist) {
      throw new BadRequestException('Email already exist');
    }

    // insert user
    this.service.create(data);

    // send response
    return res.status(201).json({
      statusCode: 201,
      message: 'User added Successfully',
    });
  }


user.service.ts

    create(data: CreateUserDto) {
        return this.userRepository.save(data)
    }

所以,我基本上是使用DTO保存数据。这就是为什么它不起作用的原因。

但是我想做的是将DTO映射到用户对象。所以,这就是我所做的。

  @Post()
  async create(@Body() data: CreateUserDto, @Res() res) {

    // Create User object
    const user = new User();

    // Map DTO to User object
    for (const [key, value] of Object.entries(data)) {
      user[key] = value;
    }

    // if user already exist
    const isUserExist = await this.service.findByEmail(user.email);
    if (isUserExist) {
      throw new BadRequestException('Email already exist');
    }

    // insert user
    this.service.create(user);

    // send response
    return res.status(201).json({
      statusCode: 201,
      message: 'User added Successfully',
    });
  }

create-user.dto.ts

import { IsEmail, IsNotEmpty, IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class CreateUserDto {
    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly firstName: string;
    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly lastName: string;
    @IsNotEmpty()
    @IsString()
    @IsEmail()
    @ApiProperty()
    readonly email: string;
    @IsNotEmpty()
    @IsString()
    @ApiProperty()
    readonly password: string;
}

有更好的方法吗?因为当前我必须在每种方法中编写代码才能对其进行映射。

node.js typescript nestjs dto typeorm
3个回答
1
投票

我首先将所有逻辑从控制器移到服务中。如果有的话,这将允许您在其他地方重用该逻辑(因为您更喜欢拥有该服务类)。

就个人而言,我会避免编写智能代码,因为它可以节省2或3行代码。当除了您之外的其他人不得不复查/重构时,这将是您的痛苦。只需编写一些易于理解的内容即可。

第三,我会避免使用诸如beforeInsert之类的魔术之类的东西。是的,它看起来很聪明,但您不清楚如何生成通行证。

  1. 如果您的实体与DTO的字段相同,那么拥有dto的好处是什么。我个人将避免公开实体的password属性。相反,我将在实体中使用changePassword(generator:IUserPassGenerator)方法。至于检查通行证,我会有类似verifyPass(validator:IPassChecker)方法。

  2. 我要避免的另一件事是二传手或公共道具,主要是因为这可能会导致您的实体进入无效状态。以您的情况为例其他人可能会使用md5哈希值更改password属性。毕竟,他们甚至可以使用完整的字符串来更改它。


0
投票

这是一种有效的方法。

您可以做的是从create方法中提取此逻辑,并创建某种Builder对象,以从DTO创建User对象,反之亦然,并在需要时调用Builder。


0
投票

我们可以使用Plain Object Literal包轻松地将Class Instances映射到'class-transformer'

答案:

async create(@Body() data: CreateUserDto, @Res() res) {

const user = plainToClass(User, data)

}
© www.soinside.com 2019 - 2024. All rights reserved.