impr(server): add header validation, allow validation to accept unknown fields (fehmer) (#4824)

* impr: Add header validation, allow validation to accept unknown fields

* review comments
This commit is contained in:
Christian Fehmer 2023-12-04 14:30:13 +01:00 committed by GitHub
parent e077be788a
commit 84dfa7aca9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 57 additions and 24 deletions

View file

@ -46,21 +46,23 @@ router.post(
}),
authenticateRequest(),
RateLimit.newQuotesAdd,
validateRequest({
body: {
text: joi.string().min(60).required(),
source: joi.string().required(),
language: joi
.string()
.regex(/^[\w+]+$/)
.required(),
captcha: joi
.string()
.regex(/[\w-_]+/)
.required(),
validateRequest(
{
body: {
text: joi.string().min(60).required(),
source: joi.string().required(),
language: joi
.string()
.regex(/^[\w+]+$/)
.required(),
captcha: joi
.string()
.regex(/[\w-_]+/)
.required(),
},
},
validationErrorMessage: "Please fill all the fields",
}),
{ validationErrorMessage: "Please fill all the fields" }
),
asyncHandler(QuoteController.addQuote)
);
@ -68,14 +70,16 @@ router.post(
"/approve",
authenticateRequest(),
RateLimit.newQuotesAction,
validateRequest({
body: {
quoteId: joi.string().required(),
editText: joi.string().allow(null),
editSource: joi.string().allow(null),
validateRequest(
{
body: {
quoteId: joi.string().required(),
editText: joi.string().allow(null),
editSource: joi.string().allow(null),
},
},
validationErrorMessage: "Please fill all the fields",
}),
{ validationErrorMessage: "Please fill all the fields" }
),
checkIfUserIsQuoteMod,
asyncHandler(QuoteController.approveQuote)
);

View file

@ -129,11 +129,37 @@ interface ValidationSchema {
body?: object;
query?: object;
params?: object;
headers?: object;
}
interface ValidationSchemaOption {
allowUnknown?: boolean;
}
interface ValidationHandlingOptions {
validationErrorMessage?: string;
}
function validateRequest(validationSchema: ValidationSchema): RequestHandler {
const { validationErrorMessage } = validationSchema;
type ValidationSchemaOptions = {
[schema in keyof ValidationSchema]?: ValidationSchemaOption;
} & ValidationHandlingOptions;
const VALIDATION_SCHEMA_DEFAULT_OPTIONS: ValidationSchemaOptions = {
body: { allowUnknown: false },
headers: { allowUnknown: true },
params: { allowUnknown: false },
query: { allowUnknown: false },
};
function validateRequest(
validationSchema: ValidationSchema,
validationOptions: ValidationSchemaOptions = VALIDATION_SCHEMA_DEFAULT_OPTIONS
): RequestHandler {
const options = {
...VALIDATION_SCHEMA_DEFAULT_OPTIONS,
...validationOptions,
};
const { validationErrorMessage } = options;
const normalizedValidationSchema: ValidationSchema = _.omit(
validationSchema,
"validationErrorMessage"
@ -143,7 +169,10 @@ function validateRequest(validationSchema: ValidationSchema): RequestHandler {
_.each(
normalizedValidationSchema,
(schema: object, key: keyof ValidationSchema) => {
const joiSchema = joi.object().keys(schema);
const joiSchema = joi
.object()
.keys(schema)
.unknown(options[key]?.allowUnknown);
const { error } = joiSchema.validate(req[key] ?? {});
if (error) {