diff --git a/server/src/server/middleware/prudence-validate.ts b/server/src/server/middleware/prudence-validate.ts index 9d7d2ac29..f162a3d64 100644 --- a/server/src/server/middleware/prudence-validate.ts +++ b/server/src/server/middleware/prudence-validate.ts @@ -1,4 +1,10 @@ -import Prudence, { MiddlewareErrorHandler } from "prudence"; +import Prudence, { + MiddlewareErrorHandler, + PrudenceSchema, + ErrorMessages, + PrudenceOptions, +} from "prudence"; +import { RequestHandler } from "express-serve-static-core"; import CreateLogCtx from "lib/logger/logger"; const logger = CreateLogCtx(__filename); @@ -6,31 +12,52 @@ const logger = CreateLogCtx(__filename); const printf = (message: string, stringVal: string | null, keychain: string | null) => `[${keychain}] ${message}${stringVal ? ` (Received ${stringVal})` : ""}`; -const API_ERR_HANDLER: MiddlewareErrorHandler = (req, res, next, error) => { - let stringVal = error.userVal; - if (error.keychain && error.keychain.includes("password") && error.userVal) { - stringVal = "****"; - } +const API_ERR_HANDLER = + (logLevel: TachiLogLevels): MiddlewareErrorHandler => + (req, res, next, error) => { + let stringVal = error.userVal; + if (error.keychain && error.keychain.includes("password") && error.userVal) { + stringVal = "****"; + } - if (typeof stringVal === "object" && stringVal !== null && !stringVal.toString) { - // this is probably null-prototype - stringVal = null; - } else if (stringVal === undefined) { - stringVal = "nothing"; - } else { - stringVal = String(stringVal); - } + if (typeof stringVal === "object" && stringVal !== null && !stringVal.toString) { + // this is probably null-prototype + stringVal = null; + } else if (stringVal === undefined) { + stringVal = "nothing"; + } else { + stringVal = String(stringVal); + } - logger.info(`Prudence rejection: ${error.message}, ${stringVal} [K:${error.keychain}]`, { - userVal: error.userVal, - }); + logger[logLevel]( + `Prudence rejection: ${error.message}, ${stringVal} [K:${error.keychain}]`, + { + userVal: error.userVal, + } + ); - return res.status(400).json({ - success: false, - description: printf(error.message, stringVal as string | null, error.keychain), - }); -}; + return res.status(400).json({ + success: false, + description: printf(error.message, stringVal as string | null, error.keychain), + }); + }; -const prValidate = Prudence.CurryMiddleware(API_ERR_HANDLER); +// Cache all of the possible API_ERROR_HANDLERS to avoid function creation +// overhead at runtime. +const API_ERROR_HANDLERS = Object.fromEntries( + (["crit", "severe", "error", "warn", "info", "verbose", "debug"] as const).map((e) => [ + e, + API_ERR_HANDLER(e), + ]) +) as Record; + +type TachiLogLevels = "crit" | "severe" | "error" | "warn" | "info" | "verbose" | "debug"; + +const prValidate = ( + s: PrudenceSchema, + errorMessage?: ErrorMessages, + options?: Partial, + level: TachiLogLevels = "info" +): RequestHandler => Prudence.CurryMiddleware(API_ERROR_HANDLERS[level])(s, errorMessage, options); export default prValidate; diff --git a/server/src/server/router/api/v1/auth/router.ts b/server/src/server/router/api/v1/auth/router.ts index 0682c5b3b..bf69b38e8 100644 --- a/server/src/server/router/api/v1/auth/router.ts +++ b/server/src/server/router/api/v1/auth/router.ts @@ -50,7 +50,9 @@ router.post( username: "Invalid username. Usernames cannot start with a number, and must be between 2 and 20 characters.", captcha: "Please fill out the captcha.", - } + }, + undefined, + "verbose" ), async (req, res) => { if (req.session.tachi?.user.id) { @@ -171,7 +173,9 @@ router.post( email: "Invalid email.", inviteCode: "Invalid invite code.", captcha: "Please fill out the captcha.", - } + }, + undefined, + "verbose" ), async (req, res) => { logger.verbose(`Recieved register request with username ${req.body.username} (${req.ip})`);