5

I have mongoose schema like so

var mongoose  = require ('mongoose');
var bcrypt = require('bcryptjs');
var Schema = mongoose.Schema;
var SALT_WORK_FACTOR = 10;
var touristSchema = new Schema ({
    local: {
        email: String,
        password: String
    },
    facebook: {
        id: String,
        token: String,
        email: String,
        name: String,
    }
});


touristSchema.pre('save', function(next) {
    var user = this;
    console.log('bcrypt called by strategy', user);

// if user is facebook user skip the pasword thing.
if (user.facebook.token) {
    next();
}
// only hash the password if it has been modified (or is new)
if (!user.isModified('password') && !user.isNew){
console.log('I am in here', user.isNew);
return next();
}
// generate a salt
bcrypt.genSalt(SALT_WORK_FACTOR, function(err, salt) {
    console.log('I am in genSalt');

    if (err) return next(err);

    // hash the password using our new salt
    bcrypt.hash(user.local.password, salt, function(err, hash) {
        if (err) return next(err);

        // override the cleartext password with the hashed one
        user.local.password = hash;
        next();
    });
  });
 });

touristSchema.methods.comparePassword = function(candidatePassword, cb) {
    bcrypt.compare(candidatePassword, this.local.password, function(err, isMatch) {
        // console.log(this.local.password);

        if (err) return cb(err);
        cb(null, isMatch);
    });
};

module.exports = mongoose.model('users', touristSchema);

and login strategy like this

passport.use('local-login', new LocalStrategy({
        usernameField: 'email',
        passwordField: 'password',
        passReqToCallback: true
    },
    function(req, email, password, done) {
        process.nextTick(function() {
                User.findOne({ 'local.email': email }, function(err, user) {
                    if(err)
                        return done(err);
                    if(!user)
                        return done(null, false, req.flash('loginMessage', 'No User Found'));
                user.comparePassword(password, function(err, isMatch) {
          if (err) throw err;
                    if (isMatch) {
                            done(null, user);
                    }
                    else
                         done(null, false, req.flash('loginMessage', 'Incorrect password'));
      });
        });
    });
 }
));

everything is working as expected but when I try to log in it gives me error: TypeError: Cannot read property 'password' of undefined. Turns out that this.local is undefined. This is very strange as in touristSchema.pre hook we assigned var user = this and on logging this returned user document. When in compare method we are using touristSchema.methods.compare then this should must refer to the document as written in mongoose middleware docs too. I am beating my head over it for a couple of days now and have consumed every available help I could. Any help is greatly appreciated in advance. Thanks and yes my
mongnodb version is v3.2.15
mongoose version is 4.9.7
which looks compatible to me according to mongoose docs

Ammar Bayg
  • 105
  • 10

0 Answers0