User.ts - why Pre Middleware instead of setter for password?
gaborszita opened this issue · comments
In the src/models/User.ts
file, to hash the password using bcrypt, the program is using a Pre Middleware instead of a setter for the password:
/**
* Password hash middleware.
*/
userSchema.pre("save", function save(next) {
const user = this as UserDocument;
if (!user.isModified("password")) { return next(); }
bcrypt.genSalt(10, (err, salt) => {
if (err) { return next(err); }
bcrypt.hash(user.password, salt, undefined, (err: mongoose.Error, hash) => {
if (err) { return next(err); }
user.password = hash;
next();
});
});
});
Just wondering, why is it using a middleware instead of a simple setter? I think this was done this way so that it could use asynchronous bcrypt functions, but correct me if I'm wrong. If this is the reason, this was a really good design choice.
I believe this is well known pattern for Mongoose schema (pre/post hooks). This block of code will be eventually called by library,
removing a need from person implementing it to take care about lot of other details (when/why/how). So your controller actions are slim and focused on saving/validating user data model, while the rest is take out of the picture (here the salting/hashing)
You will find this in other frameworks as well (I'm more C# MVC, in ORM framework like Entity Framework this is done via framework interceptors, but can be done also via server middleware alone)