You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.8 KiB
125 lines
3.8 KiB
import { Request, Response, NextFunction } from "express" |
|
import { Logging } from "@hibas123/nodelogging"; |
|
import { isBoolean, isString, isNumber, isObject, isDate, isArray, isSymbol } from "util"; |
|
import RequestError, { HttpStatusCode } from "../../helper/request_error"; |
|
|
|
export enum Types { |
|
STRING, |
|
NUMBER, |
|
BOOLEAN, |
|
EMAIL, |
|
OBJECT, |
|
DATE, |
|
ARRAY, |
|
ENUM |
|
} |
|
|
|
function isEmail(value: any): boolean { |
|
return /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(value) |
|
} |
|
|
|
export interface CheckObject { |
|
type: Types |
|
query?: boolean |
|
optional?: boolean |
|
|
|
/** |
|
* Only when Type.ENUM |
|
* |
|
* values to check before |
|
*/ |
|
values?: string[] |
|
|
|
/** |
|
* Only when Type.STRING |
|
*/ |
|
notempty?: boolean // Only STRING |
|
} |
|
|
|
export interface Checks { |
|
[index: string]: CheckObject// | Types |
|
} |
|
|
|
// req: Request, res: Response, next: NextFunction |
|
export default function (fields: Checks, noadditional = false) { |
|
return (req: Request, res: Response, next: NextFunction) => { |
|
let errors: { message: string, field: string }[] = [] |
|
|
|
function check(data: any, field_name: string, field: CheckObject) { |
|
if (data !== undefined && data !== null) { |
|
switch (field.type) { |
|
case Types.STRING: |
|
if (isString(data)) { |
|
if (!field.notempty) return; |
|
if (data !== "") return; |
|
} |
|
break; |
|
case Types.NUMBER: |
|
if (isNumber(data)) return; |
|
break; |
|
case Types.EMAIL: |
|
if (isEmail(data)) return; |
|
break; |
|
case Types.BOOLEAN: |
|
if (isBoolean(data)) return; |
|
break; |
|
case Types.OBJECT: |
|
if (isObject(data)) return; |
|
break; |
|
case Types.ARRAY: |
|
if (isArray(data)) return; |
|
break; |
|
case Types.DATE: |
|
if (isDate(data)) return; |
|
break; |
|
case Types.ENUM: |
|
if (isString(data)) { |
|
if (field.values.indexOf(data) >= 0) return; |
|
} |
|
break; |
|
default: |
|
Logging.error(`Invalid type to check: ${field.type} ${Types[field.type]}`) |
|
} |
|
errors.push({ |
|
message: res.__("Field {{field}} has wrong type. It should be from type {{type}}", { field: field_name, type: Types[field.type].toLowerCase() }), |
|
field: field_name |
|
}) |
|
} else { |
|
if (!field.optional) errors.push({ |
|
message: res.__("Field {{field}} is not defined", { field: field_name }), |
|
field: field_name |
|
}) |
|
} |
|
} |
|
|
|
for (let field_name in fields) { |
|
let field = fields[field_name] |
|
let data = fields[field_name].query ? req.query[field_name] : req.body[field_name] |
|
check(data, field_name, field) |
|
} |
|
|
|
if (noadditional) { //Checks if the data given has additional parameters |
|
let should = Object.keys(fields); |
|
should = should.filter(e => !fields[e].query); //Query parameters should not exist on body |
|
let has = Object.keys(req.body); |
|
|
|
has.every(e => { |
|
if (should.indexOf(e) >= 0) { |
|
return true; |
|
} else { |
|
errors.push({ |
|
message: res.__("Field {{field}} should not be there", { field: e }), |
|
field: e |
|
}) |
|
return false; |
|
} |
|
}) |
|
} |
|
|
|
if (errors.length > 0) { |
|
let err = new RequestError(errors, HttpStatusCode.BAD_REQUEST, true); |
|
next(err); |
|
} else |
|
next() |
|
} |
|
} |