Reputation: 25
I understand that in web development user input should be validated on the client and server side.
I'm having a hard time figuring out where to validate the input on the server side.
For example, after a request passes through the middleware and gets to the controllers. In the controllers I have other modules that will take the input and finally get to its destination and then respond.
Should validating of the inputs be done completely in the controllers so that when the inputs are put into the other modules it is as expected? Or should I check the inputs in the modules that take the inputs? Or should I do a "shallow" check of input in the controllers (basic primitive type checks, etc) and reserve the business logic checks in the modules themselves (is value positive?, negative? etc) ?
Example Code:
controller.js
var mashUp = require('./mashupService');
var create = function(req, res) {
var user = req.body.user;
var imageName = req.body.imageName;
var description = req.body.description;
//more validation here?
if (!user) {
return ApiResponse(req, res, new Error('no user'));
} else if (!imageName) {
return ApiResponse(req, res, new Error('no image name'));
} else if (!description) {
return ApiResponse(req, res, new Error('no description'));
}
// continue with business
mashUp(user, imageName, description, function(err, id) {
if (err) {
return ApiResponse(req, res, new Error('mashup error'));
}
return ApiResponse(req, res, { id: id });
});
};
`other modules, libs, etc'
var User = require('./model/user');
function mashUp(user, imageName, desc, callback) {
//more validation here?
User.find({ user: user }, function(err, _user) {
//do stuff
callback(err, id) ;
});
}
module.exports = mashUp
Upvotes: 0
Views: 1230
Reputation: 16066
well there's some difference when you validate data from different perspectives:
Model validation: when you have a rule that need to be applied to your data model like required, min, max, match, etc. those are built int with any orm or odm if any validation fails in most of the cases that will bubble up to a middleware and you can handle from there.
you may have the option to setup custom validators in case you need to implement more complex logic.
this is a moongose example:
var UserSchema = new Schema({
firstName: {
type: String,
trim: true,
default: '',
validate: [customValidator, 'Please fill in your first name']
// custom validator
},
lastName: {
type: String,
trim: true,
default: '',
validate: [customValidator, 'Please fill in your last name']
// custom validator
},
displayName: {
type: String,
trim: true
},
email: {
type: String,
trim: true,
unique: true,
default: '',
validate: [customValidator, 'Please fill in your email'],
// custom validator
match: [/.+\@.+\..+/, 'Please fill a valid email address']
//match validator
},
username: {
type: String,
unique: true,
required: 'Please fill in a username', //required validator
trim: true
}
});
For further reference look at mongoose validations
Busines rules
this applies more to the scenario that you are describing right now, handling rules that may apply to specific circumstances or user histories in the system.
I don't recommend to manage the validations in controllers, a thumbs up rule is to create Fat models and skinny controllers you may google it but randomly I picked this presentation and this article.
Being said that I prefer to do those validations in a middleware prior to the controller execution.
Let's make a case for the following case
when editing an article lets validate that id belong to the user that is requesting to edit
exports.validateArticle = function(req, res, next){
var userId = req.param('userId'),
articleId = req.param('articleId');
// TODO: logic validation
}
then you hook up your middleware prior to the controller execution like
app.route('/article').all( rule.validateArticle ).post(controller.editArticle);
that way you are not polluting your controllers with a bunch of validations, also you could potentially reuse validations from one controller to another.
as a side note validation on the client side are made for user experience but not rely on them as a proper validator for your system.
just my two cents here, I hope that helps.
cheers!
Upvotes: 1
Reputation: 63
This is about data validation. It is not necessary to do data validation on client side since client data is usually not reliable. The correct data must be validated on server. I would recommend you to do the validation in controller instead of other modules. Let's have a look at your example:
var create = function(req, res) {
var user = req.body.user;
var imageName = req.body.imageName;
var description = req.body.description;
//more validation here?
Answer: Yes. Think about if user is existed or has permission, description has at least 10 chars, contains illegal chars etc.
if (!user) {
return ApiResponse(req, res, new Error('no user'));
} else if (!imageName) {
return ApiResponse(req, res, new Error('no image name'));
} else if (!description) {
return ApiResponse(req, res, new Error('no description'));
}
//Btw, here is kind of validation right?
//but it looks like that you only want to check if user is posted,
//then imageName and description will be ignored.
//There may be some logic error here.
At last, I also suggest you to create a module specially for data validation.
Upvotes: 0