diff --git a/server/src/service/business/monitorService.ts b/server/src/service/business/monitorService.ts index 742e0200a..947a971fe 100644 --- a/server/src/service/business/monitorService.ts +++ b/server/src/service/business/monitorService.ts @@ -223,7 +223,8 @@ export class MonitorService implements IMonitorService { checksData.monitorType !== "port" && checksData.monitorType !== "game" && checksData.monitorType !== "grpc" && - checksData.monitorType !== "websocket" + checksData.monitorType !== "websocket" && + checksData.monitorType !== "dns" ) { throw new AppError({ message: `${monitor.type} monitors are not supported for uptime details`, status: 400 }); } diff --git a/server/src/validation/checkValidation.ts b/server/src/validation/checkValidation.ts index e511118e6..8a4a7938e 100644 --- a/server/src/validation/checkValidation.ts +++ b/server/src/validation/checkValidation.ts @@ -11,7 +11,7 @@ export const getChecksParamValidation = z.object({ }); export const getChecksQueryValidation = z.object({ - type: z.enum(["http", "ping", "pagespeed", "hardware", "docker", "port", "game", "grpc", "websocket"]).optional(), + type: z.enum(["http", "ping", "pagespeed", "hardware", "docker", "port", "game", "grpc", "websocket", "dns"]).optional(), sortOrder: z.enum(["asc", "desc"]), limit: z.coerce.number().optional(), dateRange: z.enum(["recent", "hour", "day", "week", "month", "all"]), diff --git a/server/src/validation/monitorValidation.ts b/server/src/validation/monitorValidation.ts index 5065a5aa1..beb990f71 100644 --- a/server/src/validation/monitorValidation.ts +++ b/server/src/validation/monitorValidation.ts @@ -1,5 +1,5 @@ import { z } from "zod"; -import { booleanCoercion } from "./shared.js"; +import { booleanCoercion, dnsServerValidation } from "./shared.js"; import { GeoContinents } from "@/types/geoCheck.js"; import { DnsRecordTypes, MonitorMatchMethods, MonitorStatuses, MonitorTypes } from "@/types/monitor.js"; @@ -68,7 +68,7 @@ export const createMonitorBodyValidation = z.object({ geoCheckEnabled: z.boolean().optional(), geoCheckLocations: z.array(z.enum(GeoContinents)).optional(), geoCheckInterval: z.number().min(300000).optional(), - dnsServer: z.string().optional(), + dnsServer: dnsServerValidation.optional(), dnsRecordType: z.enum(DnsRecordTypes).optional(), }); @@ -99,7 +99,7 @@ export const editMonitorBodyValidation = z.object({ geoCheckEnabled: z.boolean().optional(), geoCheckLocations: z.array(z.enum(GeoContinents)).optional(), geoCheckInterval: z.number().min(300000).optional(), - dnsServer: z.string().optional(), + dnsServer: dnsServerValidation.optional(), dnsRecordType: z.enum(DnsRecordTypes).optional(), }); @@ -162,7 +162,7 @@ const importedMonitorSchema = z.object({ geoCheckEnabled: z.boolean().default(false), geoCheckLocations: z.array(z.enum(GeoContinents)).default([]), geoCheckInterval: z.number().min(300000).default(300000), - dnsServer: z.string().optional(), + dnsServer: dnsServerValidation.optional(), dnsRecordType: z.enum(DnsRecordTypes).optional(), createdAt: z.string().optional(), updatedAt: z.string().optional(), diff --git a/server/src/validation/shared.ts b/server/src/validation/shared.ts index 28fd13c82..6b607cce3 100644 --- a/server/src/validation/shared.ts +++ b/server/src/validation/shared.ts @@ -15,6 +15,11 @@ export const nameValidation = z export const lowercaseEmailValidation = z.email().transform((val) => val.toLowerCase()); +export const dnsServerValidation = z + .string() + .min(1, "DNS server is required") + .refine((v) => z.ipv4().safeParse(v).success || z.ipv6().safeParse(v).success, "Enter a valid IPv4 or IPv6 address (e.g. 8.8.8.8)"); + export const booleanCoercion = z.preprocess((val) => { if (val === "true" || val === true) return true; if (val === "false" || val === false) return false;