Validating password / confirm password with Mongoose schema


Question

I have a userSchema that looks like this:

var userSchema = new Schema({
    name: {
      type: String
    , required: true
    , validate: [validators.notEmpty, 'Name is empty']
    }
  , username: {
      type: String
    , required: true
    , validate: [validators.notEmpty, 'Username is empty']
    }
  , email: {
      type: String
    , required: true
    , validate: [
        { validator: validators.notEmpty, msg: 'Email is empty' }
      , { validator: validators.isEmail, msg: 'Invalid email' }
      ]
    }
  , salt: String
  , hash: String
});

All of my validation is happening in the schema so far, and I'm wondering how to go about achieving this with password validation. The user inputs the password into two fields, and the model should check that they are the same as each other.

Does this kind of validation belong in the schema? I'm new to this sort of validation.

How should I validate the passwords?

1
11
12/20/2012 11:29:16 PM

Accepted Answer

I eventually discovered that you can use a combination of virtual paths and the invalidate function to achieve this, as shown in this gist, for the very same purpose of matching passwords: https://gist.github.com/1350041

To quote directly:

CustomerSchema.virtual('password')
.get(function() {
  return this._password;
})
.set(function(value) {
  this._password = value;
  var salt = bcrypt.gen_salt_sync(12);
  this.passwordHash = bcrypt.encrypt_sync(value, salt);
});

CustomerSchema.virtual('passwordConfirmation')
.get(function() {
  return this._passwordConfirmation;
})
.set(function(value) {
  this._passwordConfirmation = value;
});

CustomerSchema.path('passwordHash').validate(function(v) {
  if (this._password || this._passwordConfirmation) {
    if (!val.check(this._password).min(6)) {
      this.invalidate('password', 'must be at least 6 characters.');
    }
    if (this._password !== this._passwordConfirmation) {
      this.invalidate('passwordConfirmation', 'must match confirmation.');
    }
  }

  if (this.isNew && !this._password) {
    this.invalidate('password', 'required');
  }
}, null);
23
12/23/2012 10:50:32 PM

I think password matching belongs in the client interface and should never get to the server (DB layer is already too much). It's better for the user experience not to have a server roundtrip just to tell the user that 2 strings are different.

As for thin controller, fat model... all these silver bullets out there should be shot back at the originator. No solution is good in any situation. Think everyone of them in their own context.

Bringing the fat model idea here, makes you use a feature (schema validation) for a totally different purpose (password matching) and makes your app dependent on the tech you're using now. One day you'll want to change tech and you'll get to something without schema validation at all... and then you'll have to remember that part of functionality of your app relied on that. And you'll have to move it back to the client side or to the controller.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon