From 3ac752246d6d097ff980631d524d706676862282 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Wed, 20 Jul 2022 00:11:15 +0200
Subject: [PATCH 01/10] Add status page summary API

---
 server/model/monitor.js              |  8 ++++++-
 server/model/status_page.js          |  5 ++--
 server/routers/status-page-router.js | 35 +++++++++++++++++++++++++++-
 3 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/server/model/monitor.js b/server/model/monitor.js
index cb044f0f1..5b098356b 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -31,7 +31,7 @@ class Monitor extends BeanModel {
      * Only show necessary data to public
      * @returns {Object}
      */
-    async toPublicJSON(showTags = false) {
+    async toPublicJSON(showTags = false, includeStatus = false) {
         let obj = {
             id: this.id,
             name: this.name,
@@ -45,6 +45,12 @@ class Monitor extends BeanModel {
         if (showTags) {
             obj.tags = await this.getTags();
         }
+
+        if (includeStatus) {
+            const heartbeat = await Monitor.getPreviousHeartbeat(this.id);
+            obj.status = heartbeat.status === 1 ? "up" : "down";
+        }
+
         return obj;
     }
 
diff --git a/server/model/status_page.js b/server/model/status_page.js
index 82d184bfd..5ac398c39 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -72,8 +72,9 @@ class StatusPage extends BeanModel {
     /**
      * Get all status page data in one call
      * @param {StatusPage} statusPage
+     * @param {boolean} includeStatus whether each monitor should include the status of the monitor ("up" or "down")
      */
-    static async getStatusPageData(statusPage) {
+    static async getStatusPageData(statusPage, includeStatus = false) {
         // Incident
         let incident = await R.findOne("incident", " pin = 1 AND active = 1 AND status_page_id = ? ", [
             statusPage.id,
@@ -92,7 +93,7 @@ class StatusPage extends BeanModel {
         ]);
 
         for (let groupBean of list) {
-            let monitorGroup = await groupBean.toPublicJSON(showTags);
+            let monitorGroup = await groupBean.toPublicJSON(showTags, includeStatus);
             publicGroupList.push(monitorGroup);
         }
 
diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js
index de075db8d..95bd9eace 100644
--- a/server/routers/status-page-router.js
+++ b/server/routers/status-page-router.js
@@ -2,7 +2,7 @@ let express = require("express");
 const apicache = require("../modules/apicache");
 const { UptimeKumaServer } = require("../uptime-kuma-server");
 const StatusPage = require("../model/status_page");
-const { allowDevAllOrigin, send403 } = require("../util-server");
+const { allowAllOrigin, allowDevAllOrigin, send403 } = require("../util-server");
 const { R } = require("redbean-node");
 const Monitor = require("../model/monitor");
 
@@ -26,6 +26,39 @@ router.get("/status-page", cache("5 minutes"), async (request, response) => {
     await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
 });
 
+// Status page config, incident, monitor list with status ("up" or "down")
+router.get("/api/status-page/:slug/summary", cache("5 minutes"), async (request, response) => {
+    allowAllOrigin(response);
+    let slug = request.params.slug;
+
+    try {
+        // Get Status Page
+        let statusPage = await R.findOne("status_page", " slug = ? ", [
+            slug
+        ]);
+
+        if (!statusPage) {
+            return null;
+        }
+
+        let statusPageData = await StatusPage.getStatusPageData(statusPage, true);
+
+        if (!statusPageData) {
+            response.statusCode = 404;
+            response.json({
+                msg: "Not Found"
+            });
+            return;
+        }
+
+        // Response
+        response.json(statusPageData);
+
+    } catch (error) {
+        send403(response, error.message);
+    }
+});
+
 // Status page config, incident, monitor list
 router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
     allowDevAllOrigin(response);

From 80e7400185e88101e198533dde132a23fb9b8cae Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Tue, 26 Jul 2022 13:47:23 +0200
Subject: [PATCH 02/10] Updates

---
 server/model/group.js                |  4 ++--
 server/model/status_page.js          | 12 ++++++++++--
 server/routers/status-page-router.js |  2 +-
 3 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/server/model/group.js b/server/model/group.js
index 3f3b3b129..32e3cc397 100644
--- a/server/model/group.js
+++ b/server/model/group.js
@@ -9,12 +9,12 @@ class Group extends BeanModel {
      * @param {boolean} [showTags=false] Should the JSON include monitor tags
      * @returns {Object}
      */
-    async toPublicJSON(showTags = false) {
+    async toPublicJSON(showTags = false, showStatus = false) {
         let monitorBeanList = await this.getMonitorList();
         let monitorList = [];
 
         for (let bean of monitorBeanList) {
-            monitorList.push(await bean.toPublicJSON(showTags));
+            monitorList.push(await bean.toPublicJSON(showTags, showStatus));
         }
 
         return {
diff --git a/server/model/status_page.js b/server/model/status_page.js
index 5ac398c39..b9e661d3d 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -73,8 +73,9 @@ class StatusPage extends BeanModel {
      * Get all status page data in one call
      * @param {StatusPage} statusPage
      * @param {boolean} includeStatus whether each monitor should include the status of the monitor ("up" or "down")
+     * @param {boolean} includeConfig whether the config for the status paghe should be included in the returned JSON
      */
-    static async getStatusPageData(statusPage, includeStatus = false) {
+    static async getStatusPageData(statusPage, includeStatus = false, includeConfig = true) {
         // Incident
         let incident = await R.findOne("incident", " pin = 1 AND active = 1 AND status_page_id = ? ", [
             statusPage.id,
@@ -97,9 +98,16 @@ class StatusPage extends BeanModel {
             publicGroupList.push(monitorGroup);
         }
 
+        let config = {};
+        if (includeConfig) {
+            config = {
+                config: await statusPage.toPublicJSON()
+            }
+        }
+
         // Response
         return {
-            config: await statusPage.toPublicJSON(),
+            ...config,
             incident,
             publicGroupList
         };
diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js
index 95bd9eace..5a24962fe 100644
--- a/server/routers/status-page-router.js
+++ b/server/routers/status-page-router.js
@@ -41,7 +41,7 @@ router.get("/api/status-page/:slug/summary", cache("5 minutes"), async (request,
             return null;
         }
 
-        let statusPageData = await StatusPage.getStatusPageData(statusPage, true);
+        let statusPageData = await StatusPage.getStatusPageData(statusPage, true, false);
 
         if (!statusPageData) {
             response.statusCode = 404;

From 2781ff566b1160946febc360178ed7b673597ef4 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Thu, 28 Jul 2022 12:44:06 +0200
Subject: [PATCH 03/10] Make linter happy

---
 server/model/status_page.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/server/model/status_page.js b/server/model/status_page.js
index b9e661d3d..870eb9b4f 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -102,7 +102,7 @@ class StatusPage extends BeanModel {
         if (includeConfig) {
             config = {
                 config: await statusPage.toPublicJSON()
-            }
+            };
         }
 
         // Response

From 1630c01fd9038a5970dcb358958494ea170e2d38 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Thu, 5 Jan 2023 15:56:08 +0100
Subject: [PATCH 04/10] chore: add support for new monitor states

---
 server/model/monitor.js | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/server/model/monitor.js b/server/model/monitor.js
index 473c39d50..763763fed 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -26,6 +26,16 @@ const { UptimeCacheList } = require("../uptime-cache-list");
  */
 class Monitor extends BeanModel {
 
+    statusToKey(status) {
+        switch (status) {
+            case 0: return "down";
+            case 1: return "up";
+            case 2: return "pending";
+            case 4: return "maintenance";
+            default: return "unknown";
+        }
+    }
+
     /**
      * Return an object that ready to parse to JSON for public
      * Only show necessary data to public
@@ -49,7 +59,7 @@ class Monitor extends BeanModel {
 
         if (includeStatus) {
             const heartbeat = await Monitor.getPreviousHeartbeat(this.id);
-            obj.status = heartbeat.status === 1 ? "up" : "down";
+            obj.status = this.statusToKey(heartbeat.status);
         }
 
         return obj;

From f33d09918d9c4f0888b12c54b277c7e7a70a1463 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gerogerke.de>
Date: Tue, 10 Jan 2023 10:41:04 +0100
Subject: [PATCH 05/10] Update server/model/group.js

Co-authored-by: Matthew Nickson <mnickson@sidingsmedia.com>
---
 server/model/group.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/server/model/group.js b/server/model/group.js
index 32e3cc397..596d2b0e9 100644
--- a/server/model/group.js
+++ b/server/model/group.js
@@ -7,6 +7,7 @@ class Group extends BeanModel {
      * Return an object that ready to parse to JSON for public
      * Only show necessary data to public
      * @param {boolean} [showTags=false] Should the JSON include monitor tags
+     * @param {boolean} [showStatus = false] Should the JSON include the status
      * @returns {Object}
      */
     async toPublicJSON(showTags = false, showStatus = false) {

From 3dbc32b225aaf64f843680bbf83486e952a85bc8 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gerogerke.de>
Date: Tue, 10 Jan 2023 10:41:18 +0100
Subject: [PATCH 06/10] Update server/model/monitor.js

Co-authored-by: Matthew Nickson <mnickson@sidingsmedia.com>
---
 server/model/monitor.js | 1 +
 1 file changed, 1 insertion(+)

diff --git a/server/model/monitor.js b/server/model/monitor.js
index 763763fed..c130dce96 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -39,6 +39,7 @@ class Monitor extends BeanModel {
     /**
      * Return an object that ready to parse to JSON for public
      * Only show necessary data to public
+     * @param {boolean} [includeStatus = false] Should the JSON include the status
      * @returns {Object}
      */
     async toPublicJSON(showTags = false, includeStatus = false) {

From 1b5ea7d44ed02197036c6410d638de88164cb86a Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gerogerke.de>
Date: Tue, 10 Jan 2023 10:41:25 +0100
Subject: [PATCH 07/10] Update server/model/status_page.js

Co-authored-by: Matthew Nickson <mnickson@sidingsmedia.com>
---
 server/model/status_page.js | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/server/model/status_page.js b/server/model/status_page.js
index 09838629c..6fce5415f 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -80,8 +80,8 @@ class StatusPage extends BeanModel {
     /**
      * Get all status page data in one call
      * @param {StatusPage} statusPage
-     * @param {boolean} includeStatus whether each monitor should include the status of the monitor ("up" or "down")
-     * @param {boolean} includeConfig whether the config for the status paghe should be included in the returned JSON
+     * @param {boolean} [includeStatus = false] whether each monitor should include the status of the monitor ("up" or "down")
+     * @param {boolean} [includeConfig = true] whether the config for the status paghe should be included in the returned JSON
      */
     static async getStatusPageData(statusPage, includeStatus = false, includeConfig = true) {
         // Incident

From 98d8598052813d2430dda472d8a5f1cd49890ece Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Tue, 10 Jan 2023 10:47:24 +0100
Subject: [PATCH 08/10] chore: add jsdocs for missing functions

---
 server/model/monitor.js | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/server/model/monitor.js b/server/model/monitor.js
index c130dce96..f773bba82 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -26,6 +26,10 @@ const { UptimeCacheList } = require("../uptime-cache-list");
  */
 class Monitor extends BeanModel {
 
+    /**
+     * Formats the status code to a human readable form
+     * @returns {string} a human readable string that corresponds to the status code
+     */
     statusToKey(status) {
         switch (status) {
             case 0: return "down";
@@ -39,10 +43,10 @@ class Monitor extends BeanModel {
     /**
      * Return an object that ready to parse to JSON for public
      * Only show necessary data to public
-     * @param {boolean} [includeStatus = false] Should the JSON include the status
+     * @param {boolean} [showStatus = false] Should the JSON show the status
      * @returns {Object}
      */
-    async toPublicJSON(showTags = false, includeStatus = false) {
+    async toPublicJSON(showTags = false, showStatus = false) {
         let obj = {
             id: this.id,
             name: this.name,
@@ -58,7 +62,7 @@ class Monitor extends BeanModel {
             obj.tags = await this.getTags();
         }
 
-        if (includeStatus) {
+        if (showStatus) {
             const heartbeat = await Monitor.getPreviousHeartbeat(this.id);
             obj.status = this.statusToKey(heartbeat.status);
         }

From f171e101fdd7b45ac435d5840c2bf5294bf05aab Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Sat, 23 Nov 2024 16:17:57 +0100
Subject: [PATCH 09/10] post-merge adaptations

---
 server/model/status_page.js          | 4 ++--
 server/routers/status-page-router.js | 2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/server/model/status_page.js b/server/model/status_page.js
index 82354be22..03591bd01 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -259,7 +259,7 @@ class StatusPage extends BeanModel {
      * Get all status page data in one call
      * @param {StatusPage} statusPage
      * @param {boolean} [includeStatus = false] whether each monitor should include the status of the monitor ("up" or "down")
-     * @param {boolean} [includeConfig = true] whether the config for the status paghe should be included in the returned JSON
+     * @param {boolean} [includeConfig = true] whether the config for the status page should be included in the returned JSON
      */
     static async getStatusPageData(statusPage, includeStatus = false, includeConfig = true) {
         // Incident
@@ -282,7 +282,7 @@ class StatusPage extends BeanModel {
         ]);
 
         for (let groupBean of list) {
-            let monitorGroup = await groupBean.toPublicJSON(showTags, includeStatus);
+            let monitorGroup = await groupBean.toPublicJSON(showTags, false, includeStatus);
             publicGroupList.push(monitorGroup);
         }
 
diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js
index 6a14186bc..60c5af633 100644
--- a/server/routers/status-page-router.js
+++ b/server/routers/status-page-router.js
@@ -2,7 +2,7 @@ let express = require("express");
 const apicache = require("../modules/apicache");
 const { UptimeKumaServer } = require("../uptime-kuma-server");
 const StatusPage = require("../model/status_page");
-const { allowDevAllOrigin, sendHttpError } = require("../util-server");
+const { allowAllOrigin, allowDevAllOrigin, sendHttpError } = require("../util-server");
 const { R } = require("redbean-node");
 const { badgeConstants } = require("../../src/util");
 const { makeBadge } = require("badge-maker");

From a8c30f5ab8928d687355568fcf0c2ee775c1c042 Mon Sep 17 00:00:00 2001
From: Gero Gerke <hello@gero.dev>
Date: Sat, 23 Nov 2024 16:28:01 +0100
Subject: [PATCH 10/10] fix lint errors

---
 server/model/group.js       | 8 +++++---
 server/model/monitor.js     | 4 ++--
 server/model/status_page.js | 7 ++++---
 3 files changed, 11 insertions(+), 8 deletions(-)

diff --git a/server/model/group.js b/server/model/group.js
index 9dd896e2c..87c3a59b8 100644
--- a/server/model/group.js
+++ b/server/model/group.js
@@ -6,9 +6,11 @@ class Group extends BeanModel {
     /**
      * Return an object that ready to parse to JSON for public
      * Only show necessary data to public
-     * @param {boolean} [showTags=false] Should the JSON include monitor tags
-     * @param {boolean} [showStatus = false] Should the JSON include the status
-     * @returns {Object}
+     * @param {boolean} showTags Should the JSON include monitor tags
+     * @param {boolean} certExpiry Should JSON include info about
+     * certificate expiry?
+     * @param {boolean} showStatus Should the JSON include the status
+     * @returns {Promise<object>} Object ready to parse
      */
     async toPublicJSON(showTags = false, certExpiry = false, showStatus = false) {
         let monitorBeanList = await this.getMonitorList();
diff --git a/server/model/monitor.js b/server/model/monitor.js
index 0abb6e0a9..dd936478c 100644
--- a/server/model/monitor.js
+++ b/server/model/monitor.js
@@ -37,8 +37,8 @@ const rootCertificates = rootCertificatesFingerprints();
 class Monitor extends BeanModel {
 
     /**
-<<<<<<< HEAD
      * Formats the status code to a human readable form
+     * @param {number} status the internal status code of the monitor
      * @returns {string} a human readable string that corresponds to the status code
      */
     statusToKey(status) {
@@ -57,7 +57,7 @@ class Monitor extends BeanModel {
      * @param {boolean} showTags Include tags in JSON
      * @param {boolean} certExpiry Include certificate expiry info in
      * JSON
-     * @param {boolean} [showStatus = false] Should the JSON show the status
+     * @param {boolean} showStatus Should the JSON show the status
      * @returns {Promise<object>} Object ready to parse
      */
     async toPublicJSON(showTags = false, certExpiry = false, showStatus = false) {
diff --git a/server/model/status_page.js b/server/model/status_page.js
index 03591bd01..c98774176 100644
--- a/server/model/status_page.js
+++ b/server/model/status_page.js
@@ -257,9 +257,10 @@ class StatusPage extends BeanModel {
 
     /**
      * Get all status page data in one call
-     * @param {StatusPage} statusPage
-     * @param {boolean} [includeStatus = false] whether each monitor should include the status of the monitor ("up" or "down")
-     * @param {boolean} [includeConfig = true] whether the config for the status page should be included in the returned JSON
+     * @param {StatusPage} statusPage the status page to return the data for
+     * @param {boolean} includeStatus whether each monitor should include the status of the monitor ("up" or "down")
+     * @param {boolean} includeConfig whether the config for the status page should be included in the returned JSON
+     * @returns {object} the status page data object
      */
     static async getStatusPageData(statusPage, includeStatus = false, includeConfig = true) {
         // Incident