ffffng/server/validation/validator.js

93 lines
2.6 KiB
JavaScript

'use strict';
angular.module('ffffng').factory('Validator', function (_, Strings, Logger) {
// TODO: sanitize input for further processing as specified by constraints (correct types, trimming, etc.)
function isValidBoolean(value) {
return _.isBoolean(value) || value === 'true' || value === 'false';
}
function isValidNumber(constraint, value) {
if (_.isString(value)) {
value = Strings.parseInt(value);
}
if (!_.isNumber(value)) {
return false;
}
if (_.isNaN(value) || !_.isFinite(value)) {
return false;
}
if (_.isNumber(constraint.min) && value < constraint.min) {
return false;
}
if (_.isNumber(constraint.max) && value > constraint.max) {
return false;
}
return true;
}
function isValidEnum(constraint, value) {
if (!_.isString(value)) {
return false;
}
return _.indexOf(constraint.allowed, value) >= 0;
}
function isValidString(constraint, value) {
if (!_.isString(value)) {
return false;
}
var trimmed = value.trim();
return (trimmed === '' && constraint.optional) || trimmed.match(constraint.regex);
}
function isValid(constraint, acceptUndefined, value) {
if (value === undefined) {
return acceptUndefined || constraint.optional;
}
switch (constraint.type) {
case 'boolean':
return isValidBoolean(value);
case 'number':
return isValidNumber(constraint, value);
case 'enum':
return isValidEnum(constraint, value);
case 'string':
return isValidString(constraint, value);
}
Logger.tag('validation').error('No validation method for constraint type: {}', constraint.type);
return false;
}
function areValid(constraints, acceptUndefined, values) {
var fields = Object.keys(constraints);
for (var i = 0; i < fields.length; i ++) {
var field = fields[i];
if (!isValid(constraints[field], acceptUndefined, values[field])) {
return false;
}
}
return true;
}
return {
forConstraint: function (constraint, acceptUndefined) {
return _.partial(isValid, constraint, acceptUndefined);
},
forConstraints: function (constraints, acceptUndefined) {
return _.partial(areValid, constraints, acceptUndefined);
}
};
});