Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

express-validator

Package Overview
Dependencies
Maintainers
2
Versions
121
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

express-validator - npm Package Compare versions

Comparing version 2.11.0 to 2.12.0

test/nestedInputSanitizeTest.js

403

lib/express_validator.js

@@ -1,262 +0,245 @@

/*
* This binds the node-validator library to the req object so that
* the validation / sanitization methods can be called on parameter
* names rather than the actual strings.
var validator = require('validator');
var _ = require('lodash');
// validators and sanitizers not prefixed with is/to
var additionalValidators = ['contains', 'equals', 'matches'];
var additionalSanitizers = ['trim', 'ltrim', 'rtrim', 'escape', 'stripLow', 'whitelist', 'blacklist', 'normalizeEmail'];
/**
* Initalizes a chain of validators
*
*
* 1. To validate parameters, use `req.check(param_name, [err_message])`
* e.g. req.check('param1').len(1, 6).isInt();
* e.g. req.checkHeader('referer').contains('mydomain.com');
*
* Each call to `check()` will throw an exception by default. To
* specify a custom err handler, use `req.onValidationError(errback)`
* where errback receives a parameter containing the error message
*
* 2. To sanitize parameters, use `req.sanitize(param_name)`
* e.g. req.sanitize('param1').toBoolean();
* e.g. req.sanitize('param2').toInt();
*
* 3. Done! Access your validated and sanitized paramaters through the
* `req.params` object
* @class
* @param {(string|string[])} param path to property to validate
* @param {string} failMsg validation failure message
* @param {Request} req request to attach validation errors
* @param {string} location request property to find value (body, params, query, etc.)
* @param {object} options options containing error formatter
*/
var validator = require('validator');
function ValidatorChain(param, failMsg, req, location, options) {
this.errorFormatter = options.errorFormatter;
this.param = param;
this.value = location ? _.get(req[location], param) : undefined;
this.validationErrors = [];
this.failMsg = failMsg;
this.req = req;
var expressValidator = function(options) {
options = options || {};
return this;
}
var _options = {};
_options.customValidators = options.customValidators || {};
_options.customSanitizers = options.customSanitizers || {};
/**
* Initializes a sanitizers
*
* @class
* @param {(string|string[])} param path to property to sanitize
* @param {[type]} req request to sanitize
* @param {[type]} location request property to find value
*/
_options.errorFormatter = options.errorFormatter || function(param, msg, value) {
return {
param : param,
msg : msg,
value : value
};
};
function Sanitizer(param, req, locations) {
this.values = locations.map(function(location) {
return _.get(req[location], param);
});
var sanitizers = ['trim', 'ltrim', 'rtrim', 'escape', 'stripLow', 'whitelist',
'blacklist', 'normalizeEmail'];
this.req = req;
this.param = param;
this.locations = locations;
return this;
}
var sanitize = function(request, param, value) {
var methods = {};
/**
* Adds validation methods to request object via express middleware
*
* @method expressValidator
* @param {object} options
* @return {function} middleware
*/
Object.keys(validator).forEach(function(methodName) {
if (methodName.match(/^to/) || sanitizers.indexOf(methodName) !== -1) {
methods[methodName] = function() {
var args = [value].concat(Array.prototype.slice.call(arguments));
var result = validator[methodName].apply(validator, args);
request.updateParam(param, result);
return result;
};
}
});
Object.keys(_options.customSanitizers).forEach(function(customName) {
methods[customName] = function() {
var args = [value].concat(Array.prototype.slice.call(arguments));
var result = _options.customSanitizers[customName].apply(null, args);
request.updateParam(param, result);
return result;
var expressValidator = function(options) {
var defaults = {
customValidators: {},
customSanitizers: {},
errorFormatter: function(param, msg, value) {
return {
param: param,
msg: msg,
value: value
};
});
return methods;
},
};
function checkParam(req, getter) {
return function(param, failMsg) {
_.defaults(options, defaults);
var value;
// _.set validators and sainitizers as prototype methods on corresponding chains
_.forEach(validator, function(method, methodName) {
if (methodName.match(/^is/) || _.contains(additionalValidators, methodName)) {
ValidatorChain.prototype[methodName] = makeValidator(methodName, validator);
}
// If param is not an array, then split by dot notation
// returning an array. It will return an array even if
// param doesn't have the dot notation.
// 'blogpost' = ['blogpost']
// 'login.username' = ['login', 'username']
// For regex matches you can access the parameters using numbers.
if (!Array.isArray(param)) {
param = typeof param === 'number' ?
[param] :
param.split('.').filter(function(e){
return e !== '';
});
}
if (methodName.match(/^to/) || _.contains(additionalSanitizers, methodName)) {
Sanitizer.prototype[methodName] = makeSanitizer(methodName, validator);
}
});
// Extract value from params
param.map(function(item) {
if (value === undefined) {
value = getter(item);
} else {
value = value[item];
}
});
param = param.join('.');
ValidatorChain.prototype.notEmpty = function() {
return this.isLength(1);
};
var errorHandler = function(msg) {
var error = _options.errorFormatter(param, msg, value);
ValidatorChain.prototype.len = function() {
return this.isLength.apply(this, arguments);
};
if (req._validationErrors === undefined) {
req._validationErrors = [];
}
req._validationErrors.push(error);
ValidatorChain.prototype.optional = function() {
if (this.value === undefined) {
this.skipValidating = true;
}
if (req.onErrorCallback) {
req.onErrorCallback(msg);
}
return this;
};
return this;
};
var methods = [];
_.forEach(options.customValidators, function(method, customValidatorName) {
ValidatorChain.prototype[customValidatorName] = makeValidator(customValidatorName, options.customValidators);
});
Object.keys(validator).forEach(function(methodName) {
if (!methodName.match(/^to/) && sanitizers.indexOf(methodName) === -1) {
methods[methodName] = function() {
var args = [value].concat(Array.prototype.slice.call(arguments));
var isCorrect = validator[methodName].apply(validator, args);
_.forEach(options.customSanitizers, function(method, customSanitizerName) {
Sanitizer.prototype[customSanitizerName] = makeSanitizer(customSanitizerName, options.customSanitizers);
});
if (!isCorrect) {
errorHandler(failMsg || 'Invalid value');
}
return function(req, res, next) {
var locations = ['body', 'params', 'query'];
return methods;
};
}
});
req._validationErrors = [];
req.validationErrors = function(mapped) {
if (mapped && req._validationErrors.length > 0) {
var errors = {};
req._validationErrors.forEach(function(err) {
errors[err.param] = err;
});
Object.keys(_options.customValidators).forEach(function(customName) {
methods[customName] = function() {
var args = [value].concat(Array.prototype.slice.call(arguments));
var isCorrect = _options.customValidators[customName].apply(null, args);
return errors;
}
if (!isCorrect) {
errorHandler(failMsg || 'Invalid value');
}
return req._validationErrors.length > 0 ? req._validationErrors : false;
};
return methods;
};
});
methods['notEmpty'] = function() {
return methods.isLength(1);
locations.forEach(function(location) {
req['sanitize' + _.capitalize(location)] = function(param) {
return new Sanitizer(param, req, [location]);
};
});
methods['len'] = function() {
return methods.isLength.apply(methods.isLength, Array.prototype.slice.call(arguments));
};
req.sanitize = function(param) {
return new Sanitizer(param, req, locations);
};
methods['optional'] = function() {
if (value !== undefined) {
return methods;
}
var dummyMethods = [];
for (var methodName in methods) {
dummyMethods[methodName] = function() { return dummyMethods; };
}
return dummyMethods;
locations.forEach(function(location) {
req['check' + _.capitalize(location)] = function(param, failMsg) {
return new ValidatorChain(param, failMsg, req, location, options);
};
});
return methods;
req.checkFiles = function(param, failMsg) {
return new ValidatorChain(param, failMsg, req, 'files', options);
};
}
return function(req, res, next) {
req.updateParam = function(name, value) {
// route params like /user/:id
if (this.params && this.params.hasOwnProperty(name) &&
undefined !== this.params[name]) {
return this.params[name] = value;
req.checkHeaders = function(param, failMsg) {
if (param === 'referrer') {
param = 'referer';
}
// query string params
if (undefined !== this.query[name]) {
return this.query[name] = value;
}
// request body params via connect.bodyParser
if (this.body && undefined !== this.body[name]) {
return this.body[name] = value;
}
return false;
return new ValidatorChain(param, failMsg, req, 'headers', options);
};
req.check = checkParam(req, function(item) {
return param(req, item);
});
req.check = function(param, failMsg) {
return new ValidatorChain(param, failMsg, req, locate(req, param), options);
};
req.checkFiles = checkParam(req, function(item) {
return req.files && req.files[item];
});
req.filter = req.sanitize;
req.assert = req.check;
req.validate = req.check;
req.checkBody = checkParam(req, function(item) {
return req.body && req.body[item];
});
next();
};
};
req.checkParams = checkParam(req, function(item) {
return req.params && req.params[item];
});
/**
* Validates and handles errors, return instance of itself to allow for chaining
*
* @method makeValidator
* @param {string} methodName
* @param {object} container
* @return {function}
*/
req.checkQuery = checkParam(req, function(item) {
return req.query && req.query[item];
});
function makeValidator(methodName, container) {
return function() {
var args = [];
args.push(this.value);
args = args.concat(Array.prototype.slice.call(arguments));
req.checkHeader = checkParam(req, function(header) {
var toCheck;
var result = container[methodName].apply(container, args);
if (header === 'referrer' || header === 'referer') {
toCheck = req.headers.referer;
} else {
toCheck = req.headers[header];
}
return req.headers && toCheck;
});
var isValid = this.skipValidating || result;
req.onValidationError = function(errback) {
req.onErrorCallback = errback;
};
if (!isValid) {
var error = this.errorFormatter(this.param, this.failMsg || 'Invalid value', this.value);
this.validationErrors.push(error);
this.req._validationErrors.push(error);
}
req.validationErrors = function(mapped) {
if (req._validationErrors === undefined) {
return null;
}
if (mapped) {
var errors = {};
req._validationErrors.forEach(function(err) {
errors[err.param] = err;
});
return errors;
}
return req._validationErrors;
};
return this;
};
}
req.filter = function(item) {
return sanitize(this, item, param(req, item));
};
/**
* Sanitizes and sets sanitized value on the request, then return instance of itself to allow for chaining
*
* @method makeSanitizer
* @param {string} methodName
* @param {object} container
* @return {function}
*/
// Create some aliases - might help with code readability
req.sanitize = req.filter;
req.assert = req.check;
req.validate = req.check;
function makeSanitizer(methodName, container) {
return function() {
var _arguments = arguments;
var result;
this.values.forEach(function(value, i) {
if (value) {
var args = [value];
args = args.concat(Array.prototype.slice.call(_arguments));
result = container[methodName].apply(container, args);
// Taken from express 3.x for express 4.x compatibility
function param(req, name, defaultValue){
// route params like /user/:id
if (req.params && req.params.hasOwnProperty(name) && undefined !== req.params[name]) {
return req.params[name];
_.set(this.req[this.locations[i]], this.param, result);
this.values[i] = result;
}
// query string params
if (undefined !== req.query[name]) {
return req.query[name];
}
// request body params via connect.bodyParser
if (req.body && undefined !== req.body[name]) {
return req.body[name];
}
return defaultValue;
}
}.bind(this));
return next();
return result;
};
};
}
/**
* find location of param
*
* @method param
* @param {Request} req express request object
* @param {(string|string[])} name [description]
* @return {string}
*/
function locate(req, name) {
if (_.get(req.params, name)) {
return 'params';
} else if (_.has(req.query, name)) {
return 'query';
} else if (_.has(req.body, name)) {
return 'body';
}
return undefined;
}
module.exports = expressValidator;
module.exports.validator = validator;

@@ -12,3 +12,3 @@ {

],
"version": "2.11.0",
"version": "2.12.0",
"homepage": "https://github.com/ctavan/express-validator",

@@ -29,3 +29,4 @@ "license": "MIT",

"dependencies": {
"validator": "3.39.0"
"lodash": "3.9.3",
"validator": "3.40.1"
},

@@ -32,0 +33,0 @@ "devDependencies": {

@@ -27,2 +27,3 @@ # express-validator

// VALIDATION
// checkBody only checks req.body; none of the other req parameters

@@ -40,2 +41,10 @@ // Similarly checkParams only checks in req.params (URL params) and

// SANITIZATION
// as with validation these will only validate the corresponding
// request object
req.sanitizeBody('postparam').toBoolean();
req.sanitizeParams('urlparam').toBoolean();
req.sanitizeQuery('getparam').toBoolean();
// OR find the relevent param in all areas
req.sanitize('postparam').toBoolean();

@@ -49,5 +58,5 @@

res.json({
urlparam: req.param('urlparam'),
getparam: req.param('getparam'),
postparam: req.param('postparam')
urlparam: req.params.urlparam,
getparam: req.params.getparam,
postparam: req.params.postparam
});

@@ -152,4 +161,32 @@ });

### Validation errors
## Validation
#### req.check();
```javascript
req.check('testparam', 'Error Message').notEmpty().isInt();
req.check('testparam.child', 'Error Message').isInt(); // find nested params
req.check(['testparam', 'child'], 'Error Message').isInt(); // find nested params
```
Starts the validation of the specifed parameter, will look for the parameter in `req` in the order `params`, `query`, `body`, then validate, you can use 'dot-notation' or an array to access nested values.
Validators are appended and can be chained. See [chriso/validator.js](https://github.com/chriso/validator.js) for available validators, or [add your own](#customvalidators).
#### req.assert();
Alias for [req.check()](#reqcheck).
#### req.validate();
Alias for [req.check()](#reqcheck).
#### req.checkBody();
Same as [req.check()](#reqcheck), but only looks in `req.body`.
#### req.checkQuery();
Same as [req.check()](#reqcheck), but only looks in `req.query`.
#### req.checkParams();
Same as [req.check()](#reqcheck), but only looks in `req.params`.
## Validation errors
You have two choices on how to get the validation errors:

@@ -202,36 +239,34 @@

### Nested input data
## Sanitizer
Example:
#### req.sanitize();
```javascript
```html
<input name="user[fields][email]" />
```
req.body.comment = 'a <span>comment</span>';
req.body.comment.username = ' user ';
Provide an array instead of a string:
req.sanitize('comment').escape(); // returns 'a &lt;span&gt;comment&lt;/span&gt;'
req.sanitize('comment.user').trim(); // returns 'a user'
```javascript
req.assert(['user', 'fields', 'email'], 'valid email required').isEmail();
var errors = req.validationErrors();
console.log(errors);
console.log(req.body.comment); // 'a &lt;span&gt;comment&lt;/span&gt;'
console.log(req.body.comment.user); // 'a user'
```
Output:
Sanitizes the specified parameter (using 'dot-notation' or array), the parameter will be updated to the sanitized result. Cannot be chained, and will return the result. See [chriso/validator.js](https://github.com/chriso/validator.js) for available sanitizers, or [add your own](#customsanitizers).
```javascript
[
{
param: "user_fields_email",
msg: "valid email required",
value: "<received input>"
}
]
```
If the parameter is present in multiple places with the same name e.g. `req.params.comment` & `req.query.comment`, they will all be sanitized.
Alternatively you can use dot-notation to specify nested fields to be checked:
#### req.filter();
Alias for [req.sanitize()](#reqsanitize).
```javascript
req.assert(['user.fields.email'], 'valid email required').isEmail();
```
#### req.sanitizeBody();
Same as [req.sanitize()](#reqsanitize), but only looks in `req.body`.
#### req.sanitizeQuery();
Same as [req.sanitize()](#reqsanitize), but only looks in `req.query`.
#### req.sanitizeParams();
Same as [req.sanitize()](#reqsanitize), but only looks in `req.params`.
### Regex routes

@@ -251,6 +286,2 @@

### Extending
You can add your own validators using the `customValidators` option. See [Middleware Options](#middleware-options) for usage details.
## Changelog

@@ -269,2 +300,1 @@

Copyright (c) 2010 Chris O'Hara <cohara87@gmail.com>, MIT License
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc