I have a code where I create a user and hash the password before saving.
userSchema.pre('save', async function(next) {
const user = this;
if (user.isModified('password')) {
user.password = await brcrypt.hash(user.password, BCRYPT_HASH_ROUND);
}
next();
});The userSchema could be any data model but the interesting part here is the pre('save'), ...
Lately, I’ve been playing around with Nestjs to use for my next project and I was trying to implement a user management with it.
Here’s my code when adding a new user
import { Repository, EntityRepository } from 'typeorm';
import { User } from './user.entity';
import { UserCredentialsDto } from './dto/user-credentials.dto';
import * as bcrypt from 'bcryptjs';
const BCRYPT_HASH_ROUND = 8;
@EntityRepository(User)
export class UserRepository extends Repository<User> {
async add(userCredentialsDTO: UserCredentialsDto): Promise<any> {
const { email, password } = userCredentialsDTO;
const user = new User();
user.email = email;
user.password = await bcrypt.hash(this.password, BCRYPT_HASH_ROUND);
try {
return await user.save();
} catch (e) {
if (e.code === '23505') {
throw new Error('Email already exists');
}
}
}
}In my code, I’m hashing the password explicity before executing the user.save() method. I want what I have in mongoose where I tapped in the pre-save event and hash the password from there.
To do this, I just need to use @BeforeInsert listener on my user entity like this
import {
BaseEntity,
Entity,
PrimaryGeneratedColumn,
Column,
BeforeInsert,
} from 'typeorm';
import * as bcrypt from 'bcryptjs';
const BCRYPT_HASH_ROUND = 8;
@Entity()
export class User extends BaseEntity {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true, length: 256 })
email: string;
@Column()
password: string;
@BeforeInsert()
async beforeInsert() {
this.password = await bcrypt.hash(this.password, BCRYPT_HASH_ROUND);
}
// imagine more code below
....Another benefit with this approach would be that the UserRepository doesn’t need to know anything about bcryptjs!