Validaciones con validator.js

This commit is contained in:
Juan Ferrer Toribio 2017-02-02 10:52:09 +01:00
parent a13526f3e7
commit 4f5a5ceee0
4 changed files with 79 additions and 246 deletions

View File

@ -1,6 +1,6 @@
import {module} from './module'; import {module} from './module';
import {loopbackValidations} from 'vendor'; import {validator} from 'vendor';
console.log(validator);
directive.$inject = ['$interpolate', '$compile', '$window'] directive.$inject = ['$interpolate', '$compile', '$window']
export function directive(interpolate, compile, $window) { export function directive(interpolate, compile, $window) {
return { return {
@ -19,7 +19,6 @@ export function directive(interpolate, compile, $window) {
let entityName = firstUpper(split[0]); let entityName = firstUpper(split[0]);
let fieldName = split[1]; let fieldName = split[1];
let entity = vnValidations[entityName]; let entity = vnValidations[entityName];
if(!entity) if(!entity)
@ -82,257 +81,86 @@ export function directive(interpolate, compile, $window) {
function isValid(value, conf, messageNode) { function isValid(value, conf, messageNode) {
let valid = true; let valid = true;
let inst = {value: value};
let validator = validators[conf.validation]; let validator = validators[conf.validation];
if(!validator) try {
nullCheck(value, conf);
validator && validator(value, conf);
}
catch(e) {
let message = conf.message ? conf.message : e.message;
messageNode.text(message);
return false;
}
return true; return true;
validator.call(inst, 'value', conf, err);
function err(kind) {
var message, code = conf.code || conf.validation;
if (conf.message) {
message = conf.message;
}
if (!message && defaultMessages[conf.validation]) {
message = defaultMessages[conf.validation];
}
if (!message) {
message = 'is invalid';
}
if (kind) {
code += '.' + kind;
if (message[kind]) {
message = message[kind];
} else if (defaultMessages.common[kind]) {
message = defaultMessages.common[kind];
} else {
message = 'is invalid';
}
}
messageNode.text(message); // code
valid = false;
}
return valid;
} }
} }
module.directive('vnValidation', directive); module.directive('vnValidation', directive);
// Code portion of 'lib/validations.js' from 'loopback-datasource-juggler' package
/*!
* Presence validator
*/
function validatePresence(attr, conf, err, options) {
if (blank(this[attr])) {
err();
}
}
/*!
* Absence validator
*/
function validateAbsence(attr, conf, err, options) {
if (!blank(this[attr])) {
err();
}
}
/*!
* Length validator
*/
function validateLength(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
var len = this[attr].length;
if (conf.min && len < conf.min) {
err('min');
}
if (conf.max && len > conf.max) {
err('max');
}
if (conf.is && len !== conf.is) {
err('is');
}
}
/*!
* Numericality validator
*/
function validateNumericality(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (typeof this[attr] !== 'number' || isNaN(this[attr])) {
return err('number');
}
if (conf.int && this[attr] !== Math.round(this[attr])) {
return err('int');
}
}
/*!
* Inclusion validator
*/
function validateInclusion(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (!~conf.in.indexOf(this[attr])) {
err();
}
}
/*!
* Exclusion validator
*/
function validateExclusion(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (~conf.in.indexOf(this[attr])) {
err();
}
}
/*!
* Format validator
*/
function validateFormat(attr, conf, err, options) {
if (nullCheck.call(this, attr, conf, err)) return;
if (typeof this[attr] === 'string') {
if (!this[attr].match(conf['with'])) {
err();
}
} else {
err();
}
}
/*!
* Custom validator
*/
function validateCustom(attr, conf, err, options, done) {
if (typeof options === 'function') {
done = options;
options = {};
}
conf.customValidator.call(this, err, done);
}
/*!
* Uniqueness validator
*/
function validateUniqueness(attr, conf, err, options, done) {
if (typeof options === 'function') {
done = options;
options = {};
}
if (blank(this[attr])) {
return process.nextTick(done);
}
var cond = {where: {}};
cond.where[attr] = this[attr];
if (conf && conf.scopedTo) {
conf.scopedTo.forEach(function(k) {
var val = this[k];
if (val !== undefined)
cond.where[k] = this[k];
}, this);
}
var idName = this.constructor.definition.idName();
var isNewRecord = this.isNewRecord();
this.constructor.find(cond, options, function(error, found) {
if (error) {
err(error);
} else if (found.length > 1) {
err();
} else if (found.length === 1 && idName === attr && isNewRecord) {
err();
} else if (found.length === 1 && (
!this.id || !found[0].id || found[0].id.toString() != this.id.toString()
)) {
err();
}
done();
}.bind(this));
}
var validators = { var validators = {
presence: validatePresence, presence: function(value, conf) {
absence: validateAbsence, console.log(value);
length: validateLength, if(validator.isEmpty(value))
numericality: validateNumericality, throw new Error(`Value can't be empty`);
inclusion: validateInclusion, },
exclusion: validateExclusion, length: function(value, conf) {
format: validateFormat, let options = {
custom: validateCustom, min: conf.min || conf.is,
uniqueness: validateUniqueness, max: conf.max || conf.is
}; };
var defaultMessages = { if(!validator.isLength(value, options)) {
presence: 'can\'t be blank', if(conf.is)
absence: 'can\'t be set', throw new Error(`Value shoud be ${conf.is} characters long`);
'unknown-property': 'is not defined in the model', else
length: { throw new Error(`Value shoud have a length between ${conf.min} and ${conf.max}`);
min: 'too short',
max: 'too long',
is: 'length is wrong',
},
common: {
blank: 'is blank',
'null': 'is null',
},
numericality: {
'int': 'is not an integer',
'number': 'is not a number',
},
inclusion: 'is not included in the list',
exclusion: 'is reserved',
uniqueness: 'is not unique',
};
/**
* Checks if attribute is undefined or null. Calls err function with 'blank' or 'null'.
* See defaultMessages. You can affect this behaviour with conf.allowBlank and conf.allowNull.
* @param {String} attr Property name of attribute
* @param {Object} conf conf object for validator
* @param {Function} err
* @return {Boolean} returns true if attribute is null or blank
*/
function nullCheck(attr, conf, err) {
// First determine if attribute is defined
if (typeof this[attr] === 'undefined') {
if (!conf.allowBlank) {
err('blank');
} }
return true; },
numericality: function(value, conf) {
if(conf.int) {
if(!validator.isInt(value))
throw new Error(`Value shoud be integer`);
}
else {
if(!validator.isNumeric(vlaue))
throw new Error(`Value shoud be a number`);
}
},
inclusion: function(value, conf) {
if(!validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
exclusion: function(value, conf) {
if(validator.isIn(value, conf.in))
throw new Error(`Invalid value`);
},
format: function(value, conf) {
if(!validator.matches(value, conf.with))
throw new Error(`Invalid value`);
},
custom: function(value, conf) {
let valid = true;
function err(kind) {
valid = false;
}
let inst = {attr: value};
conf.customValidator.call(inst, err)
if(!valid)
throw new Error(`Invalid value`);
},
absence: function() {},
uniqueness: function() {},
};
function nullCheck(value, conf) {
if (typeof value === 'undefined') {
if (!conf.allowBlank)
throw new Error(`Value can't be blank`);
} else { } else {
// Now check if attribute is null if (value === null && !conf.allowNull)
if (this[attr] === null) { throw new Error(`Value can't be null`);
if (!conf.allowNull) {
err('null');
}
return true;
} }
} }
return false;
}
/*!
* Return true when v is undefined, blank array, null or empty string
* otherwise returns false
*
* @param {Mix} v
* Returns true if `v` is blank.
*/
function blank(v) {
if (typeof v === 'undefined') return true;
if (v instanceof Array && v.length === 0) return true;
if (v === null) return true;
if (typeof v === 'number' && isNaN(v)) return true;
if (typeof v == 'string' && v === '') return true;
return false;
}

3
client/vendor/src/validator.js vendored Normal file
View File

@ -0,0 +1,3 @@
import * as validatorJs from 'validator';
export const validator = validatorJs;

View File

@ -4,3 +4,4 @@ export * from './ui-router';
export * from './angular-translate'; export * from './angular-translate';
export * from './material-design-lite'; export * from './material-design-lite';
export * from './angular-paging'; export * from './angular-paging';
export * from './validator';

View File

@ -15,7 +15,8 @@
"angular-translate-loader-partial": "^2.13.1", "angular-translate-loader-partial": "^2.13.1",
"angular-ui-router": "^1.0.0-beta.3", "angular-ui-router": "^1.0.0-beta.3",
"material-design-lite": "^1.3.0", "material-design-lite": "^1.3.0",
"oclazyload": "^0.6.3" "oclazyload": "^0.6.3",
"validator": "^6.2.1"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "*", "babel-core": "*",