Asif Ali
Asif Ali

Reputation: 1432

Mongoose .pre('save') not triggering - bcrypt

I have been trying to create a simple Authentication app but facing this issue of .pre('save') middleware not triggering at all when I'm trying to save the hashed password in Mongodb. Here's my Model.js File.

import mongoose from 'mongoose';
import bcrypt from 'bcryptjs';

const userSchema = new mongoose.Schema({
  auth_method: {
    type: String,
    enum: ['local', 'google', 'facebook'],
    required: true
  },
  email: {
    type: String,
    lowercase: true,
    unique: true
  },
  local: {
    password: {
      type: String
    }
  },
  google: {
    id: {
      type: String
    }
  },
  facebook: {
    id: {
      type: String
    }
  }
},
  {
    collection: 'Users'
  });

const userModel = module.exports = mongoose.model('Users', userSchema);

userSchema.pre('save', function (next) {
  console.log("this:",this); //  Nothing prints to the console here
  if (this.auth_method !== 'local') {
    next();
  }
  bcrypt.genSalt(10, function (error, salt) {
    if (error) throw error;
    bcrypt.hash(this.local.password, salt, function (err, hashPassword) {
      if (err) throw err;
      else {
        this.local.password = hashPassword;
        next();
      }
    });
  });
});

const comparePassword = (candidatePassword, hashPassword) => {
  return new Promise((resolve, reject) => {
    bcrypt.compare(candidatePassword, hashPassword, (err, isMatch) => {
      if (err) reject(err);
      resolve(isMatch);
    });
  });
};

const saveUser = (user) => user.save();

const findUserByEmail = (email) => userModel.findOne({ email });

const findUserById = (id, cb) => { userModel.findById(id, cb); };

module.exports = {
  userModel,
  comparePassword,
  saveUser,
  findUserByEmail,
  findUserById
};

Any help is appreciated, I have tried all possible solutions suggested in other threads, none worked including return next(this) Even in the database, there's no field for local: {password: 'hashedPassword'}

Upvotes: 0

Views: 2332

Answers (1)

Artur P.
Artur P.

Reputation: 896

You are compiling model const userModel = module.exports = mongoose.model('Users', userSchema); before creating userSchema.pre hook.

Correct order:

...
    userSchema.pre('save', function (next) {
      console.log("this:",this); //  Nothing prints to the console here
      if (this.auth_method !== 'local') {
        next();
      }
      bcrypt.genSalt(10, function (error, salt) {
        if (error) throw error;
        bcrypt.hash(this.local.password, salt, function (err, hashPassword) {
          if (err) throw err;
          else {
            this.local.password = hashPassword;
            next();
          }
        });
      });
    });
    const userModel = module.exports = mongoose.model('Users', userSchema);
...

Look at this simple code: http://devsmash.com/blog/password-authentication-with-mongoose-and-bcrypt

Upvotes: 4

Related Questions