1 | var ValidaInvalidError = require('./valida-invalid-error');
|
2 | var async = require('async');
|
3 |
|
4 |
|
5 | var Context = module.exports = function(valida, obj, schema, cb, groups) {
|
6 | this.valida = valida;
|
7 | this.obj = obj;
|
8 | this.schema = schema;
|
9 | this.cb = cb;
|
10 | this.groups = typeof groups == 'string' ? [groups] : groups;
|
11 |
|
12 | this.status = {
|
13 | errors: {},
|
14 | valid: true
|
15 | };
|
16 | };
|
17 |
|
18 |
|
19 | Context.prototype.isValid = function() {
|
20 | return this.status && this.status.valid;
|
21 | };
|
22 |
|
23 |
|
24 | Context.prototype.errors = function() {
|
25 | if (!this.status || this.status.valid) return;
|
26 | return this.status.errors;
|
27 | };
|
28 |
|
29 |
|
30 | Context.prototype.invalidError = function () {
|
31 | return new ValidaInvalidError(this.status.errors);
|
32 | };
|
33 |
|
34 |
|
35 | Context.prototype.addError = function(key, error) {
|
36 | this.status.errors[key] = this.status.errors[key] || [];
|
37 | this.status.errors[key].push(error);
|
38 | this.status.valid = false;
|
39 | };
|
40 |
|
41 |
|
42 | Context.prototype.groupsValid = function(groups) {
|
43 | var checkGroupsEmpty = !this.groups || this.groups.length === 0;
|
44 | var ruleGroupsEmpty = !groups || groups.length === 0;
|
45 |
|
46 | if (checkGroupsEmpty && ruleGroupsEmpty) return true;
|
47 | if (!checkGroupsEmpty && ruleGroupsEmpty) return true;
|
48 | if (!checkGroupsEmpty && !ruleGroupsEmpty) {
|
49 | for (var i = 0, len = this.groups.length; i < len; i++) {
|
50 | if (groups.indexOf(this.groups[i]) != -1) return true;
|
51 | }
|
52 | }
|
53 |
|
54 | return false;
|
55 | };
|
56 |
|
57 |
|
58 | Context.prototype.run = function() {
|
59 | Object.keys(this.schema).forEach(function (key) {
|
60 | var rules = this.schema[key];
|
61 |
|
62 |
|
63 | for (var i = 0, len = rules.length; i < len; i++) {
|
64 | if (!rules[i].sanitizer) continue;
|
65 | if (typeof this.obj[key] == 'undefined') continue;
|
66 | if (!this.groupsValid(rules[i].groups)) continue;
|
67 |
|
68 | var fn = rules[i].sanitizer;
|
69 | if (typeof fn === 'string') fn = this.valida.sanitizers[fn];
|
70 | if (!fn) return this.cb(new Error('invalid sanitizer ' + rules[i].sanitizer));
|
71 |
|
72 | this.obj[key] = fn(this, rules[i], this.obj[key]);
|
73 | }
|
74 | }, this);
|
75 |
|
76 | var asyncValidators = [];
|
77 | Object.keys(this.schema).forEach(function (key) {
|
78 | var rules = this.schema[key];
|
79 |
|
80 |
|
81 | for (var i = 0, len = rules.length; i < len; i++) {
|
82 | if (!rules[i].validator) continue;
|
83 | if (!this.groupsValid(rules[i].groups)) continue;
|
84 |
|
85 | var fn = rules[i].validator;
|
86 | if (typeof fn === 'string') fn = this.valida.validators[fn];
|
87 | if (!fn) return this.cb(new Error('invalid validator ' + rules[i].validator));
|
88 |
|
89 | if (fn.length == 4) {
|
90 | asyncValidators.push(asyncCall.bind(null, fn, this, key, rules[i], this.obj[key]));
|
91 | } else {
|
92 | var result = fn(this, rules[i], this.obj[key]);
|
93 | if (typeof result != 'undefined') this.addError(key, result);
|
94 | }
|
95 | }
|
96 | }, this);
|
97 |
|
98 | if (asyncValidators.length > 0) {
|
99 | var that = this;
|
100 | async.parallel(asyncValidators, function(err) {
|
101 | that.cb(err, that);
|
102 | });
|
103 | } else {
|
104 | this.cb(null, this);
|
105 | }
|
106 | };
|
107 |
|
108 |
|
109 | var asyncCall = function (fn, ctx, key, options, value, cb) {
|
110 | fn(ctx, options, value, function(err, result) {
|
111 | if (err) return cb(err);
|
112 | if (typeof result != 'undefined') ctx.addError(key, result);
|
113 | cb();
|
114 | });
|
115 | };
|