Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Promisifying bcrypt-nodejs with Bluebird

I'm using NodeJS, with bcrypt-nodejs (https://github.com/shaneGirish/bcrypt-nodejs) and Bluebird for promises. Came up with this code and been wondering if there is better way to do the same thing. I have module with:

var Promise = require("bluebird"),
    bcrypt = Promise.promisifyAll(require('bcrypt-nodejs'));

// ....[some othe code here]

    Users.prototype.setPassword = function(user) {

        return bcrypt.genSaltAsync(10).then(function(result) {
            return bcrypt.hashAsync(user.password, result);
        });

    };

then from another module I call users.setPassword as below:

app.post('/api/v1/users/set-password', function(req, res, next) {
    users.setPassword(req.body).then(function(result) {

        // Store hash in your password DB.
        console.log(result[1]);

        res.json({
            success: true
        })
    })
        .catch(function(err) {
            console.log(err);
        });
});

It always ends up with "[Error: No callback function was given.]" message as bcrypt.hashAsync seems to require 4 parameters. Original, non-promisified hash method requires 3 only though. When I add empty callback to hashAsync, it works fine:

Users.prototype.setPassword = function(user) {

    return bcrypt.genSaltAsync(10).then(function(result) {
        return bcrypt.hashAsync(user.password, result,function() {});
    });

};

Is there any better way to do this, without providing empty callback as above?

EDIT:

In response to Bergi's comment.. the function will set password eventually, I just didn't get that far when posted the question. Now got this far, please let me know if something is not quite right though:

 Users.prototype.setPassword = function(user) {


        return bcrypt.genSaltAsync(10).then(function(result) {
            return bcrypt.hashAsync(user.password, result, null);
        })
        .then(function(result) {
                // store in database
                console.log("stored in database!");
                return result;
            });

    };
like image 738
spirytus Avatar asked Jul 18 '14 06:07

spirytus


1 Answers

bcrypt.hashAsync seems to require 4 parameters. Original, non-promisified hash method requires 3 only though.

It's the other way round rather. From the docs:

hash(data, salt, progress, cb)

  • data - [REQUIRED] - the data to be encrypted.
  • salt - [REQUIRED] - the salt to be used to hash the password.
  • progress - a callback to be called during the hash calculation to signify progress
  • callback - [REQUIRED] - a callback to be fired once the data has been encrypted.

The original method took 4 arguments, hashAsync will take 3 and return a promise.

However, in your code you were only passing two. You don't need to pass an empty function though, that the parameter is not [REQUIRED] means you can pass null (or any other falsy value) for it. bcrypt will create such an empty function itself. So use

function (data) {
    return bcrypt.genSaltAsync(10).then(function(result) {
        return bcrypt.hashAsync(data.password, result, null);
    });
}
like image 50
Bergi Avatar answered Sep 28 '22 14:09

Bergi