UI improvements for DNS monitor edit form

This commit is contained in:
ekrekeler 2025-02-25 00:58:45 -06:00
parent 6ab986b935
commit aaf438a248
No known key found for this signature in database
GPG key ID: 4C66C864B6B00854
4 changed files with 53 additions and 13 deletions

View file

@ -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}`,
});

View file

@ -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?",

View file

@ -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 @@
</div>
</div>
<div class="my-3">
<div v-if="dohSelected" class="my-3">
<label for="doh_query_path" class="form-label">{{ $t("Query Path") }}</label>
<input id="doh_query_path" v-model="monitor.doh_query_path" type="text" class="form-control" :pattern="urlQueryRegex">
<div class="d-flex">
<label for="doh_query_path" class="px-2 fs-5">/</label>
<input id="doh_query_path" v-model="monitor.doh_query_path" type="text" class="form-control" :pattern="urlQueryRegex" placeholder="dns-query?dns={query}">
</div>
<div class="form-text">
{{ $t("dohQueryPathDescription") }}
{{ $t("dohQueryPathDescription") }}{{ ' "{query}".' }}
</div>
</div>
<div class="my-3">
<label for="dns_transport" class="form-label">{{ $t("Transport Method") }}</label>
<!-- :allow-empty="false" is not working, set a default value instead https://github.com/shentao/vue-multiselect/issues/336 -->
<VueMultiselect
id="dns_transport"
v-model="monitor.dns_transport"
@ -1091,7 +1097,7 @@ import RemoteBrowserDialog from "../components/RemoteBrowserDialog.vue";
import ProxyDialog from "../components/ProxyDialog.vue";
import TagsManager from "../components/TagsManager.vue";
import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, sleep } from "../util.ts";
import { hostNameRegexPattern, urlPathRegexPattern } from "../util-frontend";
import { hostNameRegexPattern, dnsNameRegexPattern, urlPathRegexPattern } from "../util-frontend";
import HiddenInput from "../components/HiddenInput.vue";
import EditMonitorConditions from "../components/EditMonitorConditions.vue";
@ -1119,7 +1125,6 @@ const monitorDefaults = {
dns_resolve_type: "A",
dns_resolve_server: "1.1.1.1",
dns_transport: "UDP",
doh_query_path: "dns-query?dns={query}",
docker_container: "",
docker_host: null,
proxyId: null,
@ -1174,8 +1179,11 @@ export default {
dnsresolvetypeOptions: [],
dnsTransportOptions: [],
kafkaSaslMechanismOptions: [],
ipRegexPattern: hostNameRegexPattern().split("|")[0],
ipOrHostnameRegexPattern: hostNameRegexPattern(),
mqttIpOrHostnameRegexPattern: hostNameRegexPattern(true),
ipOrDnsNameRegexPattern: dnsNameRegexPattern(),
queryRegexPattern: urlPathRegexPattern(),
gameList: null,
connectionStringTemplates: {
"sqlserver": "Server=<hostname>,<port>;Database=<your database>;User Id=<your user id>;Password=<your password>;Encrypt=<true/false>;TrustServerCertificate=<Yes/No>;Connection Timeout=<int>",
@ -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",

View file

@ -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;
}
/**