diff --git a/core/server/data/schema/validator.js b/core/server/data/schema/validator.js
index 8b0dfadedf..ec7874cf05 100644
--- a/core/server/data/schema/validator.js
+++ b/core/server/data/schema/validator.js
@@ -47,7 +47,7 @@ function validateSchema(tableName, model, options) {
schema[tableName][columnKey].nullable !== true &&
!Object.prototype.hasOwnProperty.call(schema[tableName][columnKey], 'defaultTo')
) {
- if (validator.empty(strVal)) {
+ if (validator.isEmpty(strVal)) {
message = tpl(messages.valueCannotBeBlank, {
tableName: tableName,
columnKey: columnKey
@@ -62,7 +62,7 @@ function validateSchema(tableName, model, options) {
// validate boolean columns
if (Object.prototype.hasOwnProperty.call(schema[tableName][columnKey], 'type')
&& schema[tableName][columnKey].type === 'bool') {
- if (!(validator.isBoolean(strVal) || validator.empty(strVal))) {
+ if (!(validator.isBoolean(strVal) || validator.isEmpty(strVal))) {
message = tpl(messages.valueMustBeBoolean, {
tableName: tableName,
columnKey: columnKey
@@ -74,7 +74,7 @@ function validateSchema(tableName, model, options) {
}
// CASE: ensure we transform 0|1 to false|true
- if (!validator.empty(strVal)) {
+ if (!validator.isEmpty(strVal)) {
model.set(columnKey, !!model.get(columnKey));
}
}
diff --git a/core/server/data/validation/validate.js b/core/server/data/validation/validate.js
index b577ce88a4..65d4eb427c 100644
--- a/core/server/data/validation/validate.js
+++ b/core/server/data/validation/validate.js
@@ -37,7 +37,7 @@ function validate(value, key, validations, tableName) {
let message;
value = _.toString(value);
- _.each(validations, function each(validationOptions, validationName) {
+ _.each(validations, (validationOptions, validationName) => {
let goodResult = true;
if (_.isBoolean(validationOptions)) {
@@ -72,7 +72,7 @@ function validate(value, key, validations, tableName) {
}
validationOptions.shift();
- }, this);
+ });
return validationErrors;
}
diff --git a/core/server/data/validation/validator.js b/core/server/data/validation/validator.js
index 8a65c88289..369aa05605 100644
--- a/core/server/data/validation/validator.js
+++ b/core/server/data/validation/validator.js
@@ -1,42 +1,48 @@
const _ = require('lodash');
-const validator = require('validator');
+const baseValidator = require('validator');
const moment = require('moment-timezone');
const assert = require('assert');
+const allowedValidators = [
+ 'isLength',
+ 'isEmpty',
+ 'isURL',
+ 'isEmail',
+ 'isIn',
+ 'isUUID',
+ 'isBoolean',
+ 'isInt',
+ 'isLowercase',
+ 'equals',
+ 'matches'
+];
+
function assertString(input) {
- assert(typeof input === 'string', 'Validator js validates strings only');
+ assert(typeof input === 'string', 'Validator validates strings only');
}
-// extends has been removed in validator >= 5.0.0, need to monkey-patch it back in
-// @TODO: We modify the global validator dependency here! https://github.com/chriso/validator.js/issues/525#issuecomment-213149570
-validator.extend = function (name, fn) {
- validator[name] = function () {
- const args = Array.prototype.slice.call(arguments);
- assertString(args[0]);
- return fn.apply(validator, args);
- };
+const validators = {};
+
+allowedValidators.forEach((name) => {
+ if (_.has(baseValidator, name)) {
+ validators[name] = baseValidator[name];
+ }
+});
+
+validators.isTimezone = function isTimezone(str) {
+ assertString(str);
+ return moment.tz.zone(str) ? true : false;
};
-// Provide a few custom validators
-validator.extend('empty', function empty(str) {
- return _.isEmpty(str);
-});
+validators.isEmptyOrURL = function isEmptyOrURL(str) {
+ assertString(str);
+ return (validators.isEmpty(str) || validators.isURL(str, {require_protocol: false}));
+};
-validator.extend('notContains', function notContains(str, badString) {
- return !_.includes(str, badString);
-});
+validators.isSlug = function isSlug(str) {
+ assertString(str);
+ return validators.matches(str, /^[a-z0-9\-_]+$/);
+};
-validator.extend('isTimezone', function isTimezone(str) {
- return moment.tz.zone(str) ? true : false;
-});
-
-validator.extend('isEmptyOrURL', function isEmptyOrURL(str) {
- return (_.isEmpty(str) || validator.isURL(str, {require_protocol: false}));
-});
-
-validator.extend('isSlug', function isSlug(str) {
- return validator.matches(str, /^[a-z0-9\-_]+$/);
-});
-
-module.exports = validator;
+module.exports = validators;
diff --git a/test/unit/data/validation/index_spec.js b/test/unit/data/validation/validate_spec.js
similarity index 78%
rename from test/unit/data/validation/index_spec.js
rename to test/unit/data/validation/validate_spec.js
index 2f6d4451b0..e9107a5dc5 100644
--- a/test/unit/data/validation/index_spec.js
+++ b/test/unit/data/validation/validate_spec.js
@@ -12,7 +12,5 @@ describe('Validation', function () {
);
validation.validate.should.be.a.Function();
-
- validation.validator.should.have.properties(['empty', 'notContains', 'isTimezone', 'isEmptyOrURL', 'isSlug']);
});
});
diff --git a/test/unit/data/validation/validator_spec.js b/test/unit/data/validation/validator_spec.js
index 7637ab5a94..6e3292d8b3 100644
--- a/test/unit/data/validation/validator_spec.js
+++ b/test/unit/data/validation/validator_spec.js
@@ -1,19 +1,43 @@
const should = require('should');
-const validation = require('../../../../core/server/data/validation');
+const {validator} = require('../../../../core/server/data/validation');
-describe('Validator dependency', function () {
- const validator = validation.validator;
+const validators = ['isLength',
+ 'isEmpty',
+ 'isURL',
+ 'isEmail',
+ 'isIn',
+ 'isUUID',
+ 'isBoolean',
+ 'isInt',
+ 'isLowercase',
+ 'equals',
+ 'matches'
+];
- it('isEmptyOrUrl filters javascript urls', function () {
- validator.isEmptyOrURL('javascript:alert(0)').should.be.false();
- validator.isEmptyOrURL('http://example.com/lol//').should.be.false();
- validator.isEmptyOrURL('http://example.com/lol?somequery=').should.be.false();
- validator.isEmptyOrURL('').should.be.true();
- validator.isEmptyOrURL('http://localhost:2368').should.be.true();
- validator.isEmptyOrURL('http://example.com/test/').should.be.true();
- validator.isEmptyOrURL('http://www.example.com/test/').should.be.true();
- validator.isEmptyOrURL('http://example.com/foo?somequery=bar').should.be.true();
- validator.isEmptyOrURL('example.com/test/').should.be.true();
+const custom = ['isTimezone', 'isEmptyOrURL', 'isSlug'];
+
+describe('Validator', function () {
+ it('should export our required functions', function () {
+ should.exist(validator);
+
+ validator.should.have.properties(validators);
+ validator.should.have.properties(custom);
+
+ Object.keys(validator).should.eql(validators.concat(custom));
+ });
+
+ describe('Custom Validators', function () {
+ it('isEmptyOrUrl filters javascript urls', function () {
+ validator.isEmptyOrURL('javascript:alert(0)').should.be.false();
+ validator.isEmptyOrURL('http://example.com/lol//').should.be.false();
+ validator.isEmptyOrURL('http://example.com/lol?somequery=').should.be.false();
+ validator.isEmptyOrURL('').should.be.true();
+ validator.isEmptyOrURL('http://localhost:2368').should.be.true();
+ validator.isEmptyOrURL('http://example.com/test/').should.be.true();
+ validator.isEmptyOrURL('http://www.example.com/test/').should.be.true();
+ validator.isEmptyOrURL('http://example.com/foo?somequery=bar').should.be.true();
+ validator.isEmptyOrURL('example.com/test/').should.be.true();
+ });
});
});