From aaf438a24882e98c926c6cc4bf7fcf79d1e9f4a6 Mon Sep 17 00:00:00 2001 From: ekrekeler Date: Tue, 25 Feb 2025 00:58:45 -0600 Subject: [PATCH] UI improvements for DNS monitor edit form --- server/util-server.js | 1 + src/lang/en.json | 2 +- src/pages/EditMonitor.vue | 37 +++++++++++++++++++++++++++++-------- src/util-frontend.js | 26 ++++++++++++++++++++++---- 4 files changed, 53 insertions(+), 13 deletions(-) diff --git a/server/util-server.js b/server/util-server.js index a602f3ad9..5abfd5e9e 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -332,6 +332,7 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype, t }); break; case "DOH": + dohQuery = dohQuery || "dns-query?dns={query}"; resolver = DOHClient({ dns: `https://${resolverServer}:${resolverPort}/${dohQuery}`, }); diff --git a/src/lang/en.json b/src/lang/en.json index 9a3a5465d..eb39081df 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -575,7 +575,7 @@ "resolverserverDescription": "Cloudflare is the default server. You can change the resolver server anytime.", "rrtypeDescription": "Select the RR type you want to monitor", "dnsTransportDescription": "Select the transport method for querying the DNS server.", - "dohQueryPathDescription": "Set the query path to use for DNS wireformat. Must contain \"{query}\".", + "dohQueryPathDescription": "Set the query path to use for DNS wireformat. Must contain", "pauseMonitorMsg": "Are you sure want to pause?", "enableDefaultNotificationDescription": "This notification will be enabled by default for new monitors. You can still disable the notification separately for each monitor.", "clearEventsMsg": "Are you sure want to delete all events for this monitor?", diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 1c87d12bd..352045921 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -289,7 +289,11 @@ v-model="monitor.hostname" type="text" class="form-control" - :pattern="`${monitor.type === 'mqtt' ? mqttIpOrHostnameRegexPattern : ipOrHostnameRegexPattern}`" + :pattern="`${ + monitor.type === 'mqtt' ? mqttIpOrHostnameRegexPattern : + monitor.type === 'dns' ? ipOrDnsNameRegexPattern : + ipOrHostnameRegexPattern + }`" required data-testid="hostname-input" > @@ -373,17 +377,19 @@ -
+
- +
+ + +
- {{ $t("dohQueryPathDescription") }} + {{ $t("dohQueryPathDescription") }}{{ ' "{query}".' }}
- ,;Database=;User Id=;Password=;Encrypt=;TrustServerCertificate=;Connection Timeout=", @@ -1208,6 +1216,15 @@ export default { return null; }, + dnsNameRegex() { + + // Permit IP address, hostname, TLD, or root + if (! isDev) { + return this.ipOrDnsNameRegexPattern; + } + return null; + }, + urlQueryRegex() { // Permit only URL paths with a query parameter ( {query} ) @@ -1440,6 +1457,10 @@ message HealthCheckResponse { conditionVariables() { return this.$root.monitorTypeList[this.monitor.type]?.conditionVariables || []; }, + + dohSelected() { + return this.monitor.dns_transport === "DoH"; + } }, watch: { "$root.proxyList"() { @@ -1595,7 +1616,7 @@ message HealthCheckResponse { "TCP", "DoH", "DoT", - ] + ]; let kafkaSaslMechanismOptions = [ "None", diff --git a/src/util-frontend.js b/src/util-frontend.js index 301d0901a..6c5a0524f 100644 --- a/src/util-frontend.js +++ b/src/util-frontend.js @@ -126,16 +126,34 @@ export function hostNameRegexPattern(mqtt = false) { } /** - * Regex patterns for validating URL paths + * Regex pattern for DNS queries * @returns {RegExp} The requested regex */ -export function urlPathRegexPattern() { +export function dnsNameRegexPattern() { + // This borrows ipRegexPattern from hostNameRegexPattern above + const ipRegexPattern = hostNameRegexPattern().split("|")[0]; + // Similar to hostNameRegexPattern, except the hostname pattern + // can also match root (.) and top-level domains (.com, .org) + const dnsNamePattern = "^(\\.|(\\.?[a-zA-Z0-9_]+)+)$"; + + return `${ipRegexPattern}|${dnsNamePattern}`; +} + +/** + * Regex patterns for validating URL paths + * @param {boolean} qstr whether or not the url follows query string format + * @returns {RegExp} The requested regex + */ +export function urlPathRegexPattern(qstr = false) { // Ensures a URL path follows query string format const queryStringRegexPattern = "^/?(([a-zA-Z0-9\\-_%])+/)*[a-zA-Z0-9\\-_%]*\\?([a-zA-Z0-9\\-_%]+=[a-zA-Z0-9\\-_%]*&?)+$"; // Only checks for valid URL path containing "{query}" - const queryRegexPattern = "^[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]*{query}[a-zA-Z0-9\\-._~:/?#\\[\\]@!$&'()*+,;=]*$"; + const queryRegexPattern = "^[a-zA-Z0-9\\-._~:\\/?#\\[\\]@!$&'\\(\\)*+,;=]*\\{query\\}[a-zA-Z0-9\\-._~:\\/?#\\[\\]@!$&'\\(\\)*+,;=]*$"; - return `${queryStringRegexPattern}|${queryRegexPattern}`; + if (qstr) { + return queryStringRegexPattern; + } + return queryRegexPattern; } /**