포시코딩

[TypeORM] BeforeInsert() - Encrypting Passwords in Entity 본문

Node.js

[TypeORM] BeforeInsert() - Encrypting Passwords in Entity

포시 2023. 12. 21. 09:21
728x90

 

 

 

지금까지는 회원가입 과정에서의 서비스 단에서 비밀번호를 암호화해왔다. 

 

기존 코드

auth.service.ts

import * as bcrypt from 'bcrypt';

@Injectable()
export class AuthService {

  async signupBuyer(body: signupBuyerDTO) {
    const { password } = body;
    const passwordHash = await this.hashPassword(password);

    body.passwordHash = passwordHash;

    // 회원가입 로직
  }
  
  private async hashPassword(password: string) {
    return bcrypt.hashSync(password, 10);
  }
}

 

하지만 TypeORM의 BeforeInsert() 데코레이터를 사용하면 좀 더 깔끔해진다. 

 

바뀐 코드

user.entity.ts

import * as bcrypt from 'bcrypt';

@InputType({ isAbstract: true })
@ObjectType()
@Entity()
export class User extends CoreEntity {
  
  // ...생략 
  
  @Column()
  @Field(type => String)
  password: string;

  @BeforeInsert()
  async hashPassword(): Promise<void> {
    try {
      this.password = await bcrypt.hash(this.password, 10);
    } catch (e) {
      console.log(e);
      throw new InternalServerErrorException();
    }
  }
}

 

users.service.ts

@Injectable()
export class UsersService {
  constructor(@InjectRepository(User) private readonly users: Repository<User>) {}

  async createAccount({ email, password, role }: CreateAccountInput): Promise<{ ok: boolean; error?: string }> {
    try {
      const exists = await this.users.findOne({ where: { email } });
      if (exists) {
        return { ok: false, error: 'There is a user with that email already' };
      }
      await this.users.save(this.users.create({ email, password, role }));
      return { ok: true };
      
    } catch (e) {
      return { ok: false, error: "Couldn't create account" };
    }
  }
}

 

typeorm의 Repository 클래스의 create 메서드를 통해 User entity를 만든 후 save 하면

DB에 insert 하기 전 @BeforeInsert() 데코레이터에 의해 hashPassword() 함수가 실행되면서 

비밀번호가 암호화 되는 방식이다. 

 

* NestJS, TypeORM, GraphQL 쓰는 환경임을 참고

* 비밀번호 암호화 뿐만 아니라 인증번호 생성 등에 대해서도 활용할 수 있다. 

 

verification.entity.ts

import { v4 as uuidv4 } from 'uuid';
import { Field, InputType, ObjectType } from "@nestjs/graphql";
import { CoreEntity } from "src/common/entities/core.entity";
import { BeforeInsert, Column, Entity, JoinColumn, OneToOne } from "typeorm";
import { User } from "./user.entity";

@InputType({ isAbstract: true })
@ObjectType()
@Entity()
export class Verification extends CoreEntity {
  @Column()
  @Field(type => String)
  code: string;

  @OneToOne(type => User)
  @JoinColumn()
  user: User;

  @BeforeInsert()
  createCode(): void {
    this.code = uuidv4();
  }
}
728x90