1 try { var _
= require("underscore"); } catch (err
) {} //for server
5 // Cell in assessment.questions array
7 "index": "section", //"2.2.1", "3.2", "1" ...etc
9 "options": "stringArray", //only for quiz
11 "answer": "string", //both this and next are mutually exclusive
12 "choice": "integerArray",
19 "input": "stringOrIntegerArray",
22 // One student response to an exam
25 // (array of) strings for open questions, arrays of integers for quizzes:
26 "inputs": Validator
.Input
,
27 "startTime": "positiveInteger",
28 "endTime": "positiveInteger",
29 "discoTime": "positiveInteger",
30 "discoCount": "positiveInteger",
31 "totalDisco": "positiveInteger",
32 "password": "password",
35 Validator
.Assessment
= {
39 "mode": "alphanumeric", //"open" or "exam", but alphanumeric is good enough
42 "display": "alphanumeric", //"one" or "all"
44 "introduction": "string",
45 "coefficient": "number",
46 "questions": Validator
.Question
,
47 "papers": Validator
.Paper
,
54 "initials": "unchecked", //not a user input
55 "loginToken": "unchecked",
56 "sessionTokens": "unchecked",
57 "token": "alphanumeric", //exception: for the purpose of user registration
63 "group": "positiveInteger",
70 "description": "string",
72 "students": Validator
.Student
,
75 Object
.assign(Validator
,
77 // Recurse into sub-documents
78 checkObject_aux: function(obj
, model
)
80 for (let key
of Object
.keys(obj
))
83 return "Unknown field";
84 if (model
[key
] == "unchecked") //not a user input (ignored)
86 if (_
.isObject(model
[key
]))
88 // TODO: next loop seems too heavy... (only a concern if big class import?)
89 for (let item
of obj
[key
])
91 let error
= Validator
.checkObject_aux(item
, model
[key
]);
98 let error
= Validator
[ "check_" + model
[key
] ](obj
[key
]);
100 return key
+ ": " + error
;
106 // Always check top-level object
107 checkObject: function(obj
, name
)
109 return Validator
.checkObject_aux(obj
, Validator
[name
]);
112 "check_string": function(arg
)
114 return ""; //strings are unchecked, but sanitized
117 "check_section": function(arg
)
119 if (!_
.isString(arg
))
120 return "not a string";
121 if (!/^[0-9.]+$/.test(arg
))
122 return "digits and dot only";
126 "check_stringArray": function(arg
)
128 return !_
.isArray(arg
) ? "not an array" : "";
131 "check_alphanumeric": function(arg
)
133 return arg
.match(/^[\w]{1,32}$/) === null ? "[1,32] alphanumerics" : "";
136 "check_bson": function(arg
)
138 return arg
.match(/^[a-z0-9]{24}$/) === null ? "not a BSON id" : "";
141 "check_name": function(arg
)
143 if (!_
.isString(arg
))
144 return "not a string";
145 if (!/^[a
-zA
-Z
\u00C0-\u024F -]{1,32}$/.test(arg
))
146 return "[1,32] letters + hyphen/space";
150 "check_email": function(arg
)
152 if (!_
.isString(arg
))
153 return "not a string";
155 return "string too long: max. 64 characters";
156 // Regexp used in "type='email'" inputs ( http://emailregex.com/ )
157 if (!/^[a-zA-Z0-9.!#$%&’*+/=?^_
`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/.test(arg))
158 return "X@Y, alphanumerics and . _ - +(X)";
162 "check_code": function(arg)
164 if (!_.isString(arg))
165 return "not a string";
166 if (!/^[\w.-]{1,16}$/.test(arg))
167 return "[1,16] alphanumerics and . _ -";
171 "check_number": function(arg)
173 if (!_.isNumber(arg))
174 arg = parseFloat(arg);
176 return "not a number";
180 "check_integer": function(arg)
182 if (!_.isNumber(arg))
184 if (isNaN(arg) || arg % 1 != 0)
185 return "not an integer";
189 "check_positiveInteger": function(arg)
191 return Validator["check_integer"](arg) || (arg<0 ? "not positive" : "");
194 "check_boolean": function(arg)
196 if (!_.isBoolean(arg))
197 return "not a boolean";
201 "check_password": function(arg)
203 if (!_.isString(arg))
204 return "not a string";
205 if (!/^[\x21-\x7E]{1,16}$/.test(arg))
206 return "[1,16] ASCII characters with code in [33,126]";
210 // Sha-1 hash: length 40, hexadecimal
211 "check_hash": function(arg)
213 if (!_.isString(arg))
214 return "not a string";
215 if (!/^[a-f0-9]{40}$/.test(arg))
216 return "not a sha-1 hash";
220 "check_integerArray": function(arg)
223 return "not an array";
224 for (let i=0; i<arg.length; i++)
226 let error = Validator["check_integer"](arg[i]);
227 if (error.length > 0)
233 "check_stringOrIntegerArray": function(arg)
235 if (!_.isString(arg))
236 return Validator["check_integerArray"](arg);
241 try { module.exports = Validator.checkObject; } catch (err) {} //for server