express-validator
Advanced tools
Comparing version 2.21.0 to 3.0.0
var validator = require('validator'); | ||
var _ = require('lodash'); | ||
var Promise = require('bluebird'); | ||
var utils = require('./utils'); | ||
@@ -241,3 +242,40 @@ // When validator upgraded to v5, they removed automatic string coercion | ||
req.getValidationResult = function() { | ||
return new Promise(function(resolve) { | ||
var promises = req._asyncValidationErrors; | ||
// Migrated using the recommended fix from | ||
// http://bluebirdjs.com/docs/api/reflect.html | ||
Promise.all(promises.map(function(promise) { | ||
// Must convert to Bluebird promise in case they are using native | ||
// Node promises since reflect() is not a native promise method | ||
// http://bluebirdjs.com/docs/api/reflect.html#comment-2369616577 | ||
return Promise.resolve(promise).reflect(); | ||
})).then(function(results) { | ||
results.forEach(function(result) { | ||
if (result.isRejected()) { | ||
req._validationErrors.push(result.reason()); | ||
} | ||
}); | ||
return resolve(utils.decorateAsValidationResult({}, req._validationErrors)); | ||
}); | ||
}); | ||
}; | ||
locations.forEach(function(location) { | ||
/** | ||
* @name req.sanitizeQuery | ||
* @see sanitize | ||
* @param param | ||
*/ | ||
/** | ||
* @name req.sanitizeParams | ||
* @see sanitize | ||
* @param param | ||
*/ | ||
/** | ||
* @name req.sanitizeBody | ||
* @see sanitize | ||
* @param param | ||
*/ | ||
req['sanitize' + _.capitalize(location)] = function(param) { | ||
@@ -253,5 +291,9 @@ return new Sanitizer(param, req, [location]); | ||
return new Sanitizer(param, req, ['headers']); | ||
return new Sanitizer(param.toLowerCase(), req, ['headers']); | ||
}; | ||
req.sanitizeCookies = function(param) { | ||
return new Sanitizer(param, req, ['cookies']); | ||
}; | ||
req.sanitize = function(param) { | ||
@@ -262,2 +304,20 @@ return new Sanitizer(param, req, locations); | ||
locations.forEach(function(location) { | ||
/** | ||
* @name req.checkQuery | ||
* @see check | ||
* @param param | ||
* @param [failMsg] | ||
*/ | ||
/** | ||
* @name req.checkParams | ||
* @see check | ||
* @param param | ||
* @param [failMsg] | ||
*/ | ||
/** | ||
* @name req.checkBody | ||
* @see check | ||
* @param param | ||
* @param [failMsg] | ||
*/ | ||
req['check' + _.capitalize(location)] = function(param, failMsg) { | ||
@@ -271,6 +331,2 @@ if (_.isPlainObject(param)) { | ||
req.checkFiles = function(param, failMsg) { | ||
return new ValidatorChain(param, failMsg, req, 'files', options); | ||
}; | ||
req.checkHeaders = function(param, failMsg) { | ||
@@ -281,5 +337,9 @@ if (param === 'referrer') { | ||
return new ValidatorChain(param, failMsg, req, 'headers', options); | ||
return new ValidatorChain(param.toLowerCase(), failMsg, req, 'headers', options); | ||
}; | ||
req.checkCookies = function(param, failMsg) { | ||
return new ValidatorChain(param, failMsg, req, 'cookies', options); | ||
}; | ||
req.check = function(param, failMsg) { | ||
@@ -352,2 +412,11 @@ if (_.isPlainObject(param)) { | ||
if (schema[param].optional) { | ||
validator.optional.apply(validator, schema[param].optional.options); | ||
if (validator.skipValidating) { | ||
validator.failMsg = schema[param].optional.errorMessage || paramErrorMessage || 'Invalid param'; | ||
continue; // continue with the next param in schema | ||
} | ||
} | ||
for (var methodName in schema[param]) { | ||
@@ -364,5 +433,4 @@ if (methodName === 'in') { | ||
if (methodName === 'errorMessage') { | ||
/** | ||
* Also do not validate if methodName | ||
* represent parameter error mesage | ||
/* Also do not validate if methodName | ||
* represent parameter error message | ||
*/ | ||
@@ -497,3 +565,3 @@ continue; | ||
function formatErrors(param, msg, value) { | ||
var formattedParam = formatParamOutput(param); | ||
var formattedParam = utils.formatParamOutput(param); | ||
@@ -503,29 +571,4 @@ return this.errorFormatter(formattedParam, msg, value); | ||
// Convert nested params as array into string for output | ||
// Ex: ['users', '0', 'fields', 'email'] to 'users[0].fields.email' | ||
function formatParamOutput(param) { | ||
if (Array.isArray(param)) { | ||
param = param.reduce(function(prev, curr) { | ||
var part = ''; | ||
if (validator.isInt(curr)) { | ||
part = '[' + curr + ']'; | ||
} else { | ||
if (prev) { | ||
part = '.' + curr; | ||
} else { | ||
part = curr; | ||
} | ||
} | ||
return prev + part; | ||
}); | ||
} | ||
return param; | ||
} | ||
module.exports = expressValidator; | ||
module.exports.validator = validator; | ||
module.exports.utils = { | ||
formatParamOutput: formatParamOutput | ||
}; | ||
module.exports.utils = utils; |
@@ -12,3 +12,3 @@ { | ||
], | ||
"version": "2.21.0", | ||
"version": "3.0.0", | ||
"homepage": "https://github.com/ctavan/express-validator", | ||
@@ -22,6 +22,7 @@ "license": "MIT", | ||
"scripts": { | ||
"test": "mocha", | ||
"test": "nyc mocha", | ||
"jshint": "jshint ./test ./lib", | ||
"jscs": "jscs ./test ./lib", | ||
"travis-build": "npm test && npm run jshint && npm run jscs", | ||
"report-coverage": "cat coverage/lcov.info | coveralls", | ||
"changelog": "github-changes -o ctavan -r express-validator -a -m YYYY/MM/DD --no-merges" | ||
@@ -33,9 +34,11 @@ }, | ||
"dependencies": { | ||
"bluebird": "3.4.x", | ||
"lodash": "4.16.x", | ||
"validator": "5.7.x" | ||
"bluebird": "^3.4.0", | ||
"lodash": "^4.16.0", | ||
"validator": "~6.1.0" | ||
}, | ||
"devDependencies": { | ||
"body-parser": "1.12.3", | ||
"cookie-parser": "1.4.1", | ||
"chai": "2.3.0", | ||
"coveralls": "2.11.14", | ||
"express": "4.12.3", | ||
@@ -46,2 +49,3 @@ "github-changes": "1.0.2", | ||
"mocha": "2.2.4", | ||
"nyc": "8.4.0", | ||
"supertest": "0.15.0" | ||
@@ -48,0 +52,0 @@ }, |
201
README.md
# express-validator | ||
[![npm version](https://badge.fury.io/js/express-validator.svg)](https://badge.fury.io/js/express-validator) [![Build Status](https://secure.travis-ci.org/ctavan/express-validator.png)](http://travis-ci.org/ctavan/express-validator) [![Dependency Status](https://david-dm.org/ctavan/express-validator.svg)](https://david-dm.org/ctavan/express-validator) | ||
[![npm version](https://img.shields.io/npm/v/express-validator.svg)](https://www.npmjs.com/package/express-validator) | ||
[![Build Status](https://img.shields.io/travis/ctavan/express-validator.svg)](http://travis-ci.org/ctavan/express-validator) | ||
[![Dependency Status](https://img.shields.io/david/ctavan/express-validator.svg)](https://david-dm.org/ctavan/express-validator) | ||
[![Coverage Status](https://img.shields.io/coveralls/ctavan/express-validator.svg)](https://coveralls.io/github/ctavan/express-validator?branch=master) | ||
@@ -8,2 +11,18 @@ An [express.js]( https://github.com/visionmedia/express ) middleware for | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Middleware options](#middleware-options) | ||
- [Validation](#validation) | ||
- [Validation by schema](#validation-by-schema) | ||
- [Validation result](#validation-result) | ||
+ [Result API](#result-api) | ||
+ [Deprecated API](#deprecated-api) | ||
+ [String formatting for error messages](#string-formatting-for-error-messages) | ||
+ [Per-validation messages](#per-validation-messages) | ||
- [Optional input](#optional-input) | ||
- [Sanitizer](#sanitizer) | ||
- [Regex routes](#regex-routes) | ||
- [Changelog](#changelog) | ||
- [License](#license) | ||
## Installation | ||
@@ -19,8 +38,9 @@ | ||
var util = require('util'), | ||
bodyParser = require('body-parser'), | ||
express = require('express'), | ||
expressValidator = require('express-validator'), | ||
app = express.createServer(); | ||
app = express(); | ||
app.use(express.bodyParser()); | ||
app.use(expressValidator([options])); // this line must be immediately after express.bodyParser()! | ||
app.use(bodyParser.json()); | ||
app.use(expressValidator([options])); // this line must be immediately after any of the bodyParser middlewares! | ||
@@ -52,11 +72,14 @@ app.post('/:urlparam', function(req, res) { | ||
var errors = req.validationErrors(); | ||
if (errors) { | ||
res.send('There have been validation errors: ' + util.inspect(errors), 400); | ||
return; | ||
} | ||
res.json({ | ||
urlparam: req.params.urlparam, | ||
getparam: req.params.getparam, | ||
postparam: req.params.postparam | ||
// Alternatively use `var result = yield req.getValidationResult();` | ||
// when using generators e.g. with co-express | ||
req.getValidationResult().then(function(result) { | ||
if (!result.isEmpty()) { | ||
res.send('There have been validation errors: ' + util.inspect(result.array()), 400); | ||
return; | ||
} | ||
res.json({ | ||
urlparam: req.params.urlparam, | ||
getparam: req.params.getparam, | ||
postparam: req.params.postparam | ||
}); | ||
}); | ||
@@ -88,7 +111,8 @@ }); | ||
### Middleware Options | ||
####`errorFormatter` | ||
## Middleware Options | ||
#### `errorFormatter` | ||
_function(param,msg,value)_ | ||
The `errorFormatter` option can be used to specify a function that can be used to format the objects that populate the error array that is returned in `req.validationErrors()`. It should return an `Object` that has `param`, `msg`, and `value` keys defined. | ||
The `errorFormatter` option can be used to specify a function that must build the error objects used in the validation result returned by `req.getValidationResult()`.<br> | ||
It should return an `Object` that has `param`, `msg`, and `value` keys defined. | ||
@@ -195,45 +219,5 @@ ```javascript | ||
## Asynchronous Validation | ||
#### req.checkCookies(); | ||
Only checks `req.cookies`. This method is not covered by the general `req.check()`. | ||
If you need to perform asynchronous validation, for example checking a database if a username has been taken already, your custom validator can return a promise. | ||
You **MUST** use `asyncValidationErrors` which returns a promise to check for errors, otherwise the validator promises won't be resolved. | ||
*`asyncValidationErrors` will also return any regular synchronous validation errors.* | ||
```javascript | ||
app.use(expressValidator({ | ||
customValidators: { | ||
isUsernameAvailable: function(username) { | ||
return new Promise(function(resolve, reject) { | ||
User.findOne({ username: username }) | ||
.then(function(user) { | ||
if (!user) { | ||
resolve(); | ||
} | ||
else { | ||
reject(user); | ||
} | ||
}) | ||
.catch(function(error){ | ||
if (error) { | ||
reject(error); | ||
} | ||
}); | ||
}); | ||
} | ||
} | ||
})); | ||
req.check('username', 'Username Taken').isUsernameAvailable(); | ||
req.asyncValidationErrors() | ||
.then(function() { | ||
// create user | ||
}) | ||
.catch(function(errors) { | ||
res.send(errors); | ||
}); | ||
``` | ||
## Validation by Schema | ||
@@ -321,7 +305,8 @@ | ||
## Validation errors | ||
## Validation result | ||
You have two choices on how to get the validation errors: | ||
### Result API | ||
The method `req.getValidationResult()` returns a Promise which resolves to a result object. | ||
```javascript | ||
```js | ||
req.assert('email', 'required').notEmpty(); | ||
@@ -331,9 +316,30 @@ req.assert('email', 'valid email required').isEmail(); | ||
var errors = req.validationErrors(); // Or req.asyncValidationErrors(); | ||
var mappedErrors = req.validationErrors(true); // Or req.asyncValidationErrors(true); | ||
req.getValidationResult().then(function(result) { | ||
// do something with the validation result | ||
}); | ||
``` | ||
errors: | ||
The API for the result object is the following: | ||
#### `result.isEmpty()` | ||
Returns a boolean determining whether there were errors or not. | ||
#### `result.useFirstErrorOnly()` | ||
Sets the `firstErrorOnly` flag of this result object, which modifies the way | ||
other methods like `result.array()` and `result.mapped()` work.<br> | ||
This method is chainable, so the following is OK: | ||
```js | ||
result.useFirstErrorOnly().array(); | ||
``` | ||
#### `result.array()` | ||
Returns an array of errors.<br> | ||
All errors for all validated parameters will be included, unless you specify that you want only the first error of each param by invoking `result.useFirstErrorOnly()`. | ||
```javascript | ||
var errors = result.array(); | ||
// errors will now contain something like this: | ||
[ | ||
@@ -346,5 +352,12 @@ {param: "email", msg: "required", value: "<received input>"}, | ||
mappedErrors: | ||
#### `result.mapped()` | ||
Returns an object of errors, where the key is the parameter name, and the value is an error object as returned by the error formatter. | ||
Because of historical reasons, by default this method will return the last error of each parameter.<br> | ||
You can change this behavior by invoking `result.useFirstErrorOnly()`, so the first error is returned instead. | ||
```javascript | ||
var errors = result.mapped(); | ||
// errors will now be similar to this: | ||
{ | ||
@@ -363,4 +376,45 @@ email: { | ||
``` | ||
*Note: Using mappedErrors will only provide the last error per param in the chain of validation errors.* | ||
#### `result.throw()` | ||
If there are errors, throws an `Error` object which is decorated with the same API as the validation result object.<br> | ||
Useful for dealing with the validation errors in the `catch` block of a `try..catch` or promise. | ||
```js | ||
try { | ||
result.throw(); | ||
res.send('success!'); | ||
} catch (e) { | ||
console.log(e.array()); | ||
res.send('oops, validation failed!'); | ||
} | ||
``` | ||
### Deprecated API | ||
The following methods are deprecated.<br> | ||
While they work, their API is unflexible and sometimes return weird results if compared to the bleeding edge `req.getValidationResult()`. | ||
Additionally, these methods may be removed in a future version. | ||
#### `req.validationErrors([mapped])` | ||
Returns synchronous errors in the form of an array, or an object that maps parameter to error in case `mapped` is passed as `true`.<br> | ||
If there are no errors, the returned value is `false`. | ||
```js | ||
var errors = req.validationErrors(); | ||
if (errors) { | ||
// do something with the errors | ||
} | ||
``` | ||
#### `req.asyncValidationErrors([mapped])` | ||
Returns a promise that will either resolve if no validation errors happened, or reject with an errors array/mapping object. For reference on this, see `req.validationErrors()`. | ||
```js | ||
req.asyncValidationErrors().then(function() { | ||
// all good here | ||
}, function(errors) { | ||
// damn, validation errors! | ||
}); | ||
``` | ||
### String formatting for error messages | ||
@@ -391,6 +445,12 @@ | ||
.isEmail(); | ||
var errors = req.validationErrors(); | ||
req.getValidationResult() | ||
.then(function(result){ | ||
console.log(result.array()); | ||
}); | ||
``` | ||
errors: | ||
prints: | ||
```javascript | ||
@@ -449,4 +509,7 @@ [ | ||
### Regex routes | ||
#### req.sanitizeCookies(); | ||
Only sanitizes `req.cookies`. This method is not covered by the general `req.sanitize()`. | ||
## Regex routes | ||
Express allows you to define regex routes like: | ||
@@ -453,0 +516,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Native code
Supply chain riskContains native code (e.g., compiled binaries or shared libraries). Including native code can obscure malicious behavior.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
529
0
103039
11
10
541
2
+ Addedbluebird@3.7.2(transitive)
+ Addedlodash@4.17.21(transitive)
+ Addedvalidator@6.1.0(transitive)
- Removedbluebird@3.4.7(transitive)
- Removedlodash@4.16.6(transitive)
- Removedvalidator@5.7.0(transitive)
Updatedbluebird@^3.4.0
Updatedlodash@^4.16.0
Updatedvalidator@~6.1.0