Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

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,721 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.