Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript

Damian Wynter
Damian Wynter
15,803 Points

Having some scope issues

Hey guys i need some extra eyes on this code here. I am using mongoose and express to create a REST API. The issue i am having is that, i am trying to use bcrypt to hash the password before its saved. Below is my code, inside the bcrypt.hash function the hashed password is stored in user, but once its finished with that function the value in user is in plaintext.

Any ideas?

userSchema.pre('save', function (next) {
    let user = this;
    // only hash the password if it has been modified (or is new)
    if (!user.isModified('password')) return next();
    bcrypt.genSalt(10, function(err, salt) {
        bcrypt.hash(user.password, salt, function(err, hash) {
            user.password = hash;
            console.log(user.password);
        });
    });

    this.password = user.password;
    next();
});

1 Answer

Samuel Ferree
Samuel Ferree
31,722 Points

I don't think it's a scope issue, I think it's a race condition.

Let's look at the signature for the bcrypt's gen salt method, and the hash method

  bcrypt.genSalt(count, callback);
  bcrypt.hash(value, salt, callback);

So what you're doing is calling the genSalt function, and passing in a callback function to execute when it's finished then, inside that function, you're calling hash and giving it another callback function to execute when it also finishes, but because javascript is non-blocking as soon as your genSalt function is called initially, the next line of code executes immediately, which sets the password on 'this' before bcrypt can generate a salt and hash it.

userSchema.pre('save', function (next) {
    let user = this;
    // only hash the password if it has been modified (or is new)
    if (!user.isModified('password')) return next();
    bcrypt.genSalt(10, callback);

    //This is the next line of code
    this.password = user.password;
    next();
});

I don't actually think you need that last line before next()

Here's what I have in my project that I did for the User Authorization with MongoDB course.

// hash password before saving to database
UserSchema.pre('save', function(next) {
  let user = this;
  bcrypt.hash(user.password, null, null, (err, hash) => {
    if (err) {
      return next(err);
    }
    user.password = hash;
    next();
  });
});

It's worth noting that as I develop on windows, that I used the full javascript package 'bcrypt-nodejs' instead of the python and SDK dependent 'bcrypt' so the syntax may differ slightly.