title: mongoose how to handle password encoding nicely?
body: <p>I want to refactor my user schema. The main reason for this decision is that I do not want to worry about password and salt generation. So I would like to move the encoding logic from the pre save handler to a setter. Unfortunately I do not have access from a setter to other properties of the object (like salt).</p>
  
  <p>So defaulting a salt does not work and encoding a password with a salt also not.</p>
  
  <p>My current implementation is:</p>
  
  <pre><code>var userSchema = new mongoose.Schema({
  
      username: { 
          type: String, 
          index: { unique: true, sparse: true }, 
          required: true, lowercase: true, trim: true
      },
  
      email: {
          type: String,
          index: { unique: true, sparse: true }, 
          required: true, lowercase: true, trim: true
      },
  
      salt: {
          type: String,
          select: false
      },
  
      password: {
          type: String,
          select: false
      },
  
      plainPassword: {
          type: String,
          select: false
      }
  
  });
  
  // FIXME: password encoding only on change, not always
  userSchema.pre('save', function(next) {
      // check if a plainPassword was set
      if (this.plainPassword !== '') {
          // generate salt
          crypto.randomBytes(64, function(err, buf) {
              if (err) return next(err);
              this.salt = buf.toString('base64');
              // encode password
              crypto.pbkdf2(this.plainPassword, this.salt, 25000, 512, function(err, encodedPassword) {
                  if (err) return next(err);
                  this.password = new Buffer(encodedPassword, 'binary').toString('base64');
                  this.plainPassword = '';
              }.bind(this));
          }.bind(this));
      }
  
      next();
  });
  
  // statics
  userSchema.methods.hasEqualPassword = function(plainPassword, cb) {
      crypto.pbkdf2(plainPassword, this.salt, 25000, 512, function(err, encodedPassword) {
          if (err) return next(err);
          encodedPassword = new Buffer(encodedPassword, 'binary').toString('base64');
          cb((this.password === encodedPassword));
      }.bind(this));
  }
  
  module.exports = mongoose.model('User', userSchema, 'Users');
  </code></pre>
  
  <p>Has somebody managed to move encryption to mongoose setters?</p>
  
  <p>Regards, bodo</p>