mirror of
https://github.com/Expand-sys/ccashfrontend
synced 2025-12-19 16:12:14 +11:00
256 lines
6.7 KiB
JavaScript
256 lines
6.7 KiB
JavaScript
var validator = require('validator');
|
|
var _ = require('lodash');
|
|
var utils = require('./utils');
|
|
const { checkSchema, validationResult } = require('../check');
|
|
const chainCreator = require('./chain-creator');
|
|
const getCustomMethods = require('./custom-methods');
|
|
const contextRunner = require('./legacy-runner');
|
|
|
|
// validators and sanitizers not prefixed with is/to
|
|
var additionalSanitizers = ['trim', 'ltrim', 'rtrim', 'escape', 'unescape', 'stripLow', 'whitelist', 'blacklist', 'normalizeEmail'];
|
|
|
|
var allLocations = ['params', 'query', 'body', 'headers', 'cookies'];
|
|
|
|
/**
|
|
* Adds validation methods to request object via express middleware
|
|
*
|
|
* @method expressValidator
|
|
* @param {object} options
|
|
* @return {function} middleware
|
|
*/
|
|
|
|
var expressValidator = function(options) {
|
|
options = options || {};
|
|
var defaults = {
|
|
customValidators: {},
|
|
customSanitizers: {},
|
|
errorFormatter: function(param, msg, value, location) {
|
|
return {
|
|
location,
|
|
param: param,
|
|
msg: msg,
|
|
value: value
|
|
};
|
|
}
|
|
};
|
|
|
|
_.defaults(options, defaults);
|
|
|
|
/**
|
|
* Initializes a sanitizer
|
|
*
|
|
* @class
|
|
* @param {(string|string[])} param path to property to sanitize
|
|
* @param {[type]} req request to sanitize
|
|
* @param {[string]} locations request property to find value
|
|
*/
|
|
|
|
function Sanitizer(param, req, locations) {
|
|
this.values = locations.map(function(location) {
|
|
return _.get(req[location], param);
|
|
});
|
|
|
|
this.req = req;
|
|
this.param = param;
|
|
this.locations = locations;
|
|
|
|
utils.mapAndExtend(
|
|
getCustomMethods(req, options).sanitizers,
|
|
Sanitizer.prototype,
|
|
utils.makeSanitizer
|
|
);
|
|
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* validate an object using a schema, using following format:
|
|
*
|
|
* {
|
|
* paramName: {
|
|
* validatorName: true,
|
|
* validator2Name: true
|
|
* }
|
|
* }
|
|
*
|
|
* Pass options or a custom error message:
|
|
*
|
|
* {
|
|
* paramName: {
|
|
* validatorName: {
|
|
* options: ['', ''],
|
|
* errorMessage: 'An Error Message'
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* @method validateSchema
|
|
* @param {Object} schema schema of validations
|
|
* @param {Request} req request to attach validation errors
|
|
* @param {string} loc request property to find value (body, params, query, etc.)
|
|
* @return {object[]} array of errors
|
|
*/
|
|
|
|
function validateSchema(schema, req, loc, contexts) {
|
|
checkSchema(schema, loc, (field, locations, message) => chainCreator(
|
|
field,
|
|
locations,
|
|
message,
|
|
contexts,
|
|
getCustomMethods(req, options)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Error formatter delegator to the legacy format
|
|
* @param {*} error
|
|
*/
|
|
function errorFormatter({ param, msg, value, location }) {
|
|
return options.errorFormatter(param, msg, value, location);
|
|
}
|
|
|
|
// _.set sanitizers as prototype methods on corresponding chains
|
|
_.forEach(validator, function(method, methodName) {
|
|
if (methodName.match(/^to/) || _.includes(additionalSanitizers, methodName)) {
|
|
Sanitizer.prototype[methodName] = utils.makeSanitizer(methodName, validator);
|
|
}
|
|
});
|
|
|
|
utils.mapAndExtend(options.customSanitizers, Sanitizer.prototype, utils.makeSanitizer);
|
|
|
|
return function(req, res, next) {
|
|
const contexts = [];
|
|
const runContexts = () => contextRunner(contexts, req);
|
|
|
|
var locations = ['body', 'params', 'query', 'cookies'];
|
|
|
|
// Extend existing validators. Fixes bug #341
|
|
const customMethods = getCustomMethods(req, options);
|
|
|
|
req._validationErrors = [];
|
|
req._asyncValidationErrors = [];
|
|
req.validationErrors = function(mapped) {
|
|
runContexts();
|
|
|
|
var result = validationResult(req).formatWith(errorFormatter);
|
|
if (result.isEmpty()) {
|
|
return false;
|
|
}
|
|
|
|
return mapped ? result.mapped() : result.array();
|
|
};
|
|
|
|
req.asyncValidationErrors = function(mapped) {
|
|
runContexts();
|
|
return Promise.all(req._asyncValidationErrors).then(() => {
|
|
if (req._validationErrors.length > 0) {
|
|
return Promise.reject(req.validationErrors(mapped, true));
|
|
}
|
|
|
|
return Promise.resolve();
|
|
});
|
|
};
|
|
|
|
req.getValidationResult = function() {
|
|
runContexts();
|
|
return Promise.all(req._asyncValidationErrors).then(() => {
|
|
return validationResult(req).formatWith(errorFormatter);
|
|
});
|
|
};
|
|
|
|
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) {
|
|
return new Sanitizer(param, req, [location]);
|
|
};
|
|
});
|
|
|
|
req.sanitizeHeaders = function(param) {
|
|
if (param === 'referrer') {
|
|
param = 'referer';
|
|
}
|
|
|
|
return new Sanitizer(param.toLowerCase(), req, ['headers']);
|
|
};
|
|
|
|
req.sanitize = function(param) {
|
|
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]
|
|
*/
|
|
/**
|
|
* @name req.checkCookies
|
|
* @see check
|
|
* @param param
|
|
* @param [failMsg]
|
|
*/
|
|
req['check' + _.capitalize(location)] = function(param, failMsg) {
|
|
if (_.isPlainObject(param)) {
|
|
return validateSchema(param, req, [location], contexts);
|
|
}
|
|
return chainCreator(param, location, failMsg, contexts, customMethods);
|
|
};
|
|
});
|
|
|
|
req.checkHeaders = function(param, failMsg) {
|
|
if (_.isPlainObject(param)) {
|
|
return validateSchema(param, req, ['headers'], contexts);
|
|
}
|
|
|
|
if (param === 'referrer') {
|
|
param = 'referer';
|
|
}
|
|
|
|
return chainCreator(param.toLowerCase(), 'headers', failMsg, contexts, customMethods);
|
|
};
|
|
|
|
req.check = function(param, failMsg) {
|
|
if (_.isPlainObject(param)) {
|
|
return validateSchema(param, req, ['params', 'query', 'body', 'headers', 'cookies'], contexts);
|
|
}
|
|
return chainCreator(param, allLocations, failMsg, contexts, customMethods);
|
|
};
|
|
|
|
req.filter = req.sanitize;
|
|
req.assert = req.check;
|
|
req.validate = req.check;
|
|
|
|
next();
|
|
};
|
|
};
|
|
|
|
module.exports = expressValidator;
|
|
module.exports.validator = validator;
|
|
module.exports.utils = utils;
|