Node.js/NestJs
[User] Model #3 Create Account (+ Hashing Password)
Ykie
2023. 4. 6. 14:13
728x90
users.service.ts / users.resolve.ts
Password Hashing
password를 db에 저장할 때 그대로 저장하지 않는다!! 매우 큰 보안적 위험이 있기 때문에!
'123' ➡ hashing ➡ 'xxxxxxxxxxxxxxxxxxxxxxxx' (one way function)
⬅⬅⬅ 이 방향으로 복구 할 수 없다.
// user.entity.ts
@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) {
throw new InternalServerErrorException();
}
}
}
// npm i bcrypt, npm i @types/bcrypt -D
// import * as bcrypt from 'bcrypt';
TypeOrm - 모든 Entity는 특정 이벤트를 listen하는 커스텀 로직 메서드를 가질 수 있다.
@beforeInsert()
- 이 Entity 삽입 전에 데코레이터가 적용되는 메서드를 호출.
GraphQL을 통해 createAccount를 진행하면 password 항목이 변환되어 DB에 저장됨을 확인할 수 있다.
service에서 [ok, error] return - error handling.
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User) private readonly users: Repository<User>,
) {}
async createAccount({
email,
password,
role,
}: CreateAccountInput): Promise<[boolean, string?]> {
try {
const exist = await this.users.findOne({ where: { email } });
if (exist) {
return [false, 'There is a user with that email already'];
}
await this.users.save(this.users.create({ email, password, role }));
return [true];
} catch (err) {
return [false, "Couldn't create account"];
}
}
}
resolver가 하는 일은 input을 가지고 output을 내보내는 것 뿐
@Mutation((returns) => CreateAccountOutput)
async createAccount(
@Args('input') createAccountInput: CreateAccountInput,
): Promise<CreateAccountOutput> {
try {
const [ok, error] = await this.userService.createAccount(
createAccountInput,
);
return { ok, error };
} catch (error) {
return { ok: false, error };
}
}
728x90