Cog Factory 2021. 9. 2. 12:33

common.entity.ts

import { Field, ObjectType } from '@nestjs/graphql';
import {
  CreateDateColumn,
  PrimaryGeneratedColumn,
  UpdateDateColumn,
} from 'typeorm';

@ObjectType()
export class CoreEntity {
  @PrimaryGeneratedColumn()
  @Field((type) => Number)
  id: number;

  @CreateDateColumn()
  @Field((type) => Date)
  createdAt: Date;

  @UpdateDateColumn()
  @Field((type) => Date)
  updatedAt: Date;
}

user.entity.ts

import {
  Field,
  InputType,
  ObjectType,
  registerEnumType,
} from '@nestjs/graphql';
import { IsBoolean, IsEmail, IsEnum, IsString } from 'class-validator';
import { BeforeInsert, Column, Entity } from 'typeorm';
import * as bcrypt from 'bcrypt';

import { CoreEntity } from 'src/common/entities/common.entity';
import { InternalServerErrorException } from '@nestjs/common';

export enum UserRole {
  Consumer = 'Consumer',
  Provider = 'Provider',
}

enum Language {
  Korean = 'Korean',
  English = 'English',
}

registerEnumType(UserRole, { name: 'UserRole' });
registerEnumType(Language, { name: 'Language' });

@InputType('UserInputType', { isAbstract: true })
@ObjectType()
@Entity()
export class User extends CoreEntity {
  @Column({ unique: true })
  @Field((type) => String)
  @IsEmail()
  email: string;

  @Column()
  @Field((type) => String)
  @IsString()
  password: string;

  @Column({ type: 'enum', enum: UserRole, default: UserRole.Consumer })
  @Field((type) => UserRole)
  @IsEnum(UserRole)
  role: UserRole;

  @Column({ default: false })
  @Field((type) => Boolean)
  @IsBoolean()
  verified: boolean;

  @Column({ default: Language.Korean })
  @Field((type) => Language)
  @IsEnum(Language)
  language: Language;

  @Column({ nullable: true })
  @Field((type) => String, { nullable: true })
  @IsString()
  bio?: string;
  
   @BeforeInsert()
  async hashPassword(): Promise<void> {
    if (this.password) {
      try {
        this.password = await bcrypt.hash(this.password, 10);
      } catch (e) {
        console.error(e);
        throw new InternalServerErrorException();
      }
    }
  }

  async checkPassowrd(password: string): Promise<boolean> {
    try {
      const ok = await bcrypt.compare(password, this.password);
      return ok;
    } catch (error) {
      console.error(error);
      throw new InternalServerErrorException();
    }
  }  
}

 

  • @Column()은 TypeORM의 Schema로 정의하는 decorator다. @Column()을 하고 밑에 field를 정의하면 db field에 등록된다.
  • @Field()는 graphql의 type을 정의한다.
  • @IsEmail(), @IsString() 등은 class-validator로 유효성 검사를 한다.
  • enum type은 registerEnumType(UserRole, { name: 'UserRole' });를 사용하여서 등록해서 쓸 수 있다.

 

  • entity 안에 method를 선언할 수 있다. ex) checkPassword
  • @BeforeInsert() decorator를 이용해서 데이터가 db에 저장되기 이전에 process 할 수 있다.
  • await bcrypt.hash() function이 있는데, password는 저장되기 전에 무조건 해시를 한 후 저장해야 한다.
    • Installation : $ npm i bcrypt

Validation

   Entity에서 @IsEmail()같이 validate를 하는 decorator가 있다.

  $ npm i class-transformer class-validator

두 개 모듈을 설치함으로써 사용할 수 있다. 그리고 app.useGlobalPipes(new ValidationPipe());를 추가한다.

참고 자료