Ich verwende Nest.Js mit TypeORM und möchte mein Kennwort hashen, bevor ich in der Datenbank bleibe.

Ich habe versucht, den Ereignisdekorator @BeforeInsert () zu verwenden, aber es funktionierte nicht für mich, aber später stellte ich fest, dass es nicht funktionierte, weil ich ein DTO als Eingabe verwendete.

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)
    }

Ich habe also im Grunde ein DTO verwendet, um die Daten zu speichern. Deshalb hat es nicht funktioniert.

Ich möchte das DTO jedoch dem Benutzerobjekt zuordnen. Also, das habe ich getan.

  @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;
}

Gibt es dafür einen besseren Ansatz? Weil ich momentan den Code in jede Methode schreiben muss, um ihn abzubilden.

1
Istiyak Tailor 7 Feb. 2020 im 21:40

3 Antworten

Beste Antwort

Mit dem Paket 'class-transformer' können wir Plain Object Literal einfach Class Instances zuordnen

Antworten:

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

const user = plainToClass(User, data)

}
0
Istiyak Tailor 12 Feb. 2020 im 13:13

Dies ist ein gültiger Ansatz.

Sie können diese Logik aus der Erstellungsmethode extrahieren und eine Art Builder-Objekt erstellen, um Benutzerobjekte aus dem DTO zu erstellen und umgekehrt, und den Builder dort aufrufen, wo Sie ihn benötigen.

0
Arthur Almeida 7 Feb. 2020 im 18:49

Ich würde zuerst die gesamte Logik von meinem Controller in den Dienst verschieben. Auf diese Weise können Sie die Logik gegebenenfalls an anderen Stellen wiederverwenden (da Sie diese Serviceklasse bevorzugen).

Persönlich würde ich das Schreiben von Smart Code vermeiden, da ich dadurch 2 oder 3 Codezeilen einsparen kann. Wenn jemand anderes als Sie überprüfen / umgestalten müsste, wäre dies ein Schmerz im Rücken. Schreiben Sie einfach etwas, das leicht zu verstehen ist.

Drittens würde ich es vermeiden, magische Dinge wie beforeInsert zu verwenden. Ja, es mag klug aussehen, aber Sie machen nicht klar, wie der Pass generiert wird.

  1. Wenn Ihre Entität dieselben Felder wie Ihr DTO hat, was ist dann der Vorteil des dto. Persönlich würde ich vermeiden, die Passworteigenschaft der Entität offenzulegen. Stattdessen hätte ich eine changePassword-Methode (Generator: IUserPassGenerator) in der Entität. Für die Überprüfung des Passes hätte ich so etwas wie die Methode verifyPass (Validator: IPassChecker).

  2. Eine andere Sache, die ich vermeiden würde, wären Setter oder öffentliche Requisiten, hauptsächlich weil dies dazu führen könnte, dass Ihre Entität in einen ungültigen Zustand übergeht. In Ihrem Fall, z. Möglicherweise ändert eine andere Person die Kennworteigenschaft mit einem MD5-Hash. Schließlich können sie es sogar mit einer nicht zerhackten Zeichenfolge ändern.

1
Bogdan Ungureanu 7 Feb. 2020 im 18:56