From a5d3c95145184895fc5360f379b26f70a63e73e0 Mon Sep 17 00:00:00 2001 From: Alex Holliday Date: Mon, 2 Mar 2026 17:29:48 +0000 Subject: [PATCH] validation refactoring --- server/src/controllers/checkController.ts | 15 ++--- server/src/controllers/geoCheckController.ts | 4 +- server/src/controllers/settingsController.ts | 2 +- .../src/validation/announcementValidation.ts | 21 ------ server/src/validation/checkValidation.ts | 67 ++++++++----------- server/src/validation/index.ts | 1 - .../src/validation/notificationValidation.ts | 17 +++++ 7 files changed, 53 insertions(+), 74 deletions(-) delete mode 100644 server/src/validation/announcementValidation.ts diff --git a/server/src/controllers/checkController.ts b/server/src/controllers/checkController.ts index 39c4db02a..ec6722bd3 100755 --- a/server/src/controllers/checkController.ts +++ b/server/src/controllers/checkController.ts @@ -7,9 +7,6 @@ import { deleteChecksParamValidation, deleteChecksByTeamIdParamValidation, updateChecksTTLBodyValidation, - ackCheckBodyValidation, - ackAllChecksParamValidation, - ackAllChecksBodyValidation, } from "@/validation/checkValidation.js"; const SERVICE_NAME = "checkController"; @@ -28,8 +25,8 @@ class CheckController { getChecksByMonitor = async (req: Request, res: Response, next: NextFunction) => { try { - await getChecksParamValidation.validateAsync(req.params); - await getChecksQueryValidation.validateAsync(req.query); + getChecksParamValidation.parse(req.params); + getChecksQueryValidation.parse(req.query); const result = await this.checkService.getChecksByMonitor({ monitorId: req?.params?.monitorId, @@ -49,7 +46,7 @@ class CheckController { getChecksByTeam = async (req: Request, res: Response, next: NextFunction) => { try { - await getTeamChecksQueryValidation.validateAsync(req.query); + getTeamChecksQueryValidation.parse(req.query); const checkData = await this.checkService.getChecksByTeam({ teamId: req?.user?.teamId, query: req?.query, @@ -80,7 +77,7 @@ class CheckController { deleteChecks = async (req: Request, res: Response, next: NextFunction) => { try { - await deleteChecksParamValidation.validateAsync(req.params); + deleteChecksParamValidation.parse(req.params); const deletedCount = await this.checkService.deleteChecks({ monitorId: req.params.monitorId as string, @@ -99,7 +96,7 @@ class CheckController { deleteChecksByTeamId = async (req: Request, res: Response, next: NextFunction) => { try { - await deleteChecksByTeamIdParamValidation.validateAsync(req.params); + deleteChecksByTeamIdParamValidation.parse(req.params); const deletedCount = await this.checkService.deleteChecksByTeamId({ teamId: req?.user?.teamId }); @@ -115,7 +112,7 @@ class CheckController { updateChecksTTL = async (req: Request, res: Response, next: NextFunction) => { try { - await updateChecksTTLBodyValidation.validateAsync(req.body); + updateChecksTTLBodyValidation.parse(req.body); await this.checkService.updateChecksTTL({ teamId: req?.user?.teamId, diff --git a/server/src/controllers/geoCheckController.ts b/server/src/controllers/geoCheckController.ts index 056599000..cfa7fe056 100644 --- a/server/src/controllers/geoCheckController.ts +++ b/server/src/controllers/geoCheckController.ts @@ -18,8 +18,8 @@ class GeoCheckController { getGeoChecksByMonitor = async (req: Request, res: Response, next: NextFunction) => { try { - await getChecksParamValidation.validateAsync(req.params); - await getChecksQueryValidation.validateAsync(req.query); + getChecksParamValidation.parse(req.params); + getChecksQueryValidation.parse(req.query); const result = await this.geoChecksService.getGeoChecksByMonitor({ monitorId: req?.params?.monitorId as string, diff --git a/server/src/controllers/settingsController.ts b/server/src/controllers/settingsController.ts index 354f34858..69443fd6a 100644 --- a/server/src/controllers/settingsController.ts +++ b/server/src/controllers/settingsController.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from "express"; import { updateAppSettingsBodyValidation } from "@/validation/settingsValidation.js"; -import { sendTestEmailBodyValidation } from "@/validation/announcementValidation.js"; +import { sendTestEmailBodyValidation } from "@/validation/notificationValidation.js"; import { AppError } from "@/utils/AppError.js"; const SERVICE_NAME = "SettingsController"; diff --git a/server/src/validation/announcementValidation.ts b/server/src/validation/announcementValidation.ts deleted file mode 100644 index 5f3514709..000000000 --- a/server/src/validation/announcementValidation.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { z } from "zod"; - -//**************************************** -// Announcement Validations -//**************************************** - -export const sendTestEmailBodyValidation = z.object({ - to: z.string().min(1, "To field is required"), - systemEmailHost: z.string().optional(), - systemEmailPort: z.number().optional(), - systemEmailSecure: z.boolean().optional(), - systemEmailPool: z.boolean().optional(), - systemEmailAddress: z.string().optional(), - systemEmailPassword: z.string().optional(), - systemEmailUser: z.string().optional(), - systemEmailConnectionHost: z.union([z.string(), z.literal("")]).optional(), - systemEmailIgnoreTLS: z.boolean().optional(), - systemEmailRequireTLS: z.boolean().optional(), - systemEmailRejectUnauthorized: z.boolean().optional(), - systemEmailTLSServername: z.union([z.string(), z.literal("")]).optional(), -}); diff --git a/server/src/validation/checkValidation.ts b/server/src/validation/checkValidation.ts index b88415876..011507692 100644 --- a/server/src/validation/checkValidation.ts +++ b/server/src/validation/checkValidation.ts @@ -1,56 +1,43 @@ -import joi from "joi"; +import { z } from "zod"; import { GeoContinents } from "@/types/geoCheck.js"; //**************************************** // Check Validations //**************************************** -export const ackCheckBodyValidation = joi.object({ - ack: joi.boolean(), +export const getChecksParamValidation = z.object({ + monitorId: z.string().min(1, "Monitor ID is required"), }); -export const ackAllChecksParamValidation = joi.object({ - monitorId: joi.string().optional(), - path: joi.string().valid("monitor", "team").required(), +export const getChecksQueryValidation = z.object({ + type: z.enum(["http", "ping", "pagespeed", "hardware", "docker", "port", "game", "grpc"]).optional(), + sortOrder: z.enum(["asc", "desc"]).optional(), + limit: z.number().optional(), + dateRange: z.enum(["recent", "hour", "day", "week", "month", "all"]).optional(), + filter: z.enum(["all", "up", "down", "resolve"]).optional(), + ack: z.boolean().optional(), + page: z.number().optional(), + rowsPerPage: z.number().optional(), + status: z.boolean().optional(), + continent: z.union([z.enum(GeoContinents), z.array(z.enum(GeoContinents))]).optional(), }); -export const ackAllChecksBodyValidation = joi.object({ - ack: joi.boolean(), +export const getTeamChecksQueryValidation = z.object({ + sortOrder: z.enum(["asc", "desc"]).optional(), + limit: z.number().optional(), + dateRange: z.enum(["recent", "hour", "day", "week", "month", "all"]).optional(), + filter: z.enum(["all", "up", "down", "resolve"]).optional(), + ack: z.boolean().optional(), + page: z.number().optional(), + rowsPerPage: z.number().optional(), }); -export const getChecksParamValidation = joi.object({ - monitorId: joi.string().required(), +export const deleteChecksParamValidation = z.object({ + monitorId: z.string().min(1, "Monitor ID is required"), }); -export const getChecksQueryValidation = joi.object({ - type: joi.string().valid("http", "ping", "pagespeed", "hardware", "docker", "port", "game", "grpc"), - sortOrder: joi.string().valid("asc", "desc"), - limit: joi.number(), - dateRange: joi.string().valid("recent", "hour", "day", "week", "month", "all"), - filter: joi.string().valid("all", "up", "down", "resolve"), - ack: joi.boolean(), - page: joi.number(), - rowsPerPage: joi.number(), - status: joi.boolean(), - continent: joi.alternatives().try(joi.string().valid(...GeoContinents), joi.array().items(joi.string().valid(...GeoContinents))), -}); +export const deleteChecksByTeamIdParamValidation = z.object({}); -export const getTeamChecksQueryValidation = joi.object({ - sortOrder: joi.string().valid("asc", "desc"), - limit: joi.number(), - dateRange: joi.string().valid("recent", "hour", "day", "week", "month", "all"), - filter: joi.string().valid("all", "up", "down", "resolve"), - ack: joi.boolean(), - page: joi.number(), - rowsPerPage: joi.number(), -}); - -export const deleteChecksParamValidation = joi.object({ - monitorId: joi.string().required(), -}); - -export const deleteChecksByTeamIdParamValidation = joi.object({}); - -export const updateChecksTTLBodyValidation = joi.object({ - ttl: joi.number().required(), +export const updateChecksTTLBodyValidation = z.object({ + ttl: z.number().min(1, "TTL is required"), }); diff --git a/server/src/validation/index.ts b/server/src/validation/index.ts index cd04ae2d2..4d7140d01 100644 --- a/server/src/validation/index.ts +++ b/server/src/validation/index.ts @@ -16,5 +16,4 @@ export * from "./maintenanceWindowValidation.js"; export * from "./settingsValidation.js"; export * from "./statusPageValidation.js"; export * from "./notificationValidation.js"; -export * from "./announcementValidation.js"; export * from "./userValidation.js"; diff --git a/server/src/validation/notificationValidation.ts b/server/src/validation/notificationValidation.ts index 73e6750f8..43eae5575 100644 --- a/server/src/validation/notificationValidation.ts +++ b/server/src/validation/notificationValidation.ts @@ -1,4 +1,5 @@ import joi from "joi"; +import { z } from "zod"; //**************************************** // Notification Validations @@ -76,3 +77,19 @@ export const createNotificationBodyValidation = joi.object({ otherwise: joi.string().allow("").optional(), }), }); + +export const sendTestEmailBodyValidation = z.object({ + to: z.string().min(1, "To field is required"), + systemEmailHost: z.string().optional(), + systemEmailPort: z.number().optional(), + systemEmailSecure: z.boolean().optional(), + systemEmailPool: z.boolean().optional(), + systemEmailAddress: z.string().optional(), + systemEmailPassword: z.string().optional(), + systemEmailUser: z.string().optional(), + systemEmailConnectionHost: z.union([z.string(), z.literal("")]).optional(), + systemEmailIgnoreTLS: z.boolean().optional(), + systemEmailRequireTLS: z.boolean().optional(), + systemEmailRejectUnauthorized: z.boolean().optional(), + systemEmailTLSServername: z.union([z.string(), z.literal("")]).optional(), +});