148 lines
4.1 KiB
TypeScript
148 lines
4.1 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();
|
|
};
|
|
}
|