Mongoose ODM: Can't save encoded password because of async

I have the problem that the salt generation and password encoding is are ready when the document gets already persisted. => mongoosejs doesn't wait until the hashing is finished, so we have no passwords and salts in database (but I can console.log them :).

Is there something to avoid this behaviour?

  1. A waiter function?
  2. Or should I move the encoding part into some pre-save middleware?

encoding method

UserSchema.methods.encodePassword = function(password) {
    crypto.randomBytes(32, function(err, buf) {
        this.salt = buf.toString('hex');
        console.log(this.salt);
        crypto.pbkdf2(password, this.salt, 25000, 512, function(err, encodedPassword) {
            if (err) throw err;
            this.password = encodedPassword;
            console.log(this.password);
        }.bind(this));
    });
};

route action

// creates a new user
app.post('/users', function(req, res) {
    // create new user
    var user = new User();
    // assign post
    user.username = req.body.username;
    user.email = req.body.email;
    user.encodePassword(req.body.password);
    user.save(function(err, user) {
        console.log(user);
        if (!err) return res.send(err, 500);
        return res.json(user);
    });
});

You'll want encodePassword to take a callback so you can call it when you're done.

UserSchema.methods.encodePassword = function(password, callback) {
    crypto.randomBytes(32, function(err, buf) {
        this.salt = buf.toString('hex');
        console.log(this.salt);
        crypto.pbkdf2(password, this.salt, 25000, 512, function(err, encodedPassword) {
            if (err) return callback(err);
            this.password = encodedPassword;
            console.log(this.password);
            callback();
        }.bind(this));
    });
};

Now you can wait for it to be done in your route.

app.post('/users', function(req, res) {
    // create new user
    var user = new User();
    // assign post
    user.username = req.body.username;
    user.email = req.body.email;
    user.encodePassword(req.body.password, function(err) {
        if(err) { /* handle error */ }
        user.save(function(err, user) {
            console.log(user);
            if (!err) return res.send(err, 500);
            return res.json(user);
        });
    });
});