Skip to content

Commit 4b0fa29

Browse files
committed
add strict remove & forbidden remove sanitizations
1 parent 098168c commit 4b0fa29

File tree

6 files changed

+68
-67
lines changed

6 files changed

+68
-67
lines changed

examples/next.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,26 @@ let v = new Validator({
1010
const schema = {
1111
//id: { type: "number", positive: true, integer: true, convert: true },
1212
//name: { type: "string", min: 3, max: 255, padStart: 5 },
13-
//token: { type: "forbidden" },
13+
token: { type: "forbidden", remove: true },
1414
//password: { type: "string", min: 6 },
1515
//confirmPassword: { type: "equal", field: "password" },
16-
//roles: { type: "array", items: "string", min: 1 },
16+
//roles: { type: "array", items: "string", min: 1, default: ["user"] },
1717
/*friends: { type: "array", items: { type: "object", properties: {
1818
name: "string",
1919
username: "string"
2020
}}},*/
21-
/*address: { type: "object", properties: {
21+
/*address: { type: "object", strict: "remove", properties: {
2222
country: "string",
2323
city: "string"
2424
} },*/
25-
bio: { type: "string", convert: true },
25+
//bio: { type: "string", convert: true },
2626
//age: { type: "number", min: 18 },
2727
//email: { type: "email", mode: "precise", normalize: true },
2828
//verified: { type: "equal", value: true, strict: true },
2929
//status: "boolean" // short-hand def
3030
//createdAt: { type: "date", convert: true },
3131
//status: { type: "boolean", convert: true },
32-
//code: { type: "string", padEnd: 10, padChar: "\u2605" },
32+
//code: { type: "string", padEnd: 10, padChar: "\u2605", default: "default-code" },
3333
/*status: [
3434
{ type: "boolean" },
3535
{ type: "number" }
@@ -63,14 +63,15 @@ const obj = {
6363
zip: "1112"
6464
},
6565
bio: null,
66-
roles: ["admin", "user", 3, 2, true],
66+
//roles: ["admin", "user", 3, 2, true],
6767
friends: [
6868
{ name: "John", username: "johnny" },
6969
{ name: "Jane", username: "jane" }
7070
],
7171
password: "123456",
7272
confirmPassword: "123456",
73-
code: "123",
73+
token: "abcdef",
74+
//code: "123",
7475
status: 1,
7576
verified: true,
7677

lib/rules/array.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ module.exports = function({ schema, messages }, path, context) {
7474
`);
7575

7676
const rule = this.getRuleFromSchema(schema.items);
77-
src.push(this.compileRule(rule, context, path, "arr[i] = context.fn[%%INDEX%%](arr[i], (parentField ? parentField : \"\") + \"[\" + i + \"]\", parent, errors, context);"));
77+
src.push(this.compileRule(rule, context, path, "arr[i] = context.fn[%%INDEX%%](arr[i], (parentField ? parentField : \"\") + \"[\" + i + \"]\", parent, errors, context);", "arr[i]"));
7878
/*
7979
const res = rule.ruleFunction.call(this, rule, path, context);
8080
context.rules[context.index] = rule;

lib/rules/forbidden.js

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,29 @@
33
/** Signature: function(value, field, parent, errors, context)
44
*/
55
module.exports = function checkForbidden({ schema, messages }, path) {
6-
return {
7-
source: `
8-
if (value !== null && value !== undefined)
9-
${this.makeError({ type: "forbidden", actual: "value", messages })}
6+
const src = [];
7+
8+
src.push(`
9+
if (value !== null && value !== undefined) {
10+
`);
11+
12+
if (schema.remove) {
13+
src.push(`
14+
return undefined;
15+
`);
1016

11-
return value;
12-
`
17+
} else {
18+
src.push(`
19+
${this.makeError({ type: "forbidden", actual: "value", messages })}
20+
`);
21+
}
22+
23+
src.push(`
24+
}
25+
return value;
26+
`);
27+
28+
return {
29+
source: src.join("\n")
1330
};
1431
};

lib/rules/multi.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,17 +19,7 @@ module.exports = function({ schema, messages }, path, context) {
1919
`);
2020

2121
const rule = this.getRuleFromSchema(schema.rules[i]);
22-
context.rules[context.index] = rule;
23-
const res = rule.ruleFunction.call(this, rule, path, context);
24-
if (res.source) {
25-
const fn = new Function("value", "field", "parent", "errors", "context", res.source);
26-
context.fn[context.index] = fn;
27-
src.push(`
28-
var tmpVal = context.fn[${context.index}](value, field, parent, errors, context);
29-
`);
30-
}
31-
context.index++;
32-
22+
src.push(this.compileRule(rule, context, path, "var tmpVal = context.fn[%%INDEX%%](value, field, parent, errors, context);", "tmpVal"));
3323
src.push(`
3424
if (errors.length == errBefore) {
3525
hasValid = true;

lib/rules/object.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -61,23 +61,11 @@ module.exports = function({ schema, messages }, path, context) {
6161
sourceCode.push(`value = ${safePropName};`);
6262

6363
const rule = this.getRuleFromSchema(subSchema[property]);
64-
sourceCode.push(this.compileRule(rule, context, newPath, `${safePropName} = context.fn[%%INDEX%%](value, field, parentObj, errors, context);`));
65-
/*context.rules[context.index] = rule;
66-
const res = rule.ruleFunction.call(this, rule, newPath, context);
67-
if (res.source) {
68-
const fn = new Function("value", "field", "parent", "errors", "context", res.source);
69-
context.fn[context.index] = fn;
70-
sourceCode.push(this.wrapRequiredCheckSourceCode(rule, `
71-
${safePropName} = context.fn[${context.index}](value, field, parentObj, errors, context);
72-
`));
73-
} else {
74-
sourceCode.push(this.wrapRequiredCheckSourceCode(rule));
75-
}
76-
context.index++;*/
64+
sourceCode.push(this.compileRule(rule, context, newPath, `${safePropName} = context.fn[%%INDEX%%](value, field, parentObj, errors, context);`, safePropName));
7765
}
7866

7967
// Strict handler
80-
if (schema.strict === true) {
68+
if (schema.strict) {
8169
const allowedProps = Object.keys(subSchema);
8270

8371
sourceCode.push(`
@@ -91,7 +79,19 @@ module.exports = function({ schema, messages }, path, context) {
9179
}
9280
}
9381
if (invalidProps.length) {
82+
`);
83+
if (schema.strict == "remove") {
84+
sourceCode.push(`
85+
invalidProps.forEach(function(field) {
86+
delete parentObj[field];
87+
});
88+
`);
89+
} else {
90+
sourceCode.push(`
9491
${this.makeError({ type: "objectStrict", expected: "\"" + allowedProps.join(", ") + "\"", actual: "invalidProps.join(', ')", messages })}
92+
`);
93+
}
94+
sourceCode.push(`
9595
}
9696
`);
9797
}

lib/validator.js

Lines changed: 21 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,22 +58,30 @@ Validator.prototype.validate = function(obj, schema) {
5858
return check(obj);
5959
};
6060

61-
Validator.prototype.wrapRequiredCheckSourceCode = function(rule, innerSrc) {
61+
Validator.prototype.wrapRequiredCheckSourceCode = function(rule, innerSrc, resVar) {
6262
const src = [];
63+
const defaultValue = rule.schema.default != null ? JSON.stringify(rule.schema.default) : null;
64+
6365
// Required, optional, forbidden
66+
src.push(`
67+
if (value === undefined || value === null) {
68+
`);
6469
if (rule.schema.optional === true || rule.schema.type == "forbidden") {
6570
// Optional field
66-
src.push(`
67-
if (value === undefined || value === null) {
68-
// Do nothing, it's an optional field
69-
} else {`);
71+
if (defaultValue != null && resVar) {
72+
src.push(`${resVar} = ${defaultValue};`);
73+
} else {
74+
src.push("// Do nothing, it's an optional field");
75+
}
7076
} else {
7177
// Required field
72-
src.push(`
73-
if (value === undefined || value === null) {
74-
${this.makeError({ type: "required", actual: "value", messages: rule.messages })}
75-
} else {`);
78+
if (defaultValue != null && resVar) {
79+
src.push(`${resVar} = ${defaultValue};`);
80+
} else {
81+
src.push(this.makeError({ type: "required", actual: "value", messages: rule.messages }));
82+
}
7683
}
84+
src.push("} else {");
7785

7886
if (innerSrc)
7987
src.push(innerSrc);
@@ -125,22 +133,7 @@ Validator.prototype.compile = function(schema) {
125133
];
126134

127135
const rule = this.getRuleFromSchema(schema);
128-
sourceCode.push(this.compileRule(rule, context, null, "context.fn[%%INDEX%%](value, field, null, errors, context);"));
129-
/*
130-
context.rules[context.index] = rule;
131-
const res = rule.ruleFunction.call(this, rule, null, context);
132-
if (res.source) {
133-
const fn = new Function("value", "field", "parent", "errors", "context", res.source);
134-
context.fn[context.index] = fn;
135-
sourceCode.push(this.wrapRequiredCheckSourceCode(rule, `
136-
context.fn[${context.index}](value, field, null, errors, context);
137-
`));
138-
139-
} else {
140-
sourceCode.push(this.wrapRequiredCheckSourceCode(rule));
141-
}
142-
context.index++;
143-
*/
136+
sourceCode.push(this.compileRule(rule, context, null, "context.fn[%%INDEX%%](value, field, null, errors, context);", "value"));
144137

145138
sourceCode.push("if (errors.length) {");
146139
sourceCode.push(`
@@ -180,7 +173,7 @@ Validator.prototype.compile = function(schema) {
180173
};
181174
};
182175

183-
Validator.prototype.compileRule = function(rule, context, path, innerSrc) {
176+
Validator.prototype.compileRule = function(rule, context, path, innerSrc, resVar) {
184177
const sourceCode = [];
185178

186179
const item = this.cache.get(rule.schema);
@@ -195,7 +188,7 @@ Validator.prototype.compileRule = function(rule, context, path, innerSrc) {
195188
${innerSrc.replace("%%INDEX%%", rule.index)}
196189
rule.cycleStack.pop(value);
197190
}
198-
`));
191+
`, resVar));
199192

200193
} else {
201194
this.cache.set(rule.schema, rule);
@@ -206,7 +199,7 @@ Validator.prototype.compileRule = function(rule, context, path, innerSrc) {
206199
if (res.source) {
207200
const fn = new Function("value", "field", "parent", "errors", "context", res.source);
208201
context.fn[rule.index] = fn;
209-
sourceCode.push(this.wrapRequiredCheckSourceCode(rule, innerSrc.replace("%%INDEX%%", rule.index)));
202+
sourceCode.push(this.wrapRequiredCheckSourceCode(rule, innerSrc.replace("%%INDEX%%", rule.index), resVar));
210203
} else {
211204
sourceCode.push(this.wrapRequiredCheckSourceCode(rule));
212205
}

0 commit comments

Comments
 (0)