Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Password confirmation and external Model validation in Sails.js

I've been playing around with Sails for maybe one day. I'm trying to wrap my head around what would be the best way to do extensive validation in Sails.js.

Here is the scenario:

Registration Form:

Username: _______________
E-Mail:   _______________
Password: _______________
Confirm:  _______________

User inputs:

  • a correct e-mail
  • a username that already exists
  • two passwords that don't match

Desired outcome:

Username: _______________ x Already taken
E-Mail:   _______________ ✓
Password: _______________ ✓
Confirm:  _______________ x Does not match

Requirements, a few key points:

  • The user receives all error messages (not just the first one) for every aspect of his input. They are not vague ("username already taken" or "username must be at least 4 letters long" is better than "invalid username")
  • The built-in model validation can obviously not be responsible for checking a matched password confirmation (SRP)

What I think I need to do:

UserController:

create: function(req, res) {
    try {
        // use a UserManager-Service to keep the controller nice and thin
        UserManager.create(req.params.all(), function(user) {
            res.send(user.toJSON());
        });
    }
    catch (e) {
        res.send(e);
    }
}

UserManager:

create: function(input, cb) {
    UserValidator.validate(input); // this can throw a ValidationException which will then be handled by the controller
    User.create(input, cb); // this line should only be reached if the UserValidator did not throw an exception
}

User: (model)

attributes: {
    username: {
        type: 'string',
        required: true,
        minLength: 3,
        unique: true
    },

    email: {
        type: 'email',
        required: true,
        unique: true
    },

    password: {
        type: 'string',
        required: true
    }
}

UserValidator:

This is the tricky part. I need to combine input-specific validation (does the password confirmation match?) with the Model validation (is the username taken and is the e-mail address valid?).

If there was a way to instantiate a User-model and perform validation without saving to the database in Sails/Waterline I think this would be quite straight-forward, but there doesn't seem to be that option.

How would you go about solving this problem? Thank you very much for your help!

like image 221
Macks Avatar asked Feb 21 '14 13:02

Macks


People also ask

How do I compare password and confirm password in node JS?

Steps to use express-validator to implement the logic:Install express-validator middleware. Create a validator. js file to code all the validation logic. Validate confirmPassword by validateConfirmPassword: check('confirmPassword') and chain on all the validation with ' .

What is password validation?

It checks that the password entered by the user is same as this confirm password fields. To create a valid password, both the password and confirm password fields value must be matched. First one, we will check for a valid password and then confirm password validation checks.

How do I validate login credentials in HTML?

should be javascript:validate(...) or just validate(...) . Use <script type="text/javascript"> to start a (java)script element. You need to wrap string values in quotes (i.e. workshop should be "workshop" ). Change name="text1" to id="text1" and then you can get the value using document.

How does sails JS work?

Sails. js uses Grunt as a build tool for building front-end assets. If you're building an app for the browser, you're in luck. Sails ships with Grunt — which means your entire front-end asset workflow is completely customizable, and comes with support for all of the great Grunt modules which are already out there.


2 Answers

You can do this in your model:

module.exports = {
types: {
    mycustomtype: function (password) {
        return password === this.confirm;
    }
},
attributes: {,
    password:{
        type: 'STRING',
        required: true,
        mycustomtype: true
    }
}
}
like image 95
Raphael Avatar answered Nov 15 '22 04:11

Raphael


There are going to be some validations that you can perform immediately on the client-side without needing to round-trip to the server. Things like comparing the password with the confirmation password, as well as verifying a string matches an email regex can be done with client-side javascript.

For other things like checking whether a username exists or not, you could use an ajax call to sails to directly ask it 'does this username exist' and provide real-time validation on the client-side based on the result, or you can wait until the user submits the form and parse the form submission to display those validations. Since checking ahead of time for things like this aren't 100% reliable (i.e. someone could create a user with that name after the check but prior to the form being posted back), some people choose to forgo the pre-check and only handle the error after post.

Waterline has its own built-in validation mechanism called Anchor, which is built on validator.js (previously called node-validator). For a full list of validations available, see here. I would recommend that instead of defining a separate validation layer, you define a method that parses the sails validation messages and formats them in a way that is user-friendly and consistent.

If you want to perform your own validations outside of what Waterline would do for you, you could do those validations inside a lifecycle callback, for instance the beforeCreate(values, callback) lifecycle callback. If you detect errors, you could pass them into the callback as the first parameter, and they would be passed back as an error to the caller of the create collection method.

An alternative to using a lifecycle callback, would be to create your own collection method that handles the create. Something like this:

Users.validateAndCreate(req.params.all(), function (err, user) {
    ...
});

More information about how to create a collection method like this can be found in my answer to this question: How can I write sails function on to use in Controller?

like image 35
Chad Avatar answered Nov 15 '22 02:11

Chad