microsoft / TypeScript-Node-Starter

A reference example for TypeScript and Node with a detailed README describing how to use the two together.
MIT License
11.29k stars 2.76k forks source link

User.ts - why Pre Middleware instead of setter for password? #344

Open gaborszita opened 2 years ago

gaborszita commented 2 years ago

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.

peterblazejewicz commented 2 years ago

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)