From c196c34840f39bb97ba094dc8f642d6f77ce84e1 Mon Sep 17 00:00:00 2001 From: David Twigger Date: Thu, 5 Jan 2023 08:57:48 +0100 Subject: [PATCH 01/35] Add mqtt, mqtts, ws and wss protocols to the mqtt monitor --- server/util-server.js | 9 +++++---- src/pages/EditMonitor.vue | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/server/util-server.js b/server/util-server.js index ffd171b40..fb96abe72 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -135,7 +135,7 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { const { port, username, password, interval = 20 } = options; // Adds MQTT protocol to the hostname if not already present - if (!/^(?:http|mqtt)s?:\/\//.test(hostname)) { + if (!/^(?:http|mqtt|ws)s?:\/\//.test(hostname)) { hostname = "mqtt://" + hostname; } @@ -145,10 +145,11 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { reject(new Error("Timeout")); }, interval * 1000 * 0.8); - log.debug("mqtt", "MQTT connecting"); + const mqttUrl = `${hostname}:${port}` + + log.debug("mqtt", `MQTT connecting to ${mqttUrl}`); - let client = mqtt.connect(hostname, { - port, + let client = mqtt.connect(mqttUrl, { username, password }); diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index c9d5ad2f1..315d1e6c2 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -604,7 +604,8 @@ export default { // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ ipRegexPattern: "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))", // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address - hostnameRegexPattern: "^(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$" + // Modified to accept http, https, mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) + hostnameRegexPattern: "^((http|mqtt|ws)s?:\/\/)?([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$" }; }, From fc1914bccd802783a24a46ffb99b5004baf967f2 Mon Sep 17 00:00:00 2001 From: David Twigger Date: Thu, 5 Jan 2023 11:42:19 +0100 Subject: [PATCH 02/35] Fix lint --- server/util-server.js | 4 ++-- src/pages/EditMonitor.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/util-server.js b/server/util-server.js index fb96abe72..3a48b5ed1 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -145,8 +145,8 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { reject(new Error("Timeout")); }, interval * 1000 * 0.8); - const mqttUrl = `${hostname}:${port}` - + const mqttUrl = `${hostname}:${port}`; + log.debug("mqtt", `MQTT connecting to ${mqttUrl}`); let client = mqtt.connect(mqttUrl, { diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 315d1e6c2..ab477a7e3 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -605,7 +605,7 @@ export default { ipRegexPattern: "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))", // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address // Modified to accept http, https, mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) - hostnameRegexPattern: "^((http|mqtt|ws)s?:\/\/)?([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$" + hostnameRegexPattern: "^((http|mqtt|ws)s?:\\/\\/)?([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$" }; }, From 5362aab0e5648a942314fcf468c3e9f127e958fd Mon Sep 17 00:00:00 2001 From: David Twigger Date: Thu, 5 Jan 2023 14:06:13 +0100 Subject: [PATCH 03/35] specify scheme for mqtt monitor type only --- src/pages/EditMonitor.vue | 19 ++++++++++++------- test/cypress/videos/setup.cy.js.mp4 | Bin 0 -> 64989 bytes 2 files changed, 12 insertions(+), 7 deletions(-) create mode 100644 test/cypress/videos/setup.cy.js.mp4 diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index ab477a7e3..302ec6fd0 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -105,7 +105,7 @@
- +
@@ -590,6 +590,15 @@ export default { }, data() { + const mqttSchemePartialRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; + // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ + const ipRegexPattern = "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))"; + const hostnameRegexPattern = "^([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$"; + + // Modified to accept mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) + const mqttIpRegexPattern = `((^\\s*${mqttSchemePartialRegexPattern}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; + const mqttHostNameRegexPattern = `^${mqttSchemePartialRegexPattern}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; + return { minInterval: MIN_INTERVAL_SECOND, maxInterval: MAX_INTERVAL_SECOND, @@ -600,12 +609,8 @@ export default { }, acceptedStatusCodeOptions: [], dnsresolvetypeOptions: [], - - // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ - ipRegexPattern: "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))", - // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address - // Modified to accept http, https, mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) - hostnameRegexPattern: "^((http|mqtt|ws)s?:\\/\\/)?([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$" + ipOrHostnameRegexPattern: `${ipRegexPattern}|${hostnameRegexPattern}`, + mqttIpOrHostnameRegexPattern: `${mqttIpRegexPattern}|${mqttHostNameRegexPattern}` }; }, diff --git a/test/cypress/videos/setup.cy.js.mp4 b/test/cypress/videos/setup.cy.js.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..59fb3971a2a2764c11552877131bc4019218211e GIT binary patch literal 64989 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�XVoO(MNxMc+Yp*cXF{n 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 literal 0 HcmV?d00001 From 8a372201f1dc323667c52db7eed86fa7553b2e51 Mon Sep 17 00:00:00 2001 From: David Twigger Date: Thu, 5 Jan 2023 14:23:05 +0100 Subject: [PATCH 04/35] clean up --- src/pages/EditMonitor.vue | 2 +- test/cypress/videos/setup.cy.js.mp4 | Bin 64989 -> 0 bytes 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 test/cypress/videos/setup.cy.js.mp4 diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 302ec6fd0..13e0be544 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -590,12 +590,12 @@ export default { }, data() { - const mqttSchemePartialRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ const ipRegexPattern = "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))"; const hostnameRegexPattern = "^([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$"; // Modified to accept mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) + const mqttSchemePartialRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; const mqttIpRegexPattern = `((^\\s*${mqttSchemePartialRegexPattern}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; const mqttHostNameRegexPattern = `^${mqttSchemePartialRegexPattern}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; diff --git a/test/cypress/videos/setup.cy.js.mp4 b/test/cypress/videos/setup.cy.js.mp4 deleted file mode 100644 index 59fb3971a2a2764c11552877131bc4019218211e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 64989 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�XVoO(MNxMc+Yp*cXF{n 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 From abf5e435fe4e18b86521a58a9f763d221501cf07 Mon Sep 17 00:00:00 2001 From: David Twigger Date: Thu, 5 Jan 2023 14:48:12 +0100 Subject: [PATCH 05/35] move to utility function --- src/pages/EditMonitor.vue | 15 +++------------ src/util.ts | 11 +++++++++++ 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 13e0be544..124c96604 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -575,7 +575,7 @@ import NotificationDialog from "../components/NotificationDialog.vue"; import DockerHostDialog from "../components/DockerHostDialog.vue"; import ProxyDialog from "../components/ProxyDialog.vue"; import TagsManager from "../components/TagsManager.vue"; -import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } from "../util.ts"; +import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, hostNameRegexPattern } from "../util.ts"; const toast = useToast(); @@ -590,15 +590,6 @@ export default { }, data() { - // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ - const ipRegexPattern = "((^\\s*((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))"; - const hostnameRegexPattern = "^([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$"; - - // Modified to accept mqtt, mqtts, ws and wss protocols accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) - const mqttSchemePartialRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; - const mqttIpRegexPattern = `((^\\s*${mqttSchemePartialRegexPattern}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; - const mqttHostNameRegexPattern = `^${mqttSchemePartialRegexPattern}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; - return { minInterval: MIN_INTERVAL_SECOND, maxInterval: MAX_INTERVAL_SECOND, @@ -609,8 +600,8 @@ export default { }, acceptedStatusCodeOptions: [], dnsresolvetypeOptions: [], - ipOrHostnameRegexPattern: `${ipRegexPattern}|${hostnameRegexPattern}`, - mqttIpOrHostnameRegexPattern: `${mqttIpRegexPattern}|${mqttHostNameRegexPattern}` + ipOrHostnameRegexPattern: hostNameRegexPattern(), + mqttIpOrHostnameRegexPattern: hostNameRegexPattern(true) }; }, diff --git a/src/util.ts b/src/util.ts index 99038c8d3..4b8f1624d 100644 --- a/src/util.ts +++ b/src/util.ts @@ -427,3 +427,14 @@ export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) { export function localToUTC(input : string, format = SQL_DATETIME_FORMAT) { return dayjs(input).utc().format(format); } + +export function hostNameRegexPattern(mqtt = false) { + // mqtt, mqtts, ws and wss schemes accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) + const mqttSchemeRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; + // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ + const ipRegexPattern = `((^\\s*${mqtt ? mqttSchemeRegexPattern : ""}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; + // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address + const hostNameRegexPattern = `^${mqtt ? mqttSchemeRegexPattern : ""}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; + + return `${ipRegexPattern}|${hostNameRegexPattern}`; +} \ No newline at end of file From c7eb72e73b09ddf7f02f355086cbdbe29ceb66c3 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Thu, 5 Jan 2023 19:57:28 +0000 Subject: [PATCH 06/35] JSDoc for extra/ Signed-off-by: Matthew Nickson --- extra/beta/update-version.js | 13 +++++++++++++ extra/download-cloudflared.js | 4 ++++ extra/remove-2fa.js | 5 +++++ extra/reset-password.js | 5 +++++ extra/simple-dns-server.js | 5 +++++ extra/simple-mqtt-server.js | 1 + extra/update-version.js | 17 +++++++++-------- extra/update-wiki-version.js | 8 ++++++++ 8 files changed, 50 insertions(+), 8 deletions(-) diff --git a/extra/beta/update-version.js b/extra/beta/update-version.js index df2cb40a6..7abac5efe 100644 --- a/extra/beta/update-version.js +++ b/extra/beta/update-version.js @@ -32,6 +32,10 @@ if (! exists) { process.exit(1); } +/** + * Commit updated files + * @param {string} version Version to update to + */ function commit(version) { let msg = "Update to " + version; @@ -47,6 +51,10 @@ function commit(version) { console.log(res.stdout.toString().trim()); } +/** + * Create a tag with the specified version + * @param {string} version Tag to create + */ function tag(version) { let res = childProcess.spawnSync("git", [ "tag", version ]); console.log(res.stdout.toString().trim()); @@ -55,6 +63,11 @@ function tag(version) { console.log(res.stdout.toString().trim()); } +/** + * Check if a tag exists for the specified version + * @param {string} version Version to check + * @returns {boolean} Does the tag already exist + */ function tagExists(version) { if (! version) { throw new Error("invalid version"); diff --git a/extra/download-cloudflared.js b/extra/download-cloudflared.js index 41519b7ca..74b9bad2a 100644 --- a/extra/download-cloudflared.js +++ b/extra/download-cloudflared.js @@ -25,6 +25,10 @@ if (platform === "linux/amd64") { const file = fs.createWriteStream("cloudflared.deb"); get("https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-" + arch + ".deb"); +/** + * Download specified file + * @param {string} url URL to request + */ function get(url) { http.get(url, function (res) { if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) { diff --git a/extra/remove-2fa.js b/extra/remove-2fa.js index 0f3f63462..f88c43fca 100644 --- a/extra/remove-2fa.js +++ b/extra/remove-2fa.js @@ -43,6 +43,11 @@ const main = async () => { console.log("Finished."); }; +/** + * Ask question of user + * @param {string} question Question to ask + * @returns {Promise} Users response + */ function question(question) { return new Promise((resolve) => { rl.question(question, (answer) => { diff --git a/extra/reset-password.js b/extra/reset-password.js index 8036a4566..168983312 100644 --- a/extra/reset-password.js +++ b/extra/reset-password.js @@ -53,6 +53,11 @@ const main = async () => { console.log("Finished."); }; +/** + * Ask question of user + * @param {string} question Question to ask + * @returns {Promise} Users response + */ function question(question) { return new Promise((resolve) => { rl.question(question, (answer) => { diff --git a/extra/simple-dns-server.js b/extra/simple-dns-server.js index 376dbdd04..a6946dcb3 100644 --- a/extra/simple-dns-server.js +++ b/extra/simple-dns-server.js @@ -135,6 +135,11 @@ server.listen({ udp: 5300 }); +/** + * Get human readable request type from request code + * @param {number} code Request code to translate + * @returns {string} Human readable request type + */ function type(code) { for (let name in Packet.TYPE) { if (Packet.TYPE[name] === code) { diff --git a/extra/simple-mqtt-server.js b/extra/simple-mqtt-server.js index 238d27726..b970a380e 100644 --- a/extra/simple-mqtt-server.js +++ b/extra/simple-mqtt-server.js @@ -11,6 +11,7 @@ class SimpleMqttServer { this.port = port; } + /** Start the MQTT server */ start() { this.server.listen(this.port, () => { console.log("server started and listening on port ", this.port); diff --git a/extra/update-version.js b/extra/update-version.js index d5c2ee5ca..246e1c1c4 100644 --- a/extra/update-version.js +++ b/extra/update-version.js @@ -36,10 +36,8 @@ if (! exists) { } /** - * Updates the version number in package.json and commits it to git. - * @param {string} version - The new version number - * - * Generated by Trelent + * Commit updated files + * @param {string} version Version to update to */ function commit(version) { let msg = "Update to " + version; @@ -53,16 +51,19 @@ function commit(version) { } } +/** + * Create a tag with the specified version + * @param {string} version Tag to create + */ function tag(version) { let res = childProcess.spawnSync("git", [ "tag", version ]); console.log(res.stdout.toString().trim()); } /** - * Checks if a given version is already tagged in the git repository. - * @param {string} version - The version to check for. - * - * Generated by Trelent + * Check if a tag exists for the specified version + * @param {string} version Version to check + * @returns {boolean} Does the tag already exist */ function tagExists(version) { if (! version) { diff --git a/extra/update-wiki-version.js b/extra/update-wiki-version.js index 65b7e7b08..880bc5568 100644 --- a/extra/update-wiki-version.js +++ b/extra/update-wiki-version.js @@ -10,6 +10,10 @@ if (!newVersion) { updateWiki(newVersion); +/** + * Update the wiki with new version number + * @param {string} newVersion Version to update to + */ function updateWiki(newVersion) { const wikiDir = "./tmp/wiki"; const howToUpdateFilename = "./tmp/wiki/🆙-How-to-Update.md"; @@ -39,6 +43,10 @@ function updateWiki(newVersion) { safeDelete(wikiDir); } +/** + * Check if a directory exists before deleting + * @param {string} dir Directory to delete + */ function safeDelete(dir) { if (fs.existsSync(dir)) { fs.rm(dir, { From caff9ca736228e833fcab0ecfef8ebb551f9d0ef Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Thu, 5 Jan 2023 22:19:05 +0000 Subject: [PATCH 07/35] Added JSDoc for server/ Signed-off-by: Matthew Nickson --- server/auth.js | 6 ++++ server/cacheable-dns-http-agent.js | 4 +++ server/jobs.js | 1 + server/model/maintenance.js | 23 +++++++++++++++ server/model/maintenance_timeslot.js | 9 ++++++ server/model/monitor.js | 8 ++++++ server/notification-providers/serverchan.js | 6 ++++ server/prometheus.js | 1 + server/uptime-cache-list.js | 18 +++++++++--- server/uptime-kuma-server.js | 32 +++++++++++++++++++++ 10 files changed, 104 insertions(+), 4 deletions(-) diff --git a/server/auth.js b/server/auth.js index 3ce1a6041..fd19b0e44 100644 --- a/server/auth.js +++ b/server/auth.js @@ -63,6 +63,12 @@ function myAuthorizer(username, password, callback) { }); } +/** + * Use basic auth if auth is not disabled + * @param {express.Request} req Express request object + * @param {express.Response} res Express response object + * @param {express.NextFunction} next + */ exports.basicAuth = async function (req, res, next) { const middleware = basicAuth({ authorizer: myAuthorizer, diff --git a/server/cacheable-dns-http-agent.js b/server/cacheable-dns-http-agent.js index 301367918..cc067f72b 100644 --- a/server/cacheable-dns-http-agent.js +++ b/server/cacheable-dns-http-agent.js @@ -37,6 +37,10 @@ class CacheableDnsHttpAgent { this.enable = isEnable; } + /** + * Attach cacheable to HTTP agent + * @param {http.Agent} agent Agent to install + */ static install(agent) { this.cacheable.install(agent); } diff --git a/server/jobs.js b/server/jobs.js index f9c7f86e9..66a276064 100644 --- a/server/jobs.js +++ b/server/jobs.js @@ -32,6 +32,7 @@ const initBackgroundJobs = function (args) { return bree; }; +/** Stop all background jobs if running */ const stopBackgroundJobs = function () { if (bree) { bree.stop(); diff --git a/server/model/maintenance.js b/server/model/maintenance.js index d9be34273..45db63d13 100644 --- a/server/model/maintenance.js +++ b/server/model/maintenance.js @@ -112,6 +112,11 @@ class Maintenance extends BeanModel { return this.toPublicJSON(timezone); } + /** + * Get a list of weekdays that the maintenance is active for + * Monday=1, Tuesday=2 etc. + * @returns {number[]} Array of active weekdays + */ getDayOfWeekList() { log.debug("timeslot", "List: " + this.weekdays); return JSON.parse(this.weekdays).sort(function (a, b) { @@ -119,12 +124,20 @@ class Maintenance extends BeanModel { }); } + /** + * Get a list of days in month that maintenance is active for + * @returns {number[]} Array of active days in month + */ getDayOfMonthList() { return JSON.parse(this.days_of_month).sort(function (a, b) { return a - b; }); } + /** + * Get the start date and time for maintenance + * @returns {dayjs.Dayjs} Start date and time + */ getStartDateTime() { let startOfTheDay = dayjs.utc(this.start_date).format("HH:mm"); log.debug("timeslot", "startOfTheDay: " + startOfTheDay); @@ -137,6 +150,10 @@ class Maintenance extends BeanModel { return dayjs.utc(this.start_date).add(startTimeSecond, "second"); } + /** + * Get the duraction of maintenance in seconds + * @returns {number} Duration of maintenance + */ getDuration() { let duration = dayjs.utc(this.end_time, "HH:mm").diff(dayjs.utc(this.start_time, "HH:mm"), "second"); // Add 24hours if it is across day @@ -146,6 +163,12 @@ class Maintenance extends BeanModel { return duration; } + /** + * Convert data from socket to bean + * @param {Bean} bean Bean to fill in + * @param {Object} obj Data to fill bean with + * @returns {Bean} Filled bean + */ static jsonToBean(bean, obj) { if (obj.id) { bean.id = obj.id; diff --git a/server/model/maintenance_timeslot.js b/server/model/maintenance_timeslot.js index 2babe6bca..77643c2cf 100644 --- a/server/model/maintenance_timeslot.js +++ b/server/model/maintenance_timeslot.js @@ -6,6 +6,11 @@ const { UptimeKumaServer } = require("../uptime-kuma-server"); class MaintenanceTimeslot extends BeanModel { + /** + * Return an object that ready to parse to JSON for public + * Only show necessary data to public + * @returns {Object} + */ async toPublicJSON() { const serverTimezoneOffset = UptimeKumaServer.getInstance().getTimezoneOffset(); @@ -21,6 +26,10 @@ class MaintenanceTimeslot extends BeanModel { return obj; } + /** + * Return an object that ready to parse to JSON + * @returns {Object} + */ async toJSON() { return await this.toPublicJSON(); } diff --git a/server/model/monitor.js b/server/model/monitor.js index 9f8c8300a..e6332b8f4 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -748,6 +748,13 @@ class Monitor extends BeanModel { } } + /** + * Make a request using axios + * @param {Object} options Options for Axios + * @param {boolean} finalCall Should this be the final call i.e + * don't retry on faliure + * @returns {Object} Axios response + */ async makeAxiosRequest(options, finalCall = false) { try { let res; @@ -1229,6 +1236,7 @@ class Monitor extends BeanModel { return maintenance.count !== 0; } + /** Make sure monitor interval is between bounds */ validate() { if (this.interval > MAX_INTERVAL_SECOND) { throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`); diff --git a/server/notification-providers/serverchan.js b/server/notification-providers/serverchan.js index fbf99f80d..d631c8e61 100644 --- a/server/notification-providers/serverchan.js +++ b/server/notification-providers/serverchan.js @@ -21,6 +21,12 @@ class ServerChan extends NotificationProvider { } } + /** + * Get the formatted title for message + * @param {?Object} monitorJSON Monitor details (For Up/Down only) + * @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @returns {string} Formatted title + */ checkStatus(heartbeatJSON, monitorJSON) { let title = "UptimeKuma Message"; if (heartbeatJSON != null && heartbeatJSON["status"] === UP) { diff --git a/server/prometheus.js b/server/prometheus.js index 1473ab7a9..aeba95f80 100644 --- a/server/prometheus.js +++ b/server/prometheus.js @@ -99,6 +99,7 @@ class Prometheus { } } + /** Remove monitor from prometheus */ remove() { try { monitorCertDaysRemaining.remove(this.monitorLabelValues); diff --git a/server/uptime-cache-list.js b/server/uptime-cache-list.js index 1347968fa..d88a9cbf8 100644 --- a/server/uptime-cache-list.js +++ b/server/uptime-cache-list.js @@ -6,10 +6,10 @@ class UptimeCacheList { static list = {}; /** - * - * @param monitorID - * @param duration - * @return number + * Get the uptime for a specific period + * @param {number} monitorID + * @param {number} duration + * @return {number} */ static getUptime(monitorID, duration) { if (UptimeCacheList.list[monitorID] && UptimeCacheList.list[monitorID][duration]) { @@ -20,6 +20,12 @@ class UptimeCacheList { } } + /** + * Add uptime for specified monitor + * @param {number} monitorID + * @param {number} duration + * @param {number} uptime Uptime to add + */ static addUptime(monitorID, duration, uptime) { log.debug("UptimeCacheList", "addUptime: " + monitorID + " " + duration); if (!UptimeCacheList.list[monitorID]) { @@ -28,6 +34,10 @@ class UptimeCacheList { UptimeCacheList.list[monitorID][duration] = uptime; } + /** + * Clear cache for specified monitor + * @param {number} monitorID + */ static clearCache(monitorID) { log.debug("UptimeCacheList", "clearCache: " + monitorID); delete UptimeCacheList.list[monitorID]; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 062375626..147121764 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -86,6 +86,7 @@ class UptimeKumaServer { this.io = new Server(this.httpServer); } + /** Initialise app after the dabase has been set up */ async initAfterDatabaseReady() { await CacheableDnsHttpAgent.update(); @@ -98,6 +99,11 @@ class UptimeKumaServer { this.generateMaintenanceTimeslotsInterval = setInterval(this.generateMaintenanceTimeslots, 60 * 1000); } + /** + * Send list of monitors to client + * @param {Socket} socket + * @returns {Object} List of monitors + */ async sendMonitorList(socket) { let list = await this.getMonitorJSONList(socket.userID); this.io.to(socket.userID).emit("monitorList", list); @@ -134,6 +140,11 @@ class UptimeKumaServer { return await this.sendMaintenanceListByUserID(socket.userID); } + /** + * Send list of maintenances to user + * @param {number} userID + * @returns {Object} + */ async sendMaintenanceListByUserID(userID) { let list = await this.getMaintenanceJSONList(userID); this.io.to(userID).emit("maintenanceList", list); @@ -185,6 +196,11 @@ class UptimeKumaServer { errorLogStream.end(); } + /** + * Get the IP of the client connected to the socket + * @param {Socket} socket + * @returns {string} + */ async getClientIP(socket) { let clientIP = socket.client.conn.remoteAddress; @@ -203,6 +219,12 @@ class UptimeKumaServer { } } + /** + * Attempt to get the current server timezone + * If this fails, fall back to environment variables and then make a + * guess. + * @returns {string} + */ async getTimezone() { let timezone = await Settings.get("serverTimezone"); if (timezone) { @@ -214,16 +236,25 @@ class UptimeKumaServer { } } + /** + * Get the current offset + * @returns {string} + */ getTimezoneOffset() { return dayjs().format("Z"); } + /** + * Set the current server timezone and environment variables + * @param {string} timezone + */ async setTimezone(timezone) { await Settings.set("serverTimezone", timezone, "general"); process.env.TZ = timezone; dayjs.tz.setDefault(timezone); } + /** Load the timeslots for maintenance */ async generateMaintenanceTimeslots() { let list = await R.find("maintenance_timeslot", " generated_next = 0 AND start_date <= DATETIME('now') "); @@ -237,6 +268,7 @@ class UptimeKumaServer { } + /** Stop the server */ async stop() { clearTimeout(this.generateMaintenanceTimeslotsInterval); } From dc8289df12e8c30861a38a15e3a39d277b5c9178 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Thu, 5 Jan 2023 22:55:51 +0000 Subject: [PATCH 08/35] Added JSDoc for src/ Signed-off-by: Matthew Nickson --- src/components/DockerHostDialog.vue | 8 +++++ src/components/notifications/Telegram.vue | 7 +++++ src/components/settings/Security.vue | 1 + src/mixins/datetime.js | 10 +++++++ src/mixins/socket.js | 36 +++++++++++++++++++++++ src/pages/EditMaintenance.vue | 12 ++++++++ src/pages/MaintenanceDetails.vue | 3 ++ src/pages/ManageMaintenance.vue | 10 +++++++ src/util.js | 16 ++++++++++ src/util.ts | 17 ++++++++++- 10 files changed, 119 insertions(+), 1 deletion(-) diff --git a/src/components/DockerHostDialog.vue b/src/components/DockerHostDialog.vue index 50ffa49c1..fc9aea498 100644 --- a/src/components/DockerHostDialog.vue +++ b/src/components/DockerHostDialog.vue @@ -91,11 +91,16 @@ export default { }, methods: { + /** Confirm deletion of docker host */ deleteConfirm() { this.modal.hide(); this.$refs.confirmDelete.show(); }, + /** + * Show specified docker host + * @param {number} dockerHostID + */ show(dockerHostID) { if (dockerHostID) { let found = false; @@ -126,6 +131,7 @@ export default { this.modal.show(); }, + /** Add docker host */ submit() { this.processing = true; this.$root.getSocket().emit("addDockerHost", this.dockerHost, this.id, (res) => { @@ -144,6 +150,7 @@ export default { }); }, + /** Test the docker host */ test() { this.processing = true; this.$root.getSocket().emit("testDockerHost", this.dockerHost, (res) => { @@ -152,6 +159,7 @@ export default { }); }, + /** Delete this docker host */ deleteDockerHost() { this.processing = true; this.$root.getSocket().emit("deleteDockerHost", this.id, (res) => { diff --git a/src/components/notifications/Telegram.vue b/src/components/notifications/Telegram.vue index 9daf31ac6..723bd1be6 100644 --- a/src/components/notifications/Telegram.vue +++ b/src/components/notifications/Telegram.vue @@ -42,6 +42,11 @@ export default { HiddenInput, }, methods: { + /** + * Get the URL for telegram updates + * @param {string} [mode=masked] Should the token be masked? + * @returns {string} formatted URL + */ telegramGetUpdatesURL(mode = "masked") { let token = `<${this.$t("YOUR BOT TOKEN HERE")}>`; @@ -55,6 +60,8 @@ export default { return `https://api.telegram.org/bot${token}/getUpdates`; }, + + /** Get the telegram chat ID */ async autoGetTelegramChatID() { try { let res = await axios.get(this.telegramGetUpdatesURL("withToken")); diff --git a/src/components/settings/Security.vue b/src/components/settings/Security.vue index 330fe9ca5..7d13ea90e 100644 --- a/src/components/settings/Security.vue +++ b/src/components/settings/Security.vue @@ -191,6 +191,7 @@ export default { location.reload(); }, + /** Show confirmation dialog for disable auth */ confirmDisableAuth() { this.$refs.confirmDisableAuth.show(); }, diff --git a/src/mixins/datetime.js b/src/mixins/datetime.js index 4fa2fa831..5a282ad03 100644 --- a/src/mixins/datetime.js +++ b/src/mixins/datetime.js @@ -12,6 +12,11 @@ export default { }, methods: { + /** + * Convert value to UTC + * @param {string | number | Date | dayjs.Dayjs} value + * @returns {dayjs.Dayjs} + */ toUTC(value) { return dayjs.tz(value, this.timezone).utc().format(); }, @@ -34,6 +39,11 @@ export default { return this.datetimeFormat(value, "YYYY-MM-DD HH:mm:ss"); }, + /** + * Get time for maintenance + * @param {string | number | Date | dayjs.Dayjs} value + * @returns {string} + */ datetimeMaintenance(value) { const inputDate = new Date(value); const now = new Date(Date.now()); diff --git a/src/mixins/socket.js b/src/mixins/socket.js index 378af06a5..0121eb153 100644 --- a/src/mixins/socket.js +++ b/src/mixins/socket.js @@ -454,6 +454,10 @@ export default { socket.emit("getMonitorList", callback); }, + /** + * Get list of maintenances + * @param {socketCB} callback + */ getMaintenanceList(callback) { if (! callback) { callback = () => { }; @@ -470,22 +474,49 @@ export default { socket.emit("add", monitor, callback); }, + /** + * Adds a maintenace + * @param {Object} maintenance + * @param {socketCB} callback + */ addMaintenance(maintenance, callback) { socket.emit("addMaintenance", maintenance, callback); }, + /** + * Add monitors to maintenance + * @param {number} maintenanceID + * @param {number[]} monitors + * @param {socketCB} callback + */ addMonitorMaintenance(maintenanceID, monitors, callback) { socket.emit("addMonitorMaintenance", maintenanceID, monitors, callback); }, + /** + * Add status page to maintenance + * @param {number} maintenanceID + * @param {number} statusPages + * @param {socketCB} callback + */ addMaintenanceStatusPage(maintenanceID, statusPages, callback) { socket.emit("addMaintenanceStatusPage", maintenanceID, statusPages, callback); }, + /** + * Get monitors affected by maintenance + * @param {number} maintenanceID + * @param {socketCB} callback + */ getMonitorMaintenance(maintenanceID, callback) { socket.emit("getMonitorMaintenance", maintenanceID, callback); }, + /** + * Get status pages where maintenance is shown + * @param {number} maintenanceID + * @param {socketCB} callback + */ getMaintenanceStatusPage(maintenanceID, callback) { socket.emit("getMaintenanceStatusPage", maintenanceID, callback); }, @@ -499,6 +530,11 @@ export default { socket.emit("deleteMonitor", monitorID, callback); }, + /** + * Delete specified maintenance + * @param {number} maintenanceID + * @param {socketCB} callback + */ deleteMaintenance(maintenanceID, callback) { socket.emit("deleteMaintenance", maintenanceID, callback); }, diff --git a/src/pages/EditMaintenance.vue b/src/pages/EditMaintenance.vue index d668d1ad1..f0d87fe5a 100644 --- a/src/pages/EditMaintenance.vue +++ b/src/pages/EditMaintenance.vue @@ -356,6 +356,7 @@ export default { }); }, methods: { + /** Initialise page */ init() { this.affectedMonitors = []; this.selectedStatusPages = []; @@ -414,6 +415,7 @@ export default { } }, + /** Create new maintenance */ async submit() { this.processing = true; @@ -458,6 +460,11 @@ export default { } }, + /** + * Add monitor to maintenance + * @param {number} maintenanceID + * @param {socketCB} callback + */ async addMonitorMaintenance(maintenanceID, callback) { await this.$root.addMonitorMaintenance(maintenanceID, this.affectedMonitors, async (res) => { if (!res.ok) { @@ -470,6 +477,11 @@ export default { }); }, + /** + * Add status page to maintenance + * @param {number} maintenanceID + * @param {socketCB} callback + */ async addMaintenanceStatusPage(maintenanceID, callback) { await this.$root.addMaintenanceStatusPage(maintenanceID, (this.showOnAllPages) ? this.selectedStatusPagesOptions : this.selectedStatusPages, async (res) => { if (!res.ok) { diff --git a/src/pages/MaintenanceDetails.vue b/src/pages/MaintenanceDetails.vue index 04c216915..0cf9283d3 100644 --- a/src/pages/MaintenanceDetails.vue +++ b/src/pages/MaintenanceDetails.vue @@ -65,6 +65,7 @@ export default { this.init(); }, methods: { + /** Initialise page */ init() { this.$root.getSocket().emit("getMonitorMaintenance", this.$route.params.id, (res) => { if (res.ok) { @@ -83,10 +84,12 @@ export default { }); }, + /** Confirm deletion */ deleteDialog() { this.$refs.confirmDelete.show(); }, + /** Delete maintenance after showing confirmation */ deleteMaintenance() { this.$root.deleteMaintenance(this.maintenance.id, (res) => { if (res.ok) { diff --git a/src/pages/ManageMaintenance.vue b/src/pages/ManageMaintenance.vue index dd36c9505..aaffbbf93 100644 --- a/src/pages/ManageMaintenance.vue +++ b/src/pages/ManageMaintenance.vue @@ -133,15 +133,25 @@ export default { } }, + /** + * Get maintenance URL + * @param {number} id + * @returns {string} Relative URL + */ maintenanceURL(id) { return getMaintenanceRelativeURL(id); }, + /** + * Show delete confirmation + * @param {number} maintenanceID + */ deleteDialog(maintenanceID) { this.selectedMaintenanceID = maintenanceID; this.$refs.confirmDelete.show(); }, + /** Delete maintenance after showing confirmation dialog */ deleteMaintenance() { this.$root.deleteMaintenance(this.selectedMaintenanceID, (res) => { if (res.ok) { diff --git a/src/util.js b/src/util.js index 09e6d0ee7..6b8f8f374 100644 --- a/src/util.js +++ b/src/util.js @@ -315,6 +315,11 @@ function getMonitorRelativeURL(id) { return "/dashboard/" + id; } exports.getMonitorRelativeURL = getMonitorRelativeURL; +/** + * Get relative path for maintenance + * @param id ID of maintenance + * @returns Formatted relative path + */ function getMaintenanceRelativeURL(id) { return "/maintenance/" + id; } @@ -361,6 +366,11 @@ function parseTimeFromTimeObject(obj) { return result; } exports.parseTimeFromTimeObject = parseTimeFromTimeObject; +/** + * Convert ISO date to UTC + * @param input Date + * @returns ISO Date time + */ function isoToUTCDateTime(input) { return dayjs(input).utc().format(exports.SQL_DATETIME_FORMAT); } @@ -379,6 +389,12 @@ function utcToLocal(input, format = exports.SQL_DATETIME_FORMAT) { return dayjs.utc(input).local().format(format); } exports.utcToLocal = utcToLocal; +/** + * Convert local datetime to UTC + * @param input Local date + * @param format Format to return + * @returns Date in requested format + */ function localToUTC(input, format = exports.SQL_DATETIME_FORMAT) { return dayjs(input).utc().format(format); } diff --git a/src/util.ts b/src/util.ts index 99038c8d3..e8a2706e3 100644 --- a/src/util.ts +++ b/src/util.ts @@ -352,6 +352,11 @@ export function getMonitorRelativeURL(id: string) { return "/dashboard/" + id; } +/** + * Get relative path for maintenance + * @param id ID of maintenance + * @returns Formatted relative path + */ export function getMaintenanceRelativeURL(id: string) { return "/maintenance/" + id; } @@ -405,7 +410,11 @@ export function parseTimeFromTimeObject(obj : any) { return result; } - +/** + * Convert ISO date to UTC + * @param input Date + * @returns ISO Date time + */ export function isoToUTCDateTime(input : string) { return dayjs(input).utc().format(SQL_DATETIME_FORMAT); } @@ -424,6 +433,12 @@ export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) { return dayjs.utc(input).local().format(format); } +/** + * Convert local datetime to UTC + * @param input Local date + * @param format Format to return + * @returns Date in requested format + */ export function localToUTC(input : string, format = SQL_DATETIME_FORMAT) { return dayjs(input).utc().format(format); } From e490ec6d29a88a10979656a877fb4a7e3eeda2ee Mon Sep 17 00:00:00 2001 From: David Twigger Date: Fri, 6 Jan 2023 11:00:20 +0100 Subject: [PATCH 09/35] move hostname regex pattern function to frontend-utils --- src/pages/EditMonitor.vue | 3 ++- src/util-frontend.js | 16 ++++++++++++++++ src/util.ts | 11 ----------- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 124c96604..2ab9acc7e 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -575,7 +575,8 @@ import NotificationDialog from "../components/NotificationDialog.vue"; import DockerHostDialog from "../components/DockerHostDialog.vue"; import ProxyDialog from "../components/ProxyDialog.vue"; import TagsManager from "../components/TagsManager.vue"; -import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, hostNameRegexPattern } from "../util.ts"; +import { genSecret, isDev, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND } from "../util.ts"; +import { hostNameRegexPattern } from "../util-frontend"; const toast = useToast(); diff --git a/src/util-frontend.js b/src/util-frontend.js index 3323f3279..23b4ec95f 100644 --- a/src/util-frontend.js +++ b/src/util-frontend.js @@ -78,3 +78,19 @@ export function getResBaseURL() { return ""; } } + +/** + * + * @param {} mqtt wheather or not the regex should take into account the fact that it is an mqtt uri + * @returns RegExp The requested regex + */ +export function hostNameRegexPattern(mqtt = false) { + // mqtt, mqtts, ws and wss schemes accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) + const mqttSchemeRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; + // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ + const ipRegexPattern = `((^\\s*${mqtt ? mqttSchemeRegexPattern : ""}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; + // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address + const hostNameRegexPattern = `^${mqtt ? mqttSchemeRegexPattern : ""}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; + + return `${ipRegexPattern}|${hostNameRegexPattern}`; +} diff --git a/src/util.ts b/src/util.ts index 4b8f1624d..99038c8d3 100644 --- a/src/util.ts +++ b/src/util.ts @@ -427,14 +427,3 @@ export function utcToLocal(input : string, format = SQL_DATETIME_FORMAT) { export function localToUTC(input : string, format = SQL_DATETIME_FORMAT) { return dayjs(input).utc().format(format); } - -export function hostNameRegexPattern(mqtt = false) { - // mqtt, mqtts, ws and wss schemes accepted by mqtt.js (https://github.com/mqttjs/MQTT.js/#connect) - const mqttSchemeRegexPattern = "((mqtt|ws)s?:\\/\\/)?"; - // Source: https://digitalfortress.tech/tips/top-15-commonly-used-regex/ - const ipRegexPattern = `((^\\s*${mqtt ? mqttSchemeRegexPattern : ""}((([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]))\\s*$)|(^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$))`; - // Source: https://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address - const hostNameRegexPattern = `^${mqtt ? mqttSchemeRegexPattern : ""}([a-zA-Z0-9])?(([a-zA-Z0-9_]|[a-zA-Z0-9_][a-zA-Z0-9\\-_]*[a-zA-Z0-9_])\\.)*([A-Za-z0-9_]|[A-Za-z0-9_][A-Za-z0-9\\-_]*[A-Za-z0-9_])$`; - - return `${ipRegexPattern}|${hostNameRegexPattern}`; -} \ No newline at end of file From 21c19218677e0d8941d480401853c2ff417d6f8a Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Fri, 6 Jan 2023 23:04:02 +0800 Subject: [PATCH 10/35] Update server/uptime-kuma-server.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 琚致远 / Zhiyuan Ju --- server/uptime-kuma-server.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 147121764..faffb98be 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -86,7 +86,7 @@ class UptimeKumaServer { this.io = new Server(this.httpServer); } - /** Initialise app after the dabase has been set up */ + /** Initialise app after the database has been set up */ async initAfterDatabaseReady() { await CacheableDnsHttpAgent.update(); From 675806829cc2548091350834b0d8b7efaf870bd9 Mon Sep 17 00:00:00 2001 From: Matthew Nickson Date: Fri, 6 Jan 2023 17:17:37 +0000 Subject: [PATCH 11/35] Changed wording for safeDelete function JSDoc --- extra/update-wiki-version.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/update-wiki-version.js b/extra/update-wiki-version.js index 880bc5568..f551db41b 100644 --- a/extra/update-wiki-version.js +++ b/extra/update-wiki-version.js @@ -44,7 +44,7 @@ function updateWiki(newVersion) { } /** - * Check if a directory exists before deleting + * Check if a directory exists and then delete it * @param {string} dir Directory to delete */ function safeDelete(dir) { From 33355c51b792430d4a262a86747d656af550d95e Mon Sep 17 00:00:00 2001 From: Joseph Irving Date: Thu, 13 Oct 2022 11:15:02 +0100 Subject: [PATCH 12/35] Add Splunk Notifications --- server/notification-providers/splunk.js | 113 ++++++++++++++++++++++++ server/notification.js | 2 + src/components/notifications/Splunk.vue | 32 +++++++ src/components/notifications/index.js | 2 + 4 files changed, 149 insertions(+) create mode 100644 server/notification-providers/splunk.js create mode 100644 src/components/notifications/Splunk.vue diff --git a/server/notification-providers/splunk.js b/server/notification-providers/splunk.js new file mode 100644 index 000000000..2d82dd397 --- /dev/null +++ b/server/notification-providers/splunk.js @@ -0,0 +1,113 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); +const { setting } = require("../util-server"); +let successMessage = "Sent Successfully."; + +class Splunk extends NotificationProvider { + name = "Splunk"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + try { + if (heartbeatJSON == null) { + const title = "Uptime Kuma Alert"; + const monitor = { + type: "ping", + url: "Uptime Kuma Test Button", + }; + return this.postNotification(notification, title, msg, monitor, "trigger"); + } + + if (heartbeatJSON.status === UP) { + const title = "Uptime Kuma Monitor ✅ Up"; + return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, "recovery"); + } + + if (heartbeatJSON.status === DOWN) { + const title = "Uptime Kuma Monitor 🔴 Down"; + return this.postNotification(notification, title, heartbeatJSON.msg, monitorJSON, "trigger"); + } + } catch (error) { + this.throwGeneralAxiosError(error); + } + } + + /** + * Check if result is successful, result code should be in range 2xx + * @param {Object} result Axios response object + * @throws {Error} The status code is not in range 2xx + */ + checkResult(result) { + if (result.status == null) { + throw new Error("Splunk notification failed with invalid response!"); + } + if (result.status < 200 || result.status >= 300) { + throw new Error("Splunk notification failed with status code " + result.status); + } + } + + /** + * Send the message + * @param {BeanModel} notification Message title + * @param {string} title Message title + * @param {string} body Message + * @param {Object} monitorInfo Monitor details (For Up/Down only) + * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) + * @returns {string} + */ + async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { + + let monitorUrl; + if (monitorInfo.type === "port") { + monitorUrl = monitorInfo.hostname; + if (monitorInfo.port) { + monitorUrl += ":" + monitorInfo.port; + } + } else if (monitorInfo.hostname != null) { + monitorUrl = monitorInfo.hostname; + } else { + monitorUrl = monitorInfo.url; + } + + if (eventAction === "recovery") { + if (notification.splunkAutoResolve === "0") { + return "No action required"; + } + eventAction = notification.splunkAutoResolve; + } else { + eventAction = notification.splunkSeverity; + } + + const options = { + method: "POST", + url: notification.splunkRestURL, + headers: { "Content-Type": "application/json" }, + data: { + message_type: eventAction, + state_message: `[${title}] [${monitorUrl}] ${body}`, + entity_display_name: "Uptime Kuma Alert: " + monitorInfo.name, + routing_key: notification.pagerdutyIntegrationKey, + entity_id: "Uptime Kuma/" + monitorInfo.id, + } + }; + + const baseURL = await setting("primaryBaseURL"); + if (baseURL && monitorInfo) { + options.client = "Uptime Kuma"; + options.client_url = baseURL + getMonitorRelativeURL(monitorInfo.id); + } + + let result = await axios.request(options); + this.checkResult(result); + if (result.statusText != null) { + return "Splunk notification succeed: " + result.statusText; + } + + return successMessage; + } +} + +module.exports = Splunk; diff --git a/server/notification.js b/server/notification.js index 1aad704c0..fd3491238 100644 --- a/server/notification.js +++ b/server/notification.js @@ -40,6 +40,7 @@ const Stackfield = require("./notification-providers/stackfield"); const Teams = require("./notification-providers/teams"); const TechulusPush = require("./notification-providers/techulus-push"); const Telegram = require("./notification-providers/telegram"); +const Splunk = require("./notification-providers/splunk"); const Webhook = require("./notification-providers/webhook"); const WeCom = require("./notification-providers/wecom"); const GoAlert = require("./notification-providers/goalert"); @@ -100,6 +101,7 @@ class Notification { new Teams(), new TechulusPush(), new Telegram(), + new Splunk(), new Webhook(), new WeCom(), new GoAlert(), diff --git a/src/components/notifications/Splunk.vue b/src/components/notifications/Splunk.vue new file mode 100644 index 000000000..86448517b --- /dev/null +++ b/src/components/notifications/Splunk.vue @@ -0,0 +1,32 @@ + + + diff --git a/src/components/notifications/index.js b/src/components/notifications/index.js index 810cdf03e..3c8b26210 100644 --- a/src/components/notifications/index.js +++ b/src/components/notifications/index.js @@ -44,6 +44,7 @@ import Webhook from "./Webhook.vue"; import WeCom from "./WeCom.vue"; import GoAlert from "./GoAlert.vue"; import ZohoCliq from "./ZohoCliq.vue"; +import Splunk from "./Splunk.vue"; /** * Manage all notification form. @@ -92,6 +93,7 @@ const NotificationFormList = { "stackfield": Stackfield, "teams": Teams, "telegram": Telegram, + "Splunk": Splunk, "webhook": Webhook, "WeCom": WeCom, "GoAlert": GoAlert, From ecd661c8016309646a3c93ec0ee7cd5ee33827b6 Mon Sep 17 00:00:00 2001 From: Luke <35193662+PopcornPanda@users.noreply.github.com> Date: Wed, 11 Jan 2023 12:06:09 +0100 Subject: [PATCH 13/35] Allow long sms in PromoSMS --- server/notification-providers/promosms.js | 1 + 1 file changed, 1 insertion(+) diff --git a/server/notification-providers/promosms.js b/server/notification-providers/promosms.js index 4f7e8f901..a9e7631eb 100644 --- a/server/notification-providers/promosms.js +++ b/server/notification-providers/promosms.js @@ -20,6 +20,7 @@ class PromoSMS extends NotificationProvider { "recipients": [ notification.promosmsPhoneNumber ], //Lets remove non ascii char "text": msg.replace(/[^\x00-\x7F]/g, ""), + "long-sms": true, "type": Number(notification.promosmsSMSType), "sender": notification.promosmsSenderName }; From 2172112144fc5d66255c5edfc628b51bb6097a8b Mon Sep 17 00:00:00 2001 From: Luke <35193662+PopcornPanda@users.noreply.github.com> Date: Wed, 11 Jan 2023 12:13:47 +0100 Subject: [PATCH 14/35] Setting for allowing long sms --- server/notification-providers/promosms.js | 2 +- src/components/notifications/PromoSMS.vue | 4 ++++ src/languages/en.js | 1 + src/languages/pl.js | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/server/notification-providers/promosms.js b/server/notification-providers/promosms.js index a9e7631eb..6992171be 100644 --- a/server/notification-providers/promosms.js +++ b/server/notification-providers/promosms.js @@ -20,7 +20,7 @@ class PromoSMS extends NotificationProvider { "recipients": [ notification.promosmsPhoneNumber ], //Lets remove non ascii char "text": msg.replace(/[^\x00-\x7F]/g, ""), - "long-sms": true, + "long-sms": notification.promosmsAllowLong, "type": Number(notification.promosmsSMSType), "sender": notification.promosmsSenderName }; diff --git a/src/components/notifications/PromoSMS.vue b/src/components/notifications/PromoSMS.vue index 03c02222d..9fe9c2172 100644 --- a/src/components/notifications/PromoSMS.vue +++ b/src/components/notifications/PromoSMS.vue @@ -26,6 +26,10 @@ +