125 lines
3.8 KiB
TypeScript
125 lines
3.8 KiB
TypeScript
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()
|
|
}
|
|
} |