From cdb8ad321dbdce48d5baa47970da5b5d1de43df1 Mon Sep 17 00:00:00 2001
From: Luke Thomas <96008479+Zoobdude@users.noreply.github.com>
Date: Tue, 26 Nov 2024 00:56:23 +0000
Subject: [PATCH 1/3] fix: slug input (#5239)

Co-authored-by: Frank Elsinga <frank@elsinga.de>
---
 server/routers/status-page-router.js                 |  8 +++++++-
 server/socket-handlers/status-page-socket-handler.js |  1 +
 src/pages/AddStatusPage.vue                          | 11 ++++++-----
 3 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js
index b209d33d1..893f57564 100644
--- a/server/routers/status-page-router.js
+++ b/server/routers/status-page-router.js
@@ -15,11 +15,13 @@ const server = UptimeKumaServer.getInstance();
 
 router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
     let slug = request.params.slug;
+    slug = slug.toLowerCase();
     await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
 });
 
 router.get("/status/:slug/rss", cache("5 minutes"), async (request, response) => {
     let slug = request.params.slug;
+    slug = slug.toLowerCase();
     await StatusPage.handleStatusPageRSSResponse(response, slug);
 });
 
@@ -37,6 +39,7 @@ router.get("/status-page", cache("5 minutes"), async (request, response) => {
 router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
     allowDevAllOrigin(response);
     let slug = request.params.slug;
+    slug = slug.toLowerCase();
 
     try {
         // Get Status Page
@@ -69,6 +72,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
         let uptimeList = {};
 
         let slug = request.params.slug;
+        slug = slug.toLowerCase();
         let statusPageID = await StatusPage.slugToID(slug);
 
         let monitorIDList = await R.getCol(`
@@ -111,6 +115,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
 router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async (request, response) => {
     allowDevAllOrigin(response);
     let slug = request.params.slug;
+    slug = slug.toLowerCase();
 
     try {
         // Get Status Page
@@ -145,7 +150,8 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async
 // overall status-page status badge
 router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, response) => {
     allowDevAllOrigin(response);
-    const slug = request.params.slug;
+    let slug = request.params.slug;
+    slug = slug.toLowerCase();
     const statusPageID = await StatusPage.slugToID(slug);
     const {
         label,
diff --git a/server/socket-handlers/status-page-socket-handler.js b/server/socket-handlers/status-page-socket-handler.js
index cbcc52b8f..1114d81fd 100644
--- a/server/socket-handlers/status-page-socket-handler.js
+++ b/server/socket-handlers/status-page-socket-handler.js
@@ -292,6 +292,7 @@ module.exports.statusPageSocketHandler = (socket) => {
                 ok: true,
                 msg: "successAdded",
                 msgi18n: true,
+                slug: slug
             });
 
         } catch (error) {
diff --git a/src/pages/AddStatusPage.vue b/src/pages/AddStatusPage.vue
index bae61449c..b35091cc2 100644
--- a/src/pages/AddStatusPage.vue
+++ b/src/pages/AddStatusPage.vue
@@ -16,14 +16,11 @@
                         <label for="slug" class="form-label">{{ $t("Slug") }}</label>
                         <div class="input-group">
                             <span id="basic-addon3" class="input-group-text">/status/</span>
-                            <input id="slug" v-model="slug" type="text" class="form-control" required data-testid="slug-input">
+                            <input id="slug" v-model="slug" type="text" class="form-control" autocapitalize="none" required data-testid="slug-input">
                         </div>
                         <div class="form-text">
                             <ul>
                                 <li>{{ $t("Accept characters:") }} <mark>a-z</mark> <mark>0-9</mark> <mark>-</mark></li>
-                                <i18n-t tag="li" keypath="startOrEndWithOnly">
-                                    <mark>a-z</mark> <mark>0-9</mark>
-                                </i18n-t>
                                 <li>{{ $t("No consecutive dashes") }} <mark>--</mark></li>
                                 <i18n-t tag="li" keypath="statusPageSpecialSlugDesc">
                                     <mark class="me-1">default</mark>
@@ -65,7 +62,7 @@ export default {
                 this.processing = false;
 
                 if (res.ok) {
-                    location.href = "/status/" + this.slug + "?edit";
+                    location.href = "/status/" + res.slug + "?edit";
                 } else {
 
                     if (res.msg.includes("UNIQUE constraint")) {
@@ -85,4 +82,8 @@ export default {
 .shadow-box {
     padding: 20px;
 }
+
+#slug {
+    text-transform: lowercase;
+}
 </style>

From c0fe669cd8f8dcb4a7d3aefae834c7a70bc692db Mon Sep 17 00:00:00 2001
From: Cyril59310 <70776486+cyril59310@users.noreply.github.com>
Date: Wed, 27 Nov 2024 22:09:07 +0100
Subject: [PATCH 2/3] Fix the save bar of the maintenance menu (#5385)

Co-authored-by: Frank Elsinga <frank@elsinga.de>
---
 src/assets/app.scss | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/assets/app.scss b/src/assets/app.scss
index 28eeca87c..6ddc99dec 100644
--- a/src/assets/app.scss
+++ b/src/assets/app.scss
@@ -619,7 +619,7 @@ $shadow-box-padding: 20px;
     bottom: 0;
     margin-left: -$shadow-box-padding;
     margin-right: -$shadow-box-padding;
-    z-index: 100;
+    z-index: 10;
     background-color: rgba(white, 0.2);
     backdrop-filter: blur(2px);
     border-radius: 0 0 10px 10px;

From efdffca06ccf4a8ca96a2ffce44467386c3fb852 Mon Sep 17 00:00:00 2001
From: Louis Lam <louislam@users.noreply.github.com>
Date: Thu, 12 Dec 2024 14:49:01 +0800
Subject: [PATCH 3/3] Fix: [MariaDB] Unable to clean up heartbeat data (#5425)

Co-authored-by: GJS <homelab.api@gmail.com>
Co-authored-by: Frank Elsinga <frank@elsinga.de>
---
 package-lock.json  |  4 ++--
 server/database.js | 12 +++++++-----
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/package-lock.json b/package-lock.json
index 100cdcd88..328b1d287 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
 {
     "name": "uptime-kuma",
-    "version": "2.0.0-dev",
+    "version": "2.0.0-beta.0",
     "lockfileVersion": 3,
     "requires": true,
     "packages": {
         "": {
             "name": "uptime-kuma",
-            "version": "2.0.0-dev",
+            "version": "2.0.0-beta.0",
             "license": "MIT",
             "dependencies": {
                 "@grpc/grpc-js": "~1.8.22",
diff --git a/server/database.js b/server/database.js
index 3b7646de8..0e6a7405d 100644
--- a/server/database.js
+++ b/server/database.js
@@ -892,11 +892,13 @@ class Database {
                 AND important = 0
                 AND time < ${sqlHourOffset}
                 AND id NOT IN (
-                    SELECT id
-                    FROM heartbeat
-                    WHERE monitor_id = ?
-                    ORDER BY time DESC
-                    LIMIT ?
+                    SELECT id FROM ( -- written this way for Maria's support
+                        SELECT id
+                        FROM heartbeat
+                        WHERE monitor_id = ?
+                        ORDER BY time DESC
+                        LIMIT ?
+                    )  AS limited_ids
                 )
             `, [
                 monitor.id,