From 401710c3bd83ae2b0702b23753e80e0afd36f4c2 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 07:01:49 +0530 Subject: [PATCH 01/16] fix(app): Fix proxy modal test --- src/components/ProxyDialog.vue | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index fc92359b..62eb6f2b 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -130,6 +130,27 @@ export default { this.modal = new Modal(this.$refs.modal); }, + beforeRouteLeave(to, from, next) { + if (this.modal) { + this.modal.hide(); + } + next(); + }, + + watch: { + $route(to, from) { + if (this.modal) { + this.modal.hide(); + } + } + }, + + beforeUnmount() { + if (this.modal) { + this.modal.dispose(); + } + }, + methods: { /** * Show dialog to confirm deletion From 1dceb96c7c81941f11b454dfc5c36b7bd707cd5e Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 07:17:31 +0530 Subject: [PATCH 02/16] fix(app): notification modal fix --- src/components/NotificationDialog.vue | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 864cbf5f..b34b5f8a 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -226,10 +226,26 @@ export default { this.notification.name = this.getUniqueDefaultName(to); } }, + $route(to, from) { + if (this.modal) { + this.modal.hide(); + } + } }, mounted() { this.modal = new Modal(this.$refs.modal); }, + beforeUnmount() { + if (this.modal) { + this.modal.dispose(); + } + }, + beforeRouteLeave(to, from, next) { + if (this.modal) { + this.modal.hide(); + } + next(); + }, methods: { /** From 45b6c8a91d084695b3ff1e144129682cd9f8161e Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 07:33:18 +0530 Subject: [PATCH 03/16] Fix scroll lock when the modal is opened, its sets overflow hidden, remove this style so as to unfreeze it --- src/components/ProxyDialog.vue | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index 62eb6f2b..718bdb5f 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -131,24 +131,18 @@ export default { }, beforeRouteLeave(to, from, next) { - if (this.modal) { - this.modal.hide(); - } + this.cleanupModal(); next(); }, watch: { $route(to, from) { - if (this.modal) { - this.modal.hide(); - } + this.cleanupModal(); } }, beforeUnmount() { - if (this.modal) { - this.modal.dispose(); - } + this.cleanupModal(); }, methods: { @@ -230,6 +224,20 @@ export default { } }); }, + + /** + * Clean up modal and restore scroll behavior + * @returns {void} + */ + cleanupModal() { + if (this.modal) { + this.modal.hide(); + this.modal.dispose(); + } + document.body.classList.remove('modal-open'); + document.body.style.paddingRight = ''; + document.body.style.overflow = ''; + } }, }; From da831893de8e56072c0e3bebe0128b5f21309b55 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 07:37:35 +0530 Subject: [PATCH 04/16] fix scroll in notfication --- src/components/NotificationDialog.vue | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index b34b5f8a..fd9042a5 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -226,24 +226,20 @@ export default { this.notification.name = this.getUniqueDefaultName(to); } }, + watch: { $route(to, from) { - if (this.modal) { - this.modal.hide(); - } + this.cleanupModal(); } }, + }, mounted() { this.modal = new Modal(this.$refs.modal); }, beforeUnmount() { - if (this.modal) { - this.modal.dispose(); - } + this.cleanupModal(); }, beforeRouteLeave(to, from, next) { - if (this.modal) { - this.modal.hide(); - } + this.cleanupModal(); next(); }, methods: { @@ -350,6 +346,20 @@ export default { }); } while (this.$root.notificationList.find(it => it.name === name)); return name; + }, + + /** + * Clean up modal and restore scroll behavior + * @returns {void} + */ + cleanupModal() { + if (this.modal) { + this.modal.hide(); + this.modal.dispose(); + } + document.body.classList.remove('modal-open'); + document.body.style.paddingRight = ''; + document.body.style.overflow = ''; } }, }; From e2ce0e38a68a7eb8432e98993e8ec2b411efe45e Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 08:23:07 +0530 Subject: [PATCH 05/16] update --- src/components/CreateGroupDialog.vue | 28 +++++++++++++++++++++++++ src/components/NotificationDialog.vue | 7 +++++-- src/components/ProxyDialog.vue | 7 +++++-- src/components/TagsManager.vue | 30 +++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 4 deletions(-) diff --git a/src/components/CreateGroupDialog.vue b/src/components/CreateGroupDialog.vue index ba7fe6eb..71136975 100644 --- a/src/components/CreateGroupDialog.vue +++ b/src/components/CreateGroupDialog.vue @@ -42,6 +42,18 @@ export default { mounted() { this.modal = new Modal(this.$refs.modal); }, + watch: { + $route(to, from) { + this.cleanupModal(); + } + }, + beforeUnmount() { + this.cleanupModal(); + }, + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, methods: { /** * Show the confirm dialog @@ -58,6 +70,22 @@ export default { this.$emit("added", this.groupName); this.modal.hide(); }, + /** + * Clean up modal and restore scroll behavior + * @returns {void} + */ + cleanupModal() { + if (this.modal) { + try { + this.modal.hide(); + } catch (e) { + console.warn("Modal hide failed:", e); + } + } + document.body.classList.remove('modal-open'); + document.body.style.paddingRight = ''; + document.body.style.overflow = ''; + } }, }; diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index fd9042a5..41b17978 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -354,8 +354,11 @@ export default { */ cleanupModal() { if (this.modal) { - this.modal.hide(); - this.modal.dispose(); + try { + this.modal.hide(); + } catch (e) { + console.warn("Modal hide failed:", e); + } } document.body.classList.remove('modal-open'); document.body.style.paddingRight = ''; diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index 718bdb5f..35c752a1 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -231,8 +231,11 @@ export default { */ cleanupModal() { if (this.modal) { - this.modal.hide(); - this.modal.dispose(); + try { + this.modal.hide(); + } catch (e) { + console.warn("Modal hide failed:", e); + } } document.body.classList.remove('modal-open'); document.body.style.paddingRight = ''; diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index 19c8e481..398cd8bd 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -248,6 +248,20 @@ export default { this.modal = new Modal(this.$refs.modal); this.getExistingTags(); }, + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, + + watch: { + $route(to, from) { + this.cleanupModal(); + } + }, + + beforeUnmount() { + this.cleanupModal(); + }, methods: { /** * Show the add tag dialog @@ -459,6 +473,22 @@ export default { this.newTags = []; this.deleteTags = []; this.processing = false; + }, + /** + * Clean up modal and restore scroll behavior + * @returns {void} + */ + cleanupModal() { + if (this.modal) { + try { + this.modal.hide(); + } catch (e) { + console.warn("Modal hide failed:", e); + } + } + document.body.classList.remove('modal-open'); + document.body.style.paddingRight = ''; + document.body.style.overflow = ''; } }, }; From 72849de1b467f21e550858982c071b8b669c981c Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 08:43:30 +0530 Subject: [PATCH 06/16] fix lint --- src/components/CreateGroupDialog.vue | 8 ++++---- src/components/NotificationDialog.vue | 10 ++++------ src/components/ProxyDialog.vue | 8 ++++---- src/components/TagsManager.vue | 8 ++++---- 4 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/components/CreateGroupDialog.vue b/src/components/CreateGroupDialog.vue index 71136975..ee37fb0b 100644 --- a/src/components/CreateGroupDialog.vue +++ b/src/components/CreateGroupDialog.vue @@ -74,7 +74,7 @@ export default { * Clean up modal and restore scroll behavior * @returns {void} */ - cleanupModal() { + cleanupModal() { if (this.modal) { try { this.modal.hide(); @@ -82,9 +82,9 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove('modal-open'); - document.body.style.paddingRight = ''; - document.body.style.overflow = ''; + document.body.classList.remove("modal-open"); + document.body.style.paddingRight = ""; + document.body.style.overflow = ""; } }, }; diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 41b17978..4641fe9a 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -226,12 +226,10 @@ export default { this.notification.name = this.getUniqueDefaultName(to); } }, - watch: { $route(to, from) { this.cleanupModal(); } }, - }, mounted() { this.modal = new Modal(this.$refs.modal); }, @@ -352,7 +350,7 @@ export default { * Clean up modal and restore scroll behavior * @returns {void} */ - cleanupModal() { + cleanupModal() { if (this.modal) { try { this.modal.hide(); @@ -360,9 +358,9 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove('modal-open'); - document.body.style.paddingRight = ''; - document.body.style.overflow = ''; + document.body.classList.remove("modal-open"); + document.body.style.paddingRight = ""; + document.body.style.overflow = ""; } }, }; diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index 35c752a1..8c212f26 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -229,7 +229,7 @@ export default { * Clean up modal and restore scroll behavior * @returns {void} */ - cleanupModal() { + cleanupModal() { if (this.modal) { try { this.modal.hide(); @@ -237,9 +237,9 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove('modal-open'); - document.body.style.paddingRight = ''; - document.body.style.overflow = ''; + document.body.classList.remove("modal-open"); + document.body.style.paddingRight = ""; + document.body.style.overflow = ""; } }, }; diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index 398cd8bd..b4938304 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -478,7 +478,7 @@ export default { * Clean up modal and restore scroll behavior * @returns {void} */ - cleanupModal() { + cleanupModal() { if (this.modal) { try { this.modal.hide(); @@ -486,9 +486,9 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove('modal-open'); - document.body.style.paddingRight = ''; - document.body.style.overflow = ''; + document.body.classList.remove("modal-open"); + document.body.style.paddingRight = ""; + document.body.style.overflow = ""; } }, }; From 56b3cf412b7758ddbfbc6226c47842df180e5f16 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 09:10:36 +0530 Subject: [PATCH 07/16] warnings fix :) --- src/components/CreateGroupDialog.vue | 14 +++++++------- src/components/ProxyDialog.vue | 19 +++++++------------ src/components/TagsManager.vue | 18 ++++++++---------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/components/CreateGroupDialog.vue b/src/components/CreateGroupDialog.vue index ee37fb0b..32610764 100644 --- a/src/components/CreateGroupDialog.vue +++ b/src/components/CreateGroupDialog.vue @@ -33,27 +33,27 @@ import { Modal } from "bootstrap"; export default { + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, props: {}, emits: [ "added" ], data: () => ({ modal: null, groupName: null, }), - mounted() { - this.modal = new Modal(this.$refs.modal); - }, watch: { $route(to, from) { this.cleanupModal(); } }, + mounted() { + this.modal = new Modal(this.$refs.modal); + }, beforeUnmount() { this.cleanupModal(); }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, methods: { /** * Show the confirm dialog diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index 8c212f26..a6f6cce5 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -105,6 +105,10 @@ export default { components: { Confirm, }, + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, props: {}, emits: [ "added" ], data() { @@ -125,26 +129,17 @@ export default { } }; }, - - mounted() { - this.modal = new Modal(this.$refs.modal); - }, - - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, - watch: { $route(to, from) { this.cleanupModal(); } }, - + mounted() { + this.modal = new Modal(this.$refs.modal); + }, beforeUnmount() { this.cleanupModal(); }, - methods: { /** * Show dialog to confirm deletion diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index b4938304..2cc3549c 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -155,6 +155,10 @@ export default { Tag, VueMultiselect, }, + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, props: { /** * Array of tags to be pre-selected @@ -244,21 +248,15 @@ export default { }; }, }, - mounted() { - this.modal = new Modal(this.$refs.modal); - this.getExistingTags(); - }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, - watch: { $route(to, from) { this.cleanupModal(); } }, - + mounted() { + this.modal = new Modal(this.$refs.modal); + this.getExistingTags(); + }, beforeUnmount() { this.cleanupModal(); }, From 0d2b380f44f7541e836b1eaaa464878be029de11 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 09:31:05 +0530 Subject: [PATCH 08/16] Update NotificationDialog.vue i hadnt saved this T_T --- src/components/NotificationDialog.vue | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index 4641fe9a..dffe2e03 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -80,6 +80,10 @@ export default { components: { Confirm, }, + beforeRouteLeave(to, from, next) { + this.cleanupModal(); + next(); + }, props: {}, emits: [ "added" ], data() { @@ -236,10 +240,6 @@ export default { beforeUnmount() { this.cleanupModal(); }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, methods: { /** From 95a9e0a096aee1f1b205d5d25a2ba7c1d51bdf4d Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Tue, 8 Oct 2024 19:09:21 +0530 Subject: [PATCH 09/16] remove duplicate code --- src/components/CreateGroupDialog.vue | 12 ------------ src/components/NotificationDialog.vue | 10 ---------- src/components/ProxyDialog.vue | 12 ------------ src/components/TagsManager.vue | 12 ------------ 4 files changed, 46 deletions(-) diff --git a/src/components/CreateGroupDialog.vue b/src/components/CreateGroupDialog.vue index 32610764..8bac1ccd 100644 --- a/src/components/CreateGroupDialog.vue +++ b/src/components/CreateGroupDialog.vue @@ -33,21 +33,12 @@ import { Modal } from "bootstrap"; export default { - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, props: {}, emits: [ "added" ], data: () => ({ modal: null, groupName: null, }), - watch: { - $route(to, from) { - this.cleanupModal(); - } - }, mounted() { this.modal = new Modal(this.$refs.modal); }, @@ -82,9 +73,6 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove("modal-open"); - document.body.style.paddingRight = ""; - document.body.style.overflow = ""; } }, }; diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index dffe2e03..cd001b37 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -80,10 +80,6 @@ export default { components: { Confirm, }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, props: {}, emits: [ "added" ], data() { @@ -230,9 +226,6 @@ export default { this.notification.name = this.getUniqueDefaultName(to); } }, - $route(to, from) { - this.cleanupModal(); - } }, mounted() { this.modal = new Modal(this.$refs.modal); @@ -358,9 +351,6 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove("modal-open"); - document.body.style.paddingRight = ""; - document.body.style.overflow = ""; } }, }; diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue index a6f6cce5..2f7ed7b6 100644 --- a/src/components/ProxyDialog.vue +++ b/src/components/ProxyDialog.vue @@ -105,10 +105,6 @@ export default { components: { Confirm, }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, props: {}, emits: [ "added" ], data() { @@ -129,11 +125,6 @@ export default { } }; }, - watch: { - $route(to, from) { - this.cleanupModal(); - } - }, mounted() { this.modal = new Modal(this.$refs.modal); }, @@ -232,9 +223,6 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove("modal-open"); - document.body.style.paddingRight = ""; - document.body.style.overflow = ""; } }, }; diff --git a/src/components/TagsManager.vue b/src/components/TagsManager.vue index 2cc3549c..368ea18c 100644 --- a/src/components/TagsManager.vue +++ b/src/components/TagsManager.vue @@ -155,10 +155,6 @@ export default { Tag, VueMultiselect, }, - beforeRouteLeave(to, from, next) { - this.cleanupModal(); - next(); - }, props: { /** * Array of tags to be pre-selected @@ -248,11 +244,6 @@ export default { }; }, }, - watch: { - $route(to, from) { - this.cleanupModal(); - } - }, mounted() { this.modal = new Modal(this.$refs.modal); this.getExistingTags(); @@ -484,9 +475,6 @@ export default { console.warn("Modal hide failed:", e); } } - document.body.classList.remove("modal-open"); - document.body.style.paddingRight = ""; - document.body.style.overflow = ""; } }, }; From 498786eb3922563dbe1318ec88af31446e666137 Mon Sep 17 00:00:00 2001 From: "deepsource-io[bot]" <42547082+deepsource-io[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 07:51:20 +0000 Subject: [PATCH 10/16] ci: add .deepsource.toml --- .deepsource.toml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml new file mode 100644 index 00000000..525c75c6 --- /dev/null +++ b/.deepsource.toml @@ -0,0 +1,31 @@ +version = 1 + +[[analyzers]] +name = "php" + +[[analyzers]] +name = "python" + + [analyzers.meta] + runtime_version = "3.x.x" + +[[analyzers]] +name = "go" + + [analyzers.meta] + import_root = "github.com/mohit-nagaraj/uptime-kuma" + +[[analyzers]] +name = "java" + + [analyzers.meta] + runtime_version = "11" + +[[analyzers]] +name = "csharp" + +[[analyzers]] +name = "javascript" + +[[analyzers]] +name = "shell" \ No newline at end of file From 949198d09ea16494c62d79759bba4da5eeb5463e Mon Sep 17 00:00:00 2001 From: "deepsource-autofix[bot]" <62050782+deepsource-autofix[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 08:31:13 +0000 Subject: [PATCH 12/16] refactor: fix check for empty string It is not recommended to use `len` for empty string test. --- extra/healthcheck.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extra/healthcheck.go b/extra/healthcheck.go index f79b3e65..9687a663 100644 --- a/extra/healthcheck.go +++ b/extra/healthcheck.go @@ -32,20 +32,20 @@ func main() { } sslKey := os.Getenv("UPTIME_KUMA_SSL_KEY") - if len(sslKey) == 0 { + if sslKey == "" { sslKey = os.Getenv("SSL_KEY") } sslCert := os.Getenv("UPTIME_KUMA_SSL_CERT") - if len(sslCert) == 0 { + if sslCert == "" { sslCert = os.Getenv("SSL_CERT") } hostname := os.Getenv("UPTIME_KUMA_HOST") - if len(hostname) == 0 && !isFreeBSD { + if hostname == "" && !isFreeBSD { hostname = os.Getenv("HOST") } - if len(hostname) == 0 { + if hostname == "" { hostname = "127.0.0.1" } @@ -54,15 +54,15 @@ func main() { if !isK8s { port = os.Getenv("UPTIME_KUMA_PORT") } - if len(port) == 0 { + if port == "" { port = os.Getenv("PORT") } - if len(port) == 0 { + if port == "" { port = "3001" } protocol := "" - if len(sslKey) != 0 && len(sslCert) != 0 { + if sslKey != "" && sslCert != "" { protocol = "https" } else { protocol = "http" From dcb675a343c6b4aa17bc708514434f56a97d31f6 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Fri, 11 Oct 2024 14:23:35 +0530 Subject: [PATCH 13/16] update --- .deepsource.toml | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 .deepsource.toml diff --git a/.deepsource.toml b/.deepsource.toml deleted file mode 100644 index 525c75c6..00000000 --- a/.deepsource.toml +++ /dev/null @@ -1,31 +0,0 @@ -version = 1 - -[[analyzers]] -name = "php" - -[[analyzers]] -name = "python" - - [analyzers.meta] - runtime_version = "3.x.x" - -[[analyzers]] -name = "go" - - [analyzers.meta] - import_root = "github.com/mohit-nagaraj/uptime-kuma" - -[[analyzers]] -name = "java" - - [analyzers.meta] - runtime_version = "11" - -[[analyzers]] -name = "csharp" - -[[analyzers]] -name = "javascript" - -[[analyzers]] -name = "shell" \ No newline at end of file From 9684d34ad0b534e6a54af4eacb6da72a7e0d49d2 Mon Sep 17 00:00:00 2001 From: mohit-nagaraj Date: Fri, 11 Oct 2024 15:11:13 +0530 Subject: [PATCH 14/16] Revert "refactor: fix check for empty string" This reverts commit 949198d09ea16494c62d79759bba4da5eeb5463e. --- extra/healthcheck.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/extra/healthcheck.go b/extra/healthcheck.go index 9687a663..f79b3e65 100644 --- a/extra/healthcheck.go +++ b/extra/healthcheck.go @@ -32,20 +32,20 @@ func main() { } sslKey := os.Getenv("UPTIME_KUMA_SSL_KEY") - if sslKey == "" { + if len(sslKey) == 0 { sslKey = os.Getenv("SSL_KEY") } sslCert := os.Getenv("UPTIME_KUMA_SSL_CERT") - if sslCert == "" { + if len(sslCert) == 0 { sslCert = os.Getenv("SSL_CERT") } hostname := os.Getenv("UPTIME_KUMA_HOST") - if hostname == "" && !isFreeBSD { + if len(hostname) == 0 && !isFreeBSD { hostname = os.Getenv("HOST") } - if hostname == "" { + if len(hostname) == 0 { hostname = "127.0.0.1" } @@ -54,15 +54,15 @@ func main() { if !isK8s { port = os.Getenv("UPTIME_KUMA_PORT") } - if port == "" { + if len(port) == 0 { port = os.Getenv("PORT") } - if port == "" { + if len(port) == 0 { port = "3001" } protocol := "" - if sslKey != "" && sslCert != "" { + if len(sslKey) != 0 && len(sslCert) != 0 { protocol = "https" } else { protocol = "http" From a7e9bdd43e27802b5593304bbbb1438fc98da8f5 Mon Sep 17 00:00:00 2001 From: Ryo Hanafusa Date: Sun, 20 Oct 2024 22:30:03 +0900 Subject: [PATCH 15/16] fix: expand hover trigger area of beat (#5223) Co-authored-by: Frank Elsinga --- src/components/HeartbeatBar.vue | 86 ++++++++++++++++++++------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index 96a62cf6..429ca9f9 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -4,11 +4,17 @@
+ > +
+
this.maxBeat) { - let width = -(this.beatWidth + this.beatMargin * 2); + let width = -(this.beatWidth + this.beatHoverAreaPadding * 2); return { transition: "all ease-in-out 0.25s", @@ -137,12 +143,17 @@ export default { }, + beatHoverAreaStyle() { + return { + padding: this.beatHoverAreaPadding + "px", + "--hover-scale": this.hoverScale, + }; + }, + beatStyle() { return { width: this.beatWidth + "px", height: this.beatHeight + "px", - margin: this.beatMargin + "px", - "--hover-scale": this.hoverScale, }; }, @@ -152,7 +163,7 @@ export default { */ timeStyle() { return { - "margin-left": this.numPadding * (this.beatWidth + this.beatMargin * 2) + "px", + "margin-left": this.numPadding * (this.beatWidth + this.beatHoverAreaPadding * 2) + "px", }; }, @@ -219,20 +230,20 @@ export default { if (this.size !== "big") { this.beatWidth = 5; this.beatHeight = 16; - this.beatMargin = 2; + this.beatHoverAreaPadding = 2; } // Suddenly, have an idea how to handle it universally. // If the pixel * ratio != Integer, then it causes render issue, round it to solve it!! const actualWidth = this.beatWidth * window.devicePixelRatio; - const actualMargin = this.beatMargin * window.devicePixelRatio; + const actualHoverAreaPadding = this.beatHoverAreaPadding * window.devicePixelRatio; if (!Number.isInteger(actualWidth)) { this.beatWidth = Math.round(actualWidth) / window.devicePixelRatio; } - if (!Number.isInteger(actualMargin)) { - this.beatMargin = Math.round(actualMargin) / window.devicePixelRatio; + if (!Number.isInteger(actualHoverAreaPadding)) { + this.beatHoverAreaPadding = Math.round(actualHoverAreaPadding) / window.devicePixelRatio; } window.addEventListener("resize", this.resize); @@ -245,7 +256,7 @@ export default { */ resize() { if (this.$refs.wrap) { - this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2)); + this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatHoverAreaPadding * 2)); } }, @@ -273,32 +284,41 @@ export default { } .hp-bar-big { - .beat { + .beat-hover-area { display: inline-block; - background-color: $primary; - border-radius: $border-radius; - - &.empty { - background-color: aliceblue; - } - - &.down { - background-color: $danger; - } - - &.pending { - background-color: $warning; - } - - &.maintenance { - background-color: $maintenance; - } &:not(.empty):hover { transition: all ease-in-out 0.15s; opacity: 0.8; transform: scale(var(--hover-scale)); } + + .beat { + background-color: $primary; + border-radius: $border-radius; + + /* + pointer-events needs to be changed because + tooltip momentarily disappears when crossing between .beat-hover-area and .beat + */ + pointer-events: none; + + &.empty { + background-color: aliceblue; + } + + &.down { + background-color: $danger; + } + + &.pending { + background-color: $warning; + } + + &.maintenance { + background-color: $maintenance; + } + } } } From c01494ec33d68dc896774c7846aa6909d415ed34 Mon Sep 17 00:00:00 2001 From: Suven-p Date: Sun, 20 Oct 2024 19:42:03 +0545 Subject: [PATCH 16/16] feat: add `RabbitMQ` monitor (#5199) Co-authored-by: Frank Elsinga --- .../2024-10-1315-rabbitmq-monitor.js | 17 +++++ package-lock.json | 17 +++-- package.json | 1 + server/model/monitor.js | 3 + server/monitor-types/rabbitmq.js | 67 +++++++++++++++++++ server/server.js | 5 ++ server/uptime-kuma-server.js | 2 + src/lang/en.json | 7 ++ src/pages/EditMonitor.vue | 67 ++++++++++++++++++- test/backend-test/test-rabbitmq.js | 53 +++++++++++++++ 10 files changed, 234 insertions(+), 5 deletions(-) create mode 100644 db/knex_migrations/2024-10-1315-rabbitmq-monitor.js create mode 100644 server/monitor-types/rabbitmq.js create mode 100644 test/backend-test/test-rabbitmq.js diff --git a/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js b/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js new file mode 100644 index 00000000..6a17f336 --- /dev/null +++ b/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js @@ -0,0 +1,17 @@ +exports.up = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.text("rabbitmq_nodes"); + table.string("rabbitmq_username"); + table.string("rabbitmq_password"); + }); + +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("rabbitmq_nodes"); + table.dropColumn("rabbitmq_username"); + table.dropColumn("rabbitmq_password"); + }); + +}; diff --git a/package-lock.json b/package-lock.json index a89b1b56..24f63d03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -93,6 +93,7 @@ "@playwright/test": "~1.39.0", "@popperjs/core": "~2.10.2", "@testcontainers/hivemq": "^10.13.1", + "@testcontainers/rabbitmq": "^10.13.2", "@types/bootstrap": "~5.1.9", "@types/node": "^20.8.6", "@typescript-eslint/eslint-plugin": "^6.7.5", @@ -4172,6 +4173,15 @@ "testcontainers": "^10.13.1" } }, + "node_modules/@testcontainers/rabbitmq": { + "version": "10.13.2", + "resolved": "https://registry.npmjs.org/@testcontainers/rabbitmq/-/rabbitmq-10.13.2.tgz", + "integrity": "sha512-npBKBnq3c6hETmxGZ/gVMke9cc1J/pcftNW9S3WidL48hxFBIPjYNM9FdTfWuoNER/8kuf4xJ8yCuJEYGH3ZAg==", + "dev": true, + "dependencies": { + "testcontainers": "^10.13.2" + } + }, "node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -15925,11 +15935,10 @@ } }, "node_modules/testcontainers": { - "version": "10.13.1", - "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.13.1.tgz", - "integrity": "sha512-JBbOhxmygj/ouH/47GnoVNt+c55Telh/45IjVxEbDoswsLchVmJiuKiw/eF6lE5i7LN+/99xsrSCttI3YRtirg==", + "version": "10.13.2", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.13.2.tgz", + "integrity": "sha512-LfEll+AG/1Ks3n4+IA5lpyBHLiYh/hSfI4+ERa6urwfQscbDU+M2iW1qPQrHQi+xJXQRYy4whyK1IEHdmxWa3Q==", "dev": true, - "license": "MIT", "dependencies": { "@balena/dockerignore": "^1.0.2", "@types/dockerode": "^3.3.29", diff --git a/package.json b/package.json index c6bef90e..5186cafc 100644 --- a/package.json +++ b/package.json @@ -155,6 +155,7 @@ "@playwright/test": "~1.39.0", "@popperjs/core": "~2.10.2", "@testcontainers/hivemq": "^10.13.1", + "@testcontainers/rabbitmq": "^10.13.2", "@types/bootstrap": "~5.1.9", "@types/node": "^20.8.6", "@typescript-eslint/eslint-plugin": "^6.7.5", diff --git a/server/model/monitor.js b/server/model/monitor.js index da0c0d5c..9a30a668 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -153,6 +153,7 @@ class Monitor extends BeanModel { snmpOid: this.snmpOid, jsonPathOperator: this.jsonPathOperator, snmpVersion: this.snmpVersion, + rabbitmqNodes: JSON.parse(this.rabbitmqNodes), conditions: JSON.parse(this.conditions), }; @@ -183,6 +184,8 @@ class Monitor extends BeanModel { tlsCert: this.tlsCert, tlsKey: this.tlsKey, kafkaProducerSaslOptions: JSON.parse(this.kafkaProducerSaslOptions), + rabbitmqUsername: this.rabbitmqUsername, + rabbitmqPassword: this.rabbitmqPassword, }; } diff --git a/server/monitor-types/rabbitmq.js b/server/monitor-types/rabbitmq.js new file mode 100644 index 00000000..165a0ed9 --- /dev/null +++ b/server/monitor-types/rabbitmq.js @@ -0,0 +1,67 @@ +const { MonitorType } = require("./monitor-type"); +const { log, UP, DOWN } = require("../../src/util"); +const { axiosAbortSignal } = require("../util-server"); +const axios = require("axios"); + +class RabbitMqMonitorType extends MonitorType { + name = "rabbitmq"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, server) { + let baseUrls = []; + try { + baseUrls = JSON.parse(monitor.rabbitmqNodes); + } catch (error) { + throw new Error("Invalid RabbitMQ Nodes"); + } + + heartbeat.status = DOWN; + for (let baseUrl of baseUrls) { + try { + // Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com + if ( !baseUrl.endsWith("/") ) { + baseUrl += "/"; + } + const options = { + // Do not start with slash, it will strip the trailing slash from baseUrl + url: new URL("api/health/checks/alarms/", baseUrl).href, + method: "get", + timeout: monitor.timeout * 1000, + headers: { + "Accept": "application/json", + "Authorization": "Basic " + Buffer.from(`${monitor.rabbitmqUsername || ""}:${monitor.rabbitmqPassword || ""}`).toString("base64"), + }, + signal: axiosAbortSignal((monitor.timeout + 10) * 1000), + // Capture reason for 503 status + validateStatus: (status) => status === 200 || status === 503, + }; + log.debug("monitor", `[${monitor.name}] Axios Request: ${JSON.stringify(options)}`); + const res = await axios.request(options); + log.debug("monitor", `[${monitor.name}] Axios Response: status=${res.status} body=${JSON.stringify(res.data)}`); + if (res.status === 200) { + heartbeat.status = UP; + heartbeat.msg = "OK"; + break; + } else if (res.status === 503) { + heartbeat.msg = res.data.reason; + } else { + heartbeat.msg = `${res.status} - ${res.statusText}`; + } + } catch (error) { + if (axios.isCancel(error)) { + heartbeat.msg = "Request timed out"; + log.debug("monitor", `[${monitor.name}] Request timed out`); + } else { + log.debug("monitor", `[${monitor.name}] Axios Error: ${JSON.stringify(error.message)}`); + heartbeat.msg = error.message; + } + } + } + } +} + +module.exports = { + RabbitMqMonitorType, +}; diff --git a/server/server.js b/server/server.js index db58ae82..c88daca8 100644 --- a/server/server.js +++ b/server/server.js @@ -718,6 +718,8 @@ let needSetup = false; monitor.conditions = JSON.stringify(monitor.conditions); + monitor.rabbitmqNodes = JSON.stringify(monitor.rabbitmqNodes); + bean.import(monitor); bean.user_id = socket.userID; @@ -868,6 +870,9 @@ let needSetup = false; bean.snmpOid = monitor.snmpOid; bean.jsonPathOperator = monitor.jsonPathOperator; bean.timeout = monitor.timeout; + bean.rabbitmqNodes = JSON.stringify(monitor.rabbitmqNodes); + bean.rabbitmqUsername = monitor.rabbitmqUsername; + bean.rabbitmqPassword = monitor.rabbitmqPassword; bean.conditions = JSON.stringify(monitor.conditions); bean.validate(); diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 76bf4256..062f098d 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -115,6 +115,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType(); UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType(); UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); + UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -552,4 +553,5 @@ const { DnsMonitorType } = require("./monitor-types/dns"); const { MqttMonitorType } = require("./monitor-types/mqtt"); const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); +const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); const Monitor = require("./model/monitor"); diff --git a/src/lang/en.json b/src/lang/en.json index 5bfc3bd9..d56e61bd 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -1052,6 +1052,13 @@ "Can be found on:": "Can be found on: {0}", "The phone number of the recipient in E.164 format.": "The phone number of the recipient in E.164 format.", "Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.":"Either a text sender ID or a phone number in E.164 format if you want to be able to receive replies.", + "RabbitMQ Nodes": "RabbitMQ Management Nodes", + "rabbitmqNodesDescription": "Enter the URL for the RabbitMQ management nodes including protocol and port. Example: {0}", + "rabbitmqNodesRequired": "Please set the nodes for this monitor.", + "rabbitmqNodesInvalid": "Please use a fully qualified (starting with 'http') URL for RabbitMQ nodes.", + "RabbitMQ Username": "RabbitMQ Username", + "RabbitMQ Password": "RabbitMQ Password", + "rabbitmqHelpText": "To use the monitor, you will need to enable the Management Plugin in your RabbitMQ setup. For more information, please consult the {rabitmq_documentation}.", "SendGrid API Key": "SendGrid API Key", "Separate multiple email addresses with commas": "Separate multiple email addresses with commas" } diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 5d999b59..677210c4 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -64,6 +64,9 @@ + @@ -90,6 +93,13 @@ + + +
+ +
@@ -549,7 +596,7 @@
-
+
@@ -1122,6 +1169,9 @@ const monitorDefaults = { kafkaProducerAllowAutoTopicCreation: false, gamedigGivenPortOnly: true, remote_browser: null, + rabbitmqNodes: [], + rabbitmqUsername: "", + rabbitmqPassword: "", conditions: [] }; @@ -1709,6 +1759,10 @@ message HealthCheckResponse { this.monitor.kafkaProducerBrokers.push(newBroker); }, + addRabbitmqNode(newNode) { + this.monitor.rabbitmqNodes.push(newNode); + }, + /** * Validate form input * @returns {boolean} Is the form input valid? @@ -1736,6 +1790,17 @@ message HealthCheckResponse { return false; } } + + if (this.monitor.type === "rabbitmq") { + if (this.monitor.rabbitmqNodes.length === 0) { + toast.error(this.$t("rabbitmqNodesRequired")); + return false; + } + if (!this.monitor.rabbitmqNodes.every(node => node.startsWith("http://") || node.startsWith("https://"))) { + toast.error(this.$t("rabbitmqNodesInvalid")); + return false; + } + } return true; }, diff --git a/test/backend-test/test-rabbitmq.js b/test/backend-test/test-rabbitmq.js new file mode 100644 index 00000000..5782ef25 --- /dev/null +++ b/test/backend-test/test-rabbitmq.js @@ -0,0 +1,53 @@ +const { describe, test } = require("node:test"); +const assert = require("node:assert"); +const { RabbitMQContainer } = require("@testcontainers/rabbitmq"); +const { RabbitMqMonitorType } = require("../../server/monitor-types/rabbitmq"); +const { UP, DOWN, PENDING } = require("../../src/util"); + +describe("RabbitMQ Single Node", { + skip: !!process.env.CI && (process.platform !== "linux" || process.arch !== "x64"), +}, () => { + test("RabbitMQ is running", async () => { + // The default timeout of 30 seconds might not be enough for the container to start + const rabbitMQContainer = await new RabbitMQContainer().withStartupTimeout(60000).start(); + const rabbitMQMonitor = new RabbitMqMonitorType(); + const connectionString = `http://${rabbitMQContainer.getHost()}:${rabbitMQContainer.getMappedPort(15672)}`; + + const monitor = { + rabbitmqNodes: JSON.stringify([ connectionString ]), + rabbitmqUsername: "guest", + rabbitmqPassword: "guest", + }; + + const heartbeat = { + msg: "", + status: PENDING, + }; + + try { + await rabbitMQMonitor.check(monitor, heartbeat, {}); + assert.strictEqual(heartbeat.status, UP); + assert.strictEqual(heartbeat.msg, "OK"); + } finally { + rabbitMQContainer.stop(); + } + }); + + test("RabbitMQ is not running", async () => { + const rabbitMQMonitor = new RabbitMqMonitorType(); + const monitor = { + rabbitmqNodes: JSON.stringify([ "http://localhost:15672" ]), + rabbitmqUsername: "rabbitmqUser", + rabbitmqPassword: "rabbitmqPass", + }; + + const heartbeat = { + msg: "", + status: PENDING, + }; + + await rabbitMQMonitor.check(monitor, heartbeat, {}); + assert.strictEqual(heartbeat.status, DOWN); + }); + +});