-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvalidator.js
162 lines (142 loc) · 5.85 KB
/
validator.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
// use this package in apigee
var validator = {};
validator.validateRequestBody = function (requestBody, schema, stripUnknown) {
// Helper functions for specific validations
function isNumber(value) {
if (typeof value === "number" && isFinite(value) && Number.isInteger(value)) {
return true;
}
if (typeof value === "string" && !isNaN(value) && isFinite(Number(value)) && Number.isInteger(Number(value))) {
return true;
}
return false;
}
function isString(value) {
return typeof value === "string";
}
function isPhoneNumber(value) {
value = value + "";
return typeof value === "string" && /^\d{10}$/.test(value);
}
function isValidDate(value, dateFormat) {
// Define date patterns
var datePatterns = {
"dd/mm/yyyy": /^(0[1-9]|[12][0-9]|3[01])[\/](0[1-9]|1[0-2])[\/]\d{4}$/,
"dd-mm-yyyy": /^(0[1-9]|[12][0-9]|3[01])[\-](0[1-9]|1[0-2])[\-]\d{4}$/,
"mm/dd/yyyy": /^(0[1-9]|1[0-2])[\/](0[1-9]|[12][0-9]|3[01])[\/]\d{4}$/,
"mm-dd-yyyy": /^(0[1-9]|1[0-2])[\-](0[1-9]|[12][0-9]|3[01])[\-]\d{4}$/,
"yyyy/mm/dd": /^\d{4}[\/](0[1-9]|1[0-2])[\/](0[1-9]|[12][0-9]|3[01])$/,
"yyyy-mm-dd": /^\d{4}[\-](0[1-9]|1[0-2])[\-](0[1-9]|[12][0-9]|3[01])$/
};
// Use default format if not specified
dateFormat = dateFormat || "dd/mm/yyyy";
// Validate against the specified or default date format
var pattern = datePatterns[dateFormat];
return pattern ? pattern.test(value) : false;
}
function validateMin(value, min) {
return Number(value) >= min;
}
function validateMax(value, max) {
return Number(value) <= max;
}
function validateMinLength(value, minLength) {
return value.length >= minLength;
}
function validateMaxLength(value, maxLength) {
return value.length <= maxLength;
}
function validateValidValues(value, validValues) {
return validValues.includes(value);
}
// Recursive function to validate the request body against the schema and strip unknown fields if required
function validateAndStrip(object, schema, errors) {
var validObject = {};
var schemaKeys = Object.keys(schema);
for (var i = 0; i < schemaKeys.length; i++) {
var key = schemaKeys[i];
if (schema.hasOwnProperty(key)) {
var rule = schema[key];
var value = object[key];
if (rule.required && (value === undefined || value === null)) {
errors.push('Field ' + key + ' is required.');
}
if (value !== undefined && value !== null) {
if (rule.type === "number") {
if (!isNumber(value)) {
errors.push('Field ' + key + ' should be an integer.');
}
if (rule.min !== undefined && !validateMin(value, rule.min)) {
errors.push('Field ' + key + ' should be at least ' + rule.min + '.');
}
if (rule.max !== undefined && !validateMax(value, rule.max)) {
errors.push('Field ' + key + ' should be at most ' + rule.max + '.');
}
if (rule.round && !Number.isInteger(Number(value))) {
errors.push('Field ' + key + ' should be a rounded number without decimal points.');
}
if (rule.phone && !isPhoneNumber(value)) {
errors.push('Field ' + key + ' should be a valid 10-digit phone number.');
}
} else if (rule.type === "string") {
if (!isString(value)) {
errors.push('Field ' + key + ' should be a string.');
}
if (rule.minLength !== undefined && !validateMinLength(value, rule.minLength)) {
errors.push('Field ' + key + ' should have at least ' + rule.minLength + ' characters.');
}
if (rule.maxLength !== undefined && !validateMaxLength(value, rule.maxLength)) {
errors.push('Field ' + key + ' should have at most ' + rule.maxLength + ' characters.');
}
if (rule.phone && !isPhoneNumber(value)) {
errors.push('Field ' + key + ' should be a valid 10-digit phone number.');
}
if (rule.validValues && !validateValidValues(value, rule.validValues)) {
errors.push('Field ' + key + ' should be one of the valid values: ' + rule.validValues.join(', ') + '.');
}
} else if (rule.type === "date") {
if (!isValidDate(value, rule.dateFormat)) {
errors.push('Field ' + key + ' should be a valid date in the format ' + (rule.dateFormat || "dd/mm/yyyy") + '.');
}
} else if (rule.type === "object") {
var nestedErrors = [];
// Recursive call to validate and strip nested object
var validNestedObject = validateAndStrip(value, rule.properties, nestedErrors);
if (nestedErrors.length > 0) {
errors.push.apply(errors, nestedErrors);
} else {
validObject[key] = validNestedObject;
}
} else {
errors.push('Unsupported type ' + rule.type + ' for field ' + key + '.');
}
if (!errors.some(err => err.includes(key))) {
validObject[key] = value;
}
}
}
}
if (stripUnknown) {
var objectKeys = Object.keys(object);
for (var j = 0; j < objectKeys.length; j++) {
var objectKey = objectKeys[j];
// Remove any key not present in the schema
if (!schema.hasOwnProperty(objectKey)) {
delete object[objectKey];
}
}
}
return validObject;
}
// Define the validation schema
var schemaDefinition = schema;
// Initialize errors array
var errors = [];
// Validate and strip unknown fields
var validRequestBody = validateAndStrip(requestBody, schemaDefinition, errors);
// Return the validation result
return {
errors: errors.length > 0 ? errors : null,
validRequestBody: validRequestBody
};
};