mirror of
				https://github.com/louislam/uptime-kuma.git
				synced 2025-11-04 13:46:13 +08:00 
			
		
		
		
	Merge pull request from GHSA-88j4-pcx8-q4q3
* WIP, still need to handle npm run reset-password * Implement it for "npm run reset-password" Bug fixes and change along with this commit - Move `ssl`, `hostname`, `port` to ./server/config.js, so `reset-password` is able to read it - Fix: FBSD is missing, no idea who dropped it. - Fix: Frontend code should not require any backend code (./server/config.js), moved "badgeConstants" to the common util (./src/util.ts) and drop vite-common.js * Minor
This commit is contained in:
		@@ -3,7 +3,6 @@ import vue from "@vitejs/plugin-vue";
 | 
				
			|||||||
import { defineConfig } from "vite";
 | 
					import { defineConfig } from "vite";
 | 
				
			||||||
import visualizer from "rollup-plugin-visualizer";
 | 
					import visualizer from "rollup-plugin-visualizer";
 | 
				
			||||||
import viteCompression from "vite-plugin-compression";
 | 
					import viteCompression from "vite-plugin-compression";
 | 
				
			||||||
import commonjs from "vite-plugin-commonjs";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const postCssScss = require("postcss-scss");
 | 
					const postCssScss = require("postcss-scss");
 | 
				
			||||||
const postcssRTLCSS = require("postcss-rtlcss");
 | 
					const postcssRTLCSS = require("postcss-rtlcss");
 | 
				
			||||||
@@ -22,7 +21,6 @@ export default defineConfig({
 | 
				
			|||||||
        "CODESPACE_NAME": JSON.stringify(process.env.CODESPACE_NAME),
 | 
					        "CODESPACE_NAME": JSON.stringify(process.env.CODESPACE_NAME),
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    plugins: [
 | 
					    plugins: [
 | 
				
			||||||
        commonjs(),
 | 
					 | 
				
			||||||
        vue(),
 | 
					        vue(),
 | 
				
			||||||
        legacy({
 | 
					        legacy({
 | 
				
			||||||
            targets: [ "since 2015" ],
 | 
					            targets: [ "since 2015" ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,7 +6,7 @@
 | 
				
			|||||||
 * ⚠️ Deprecated: Changed to healthcheck.go, it will be deleted in the future.
 | 
					 * ⚠️ Deprecated: Changed to healthcheck.go, it will be deleted in the future.
 | 
				
			||||||
 * This script should be run after a period of time (180s), because the server may need some time to prepare.
 | 
					 * This script should be run after a period of time (180s), because the server may need some time to prepare.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
const { FBSD } = require("../server/util-server");
 | 
					const FBSD = /^freebsd/.test(process.platform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
 | 
					process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@ const { R } = require("redbean-node");
 | 
				
			|||||||
const readline = require("readline");
 | 
					const readline = require("readline");
 | 
				
			||||||
const { initJWTSecret } = require("../server/util-server");
 | 
					const { initJWTSecret } = require("../server/util-server");
 | 
				
			||||||
const User = require("../server/model/user");
 | 
					const User = require("../server/model/user");
 | 
				
			||||||
 | 
					const { io } = require("socket.io-client");
 | 
				
			||||||
 | 
					const { localWebSocketURL } = require("../server/config");
 | 
				
			||||||
const args = require("args-parser")(process.argv);
 | 
					const args = require("args-parser")(process.argv);
 | 
				
			||||||
const rl = readline.createInterface({
 | 
					const rl = readline.createInterface({
 | 
				
			||||||
    input: process.stdin,
 | 
					    input: process.stdin,
 | 
				
			||||||
@@ -36,12 +38,16 @@ const main = async () => {
 | 
				
			|||||||
                    // Reset all sessions by reset jwt secret
 | 
					                    // Reset all sessions by reset jwt secret
 | 
				
			||||||
                    await initJWTSecret();
 | 
					                    await initJWTSecret();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    // Disconnect all other socket clients of the user
 | 
				
			||||||
 | 
					                    await disconnectAllSocketClients(user.username, password);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    console.log("Passwords do not match, please try again.");
 | 
					                    console.log("Passwords do not match, please try again.");
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            console.log("Password reset successfully.");
 | 
					            console.log("Password reset successfully.");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
        console.error("Error: " + e.message);
 | 
					        console.error("Error: " + e.message);
 | 
				
			||||||
@@ -66,6 +72,45 @@ function question(question) {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function disconnectAllSocketClients(username, password) {
 | 
				
			||||||
 | 
					    return new Promise((resolve) => {
 | 
				
			||||||
 | 
					        console.log("Connecting to " + localWebSocketURL + " to disconnect all other socket clients");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Disconnect all socket connections
 | 
				
			||||||
 | 
					        const socket = io(localWebSocketURL, {
 | 
				
			||||||
 | 
					            transports: [ "websocket" ],
 | 
				
			||||||
 | 
					            reconnection: false,
 | 
				
			||||||
 | 
					            timeout: 5000,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        socket.on("connect", () => {
 | 
				
			||||||
 | 
					            socket.emit("login", {
 | 
				
			||||||
 | 
					                username,
 | 
				
			||||||
 | 
					                password,
 | 
				
			||||||
 | 
					            }, (res) => {
 | 
				
			||||||
 | 
					                if (res.ok) {
 | 
				
			||||||
 | 
					                    console.log("Logged in.");
 | 
				
			||||||
 | 
					                    socket.emit("disconnectOtherSocketClients");
 | 
				
			||||||
 | 
					                } else {
 | 
				
			||||||
 | 
					                    console.warn("Login failed.");
 | 
				
			||||||
 | 
					                    console.warn("Please restart the server to disconnect all sessions.");
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                socket.close();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        socket.on("connect_error", function () {
 | 
				
			||||||
 | 
					            // The localWebSocketURL is not guaranteed to be working for some complicated Uptime Kuma setup
 | 
				
			||||||
 | 
					            // Ask the user to restart the server manually
 | 
				
			||||||
 | 
					            console.warn("Failed to connect to " + localWebSocketURL);
 | 
				
			||||||
 | 
					            console.warn("Please restart the server to disconnect all sessions manually.");
 | 
				
			||||||
 | 
					            resolve();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					        socket.on("disconnect", () => {
 | 
				
			||||||
 | 
					            resolve();
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (!process.env.TEST_BACKEND) {
 | 
					if (!process.env.TEST_BACKEND) {
 | 
				
			||||||
    main();
 | 
					    main();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -192,7 +192,6 @@
 | 
				
			|||||||
        "typescript": "~4.4.4",
 | 
					        "typescript": "~4.4.4",
 | 
				
			||||||
        "v-pagination-3": "~0.1.7",
 | 
					        "v-pagination-3": "~0.1.7",
 | 
				
			||||||
        "vite": "~4.4.1",
 | 
					        "vite": "~4.4.1",
 | 
				
			||||||
        "vite-plugin-commonjs": "^0.8.0",
 | 
					 | 
				
			||||||
        "vite-plugin-compression": "^0.5.1",
 | 
					        "vite-plugin-compression": "^0.5.1",
 | 
				
			||||||
        "vue": "~3.3.4",
 | 
					        "vue": "~3.3.4",
 | 
				
			||||||
        "vue-chartjs": "~5.2.0",
 | 
					        "vue-chartjs": "~5.2.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,29 +1,42 @@
 | 
				
			|||||||
 | 
					const isFreeBSD = /^freebsd/.test(process.platform);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Interop with browser
 | 
					// Interop with browser
 | 
				
			||||||
const args = (typeof process !== "undefined") ? require("args-parser")(process.argv) : {};
 | 
					const args = (typeof process !== "undefined") ? require("args-parser")(process.argv) : {};
 | 
				
			||||||
const demoMode = args["demo"] || false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const badgeConstants = {
 | 
					// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
 | 
				
			||||||
    naColor: "#999",
 | 
					// Dual-stack support for (::)
 | 
				
			||||||
    defaultUpColor: "#66c20a",
 | 
					// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
 | 
				
			||||||
    defaultWarnColor: "#eed202",
 | 
					let hostEnv = isFreeBSD ? null : process.env.HOST;
 | 
				
			||||||
    defaultDownColor: "#c2290a",
 | 
					const hostname = args.host || process.env.UPTIME_KUMA_HOST || hostEnv;
 | 
				
			||||||
    defaultPendingColor: "#f8a306",
 | 
					
 | 
				
			||||||
    defaultMaintenanceColor: "#1747f5",
 | 
					const port = [ args.port, process.env.UPTIME_KUMA_PORT, process.env.PORT, 3001 ]
 | 
				
			||||||
    defaultPingColor: "blue",  // as defined by badge-maker / shields.io
 | 
					    .map(portValue => parseInt(portValue))
 | 
				
			||||||
    defaultStyle: "flat",
 | 
					    .find(portValue => !isNaN(portValue));
 | 
				
			||||||
    defaultPingValueSuffix: "ms",
 | 
					
 | 
				
			||||||
    defaultPingLabelSuffix: "h",
 | 
					const sslKey = args["ssl-key"] || process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || undefined;
 | 
				
			||||||
    defaultUptimeValueSuffix: "%",
 | 
					const sslCert = args["ssl-cert"] || process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined;
 | 
				
			||||||
    defaultUptimeLabelSuffix: "h",
 | 
					const sslKeyPassphrase = args["ssl-key-passphrase"] || process.env.UPTIME_KUMA_SSL_KEY_PASSPHRASE || process.env.SSL_KEY_PASSPHRASE || undefined;
 | 
				
			||||||
    defaultCertExpValueSuffix: " days",
 | 
					
 | 
				
			||||||
    defaultCertExpLabelSuffix: "h",
 | 
					const isSSL = sslKey && sslCert;
 | 
				
			||||||
    // Values Come From Default Notification Times
 | 
					
 | 
				
			||||||
    defaultCertExpireWarnDays: "14",
 | 
					function getLocalWebSocketURL() {
 | 
				
			||||||
    defaultCertExpireDownDays: "7"
 | 
					    const protocol = isSSL ? "wss" : "ws";
 | 
				
			||||||
};
 | 
					    const host = hostname || "localhost";
 | 
				
			||||||
 | 
					    return `${protocol}://${host}:${port}`;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const localWebSocketURL = getLocalWebSocketURL();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const demoMode = args["demo"] || false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    args,
 | 
					    args,
 | 
				
			||||||
 | 
					    hostname,
 | 
				
			||||||
 | 
					    port,
 | 
				
			||||||
 | 
					    sslKey,
 | 
				
			||||||
 | 
					    sslCert,
 | 
				
			||||||
 | 
					    sslKeyPassphrase,
 | 
				
			||||||
 | 
					    isSSL,
 | 
				
			||||||
 | 
					    localWebSocketURL,
 | 
				
			||||||
    demoMode,
 | 
					    demoMode,
 | 
				
			||||||
    badgeConstants,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,12 +11,11 @@ const { R } = require("redbean-node");
 | 
				
			|||||||
const apicache = require("../modules/apicache");
 | 
					const apicache = require("../modules/apicache");
 | 
				
			||||||
const Monitor = require("../model/monitor");
 | 
					const Monitor = require("../model/monitor");
 | 
				
			||||||
const dayjs = require("dayjs");
 | 
					const dayjs = require("dayjs");
 | 
				
			||||||
const { UP, MAINTENANCE, DOWN, PENDING, flipStatus, log } = require("../../src/util");
 | 
					const { UP, MAINTENANCE, DOWN, PENDING, flipStatus, log, badgeConstants } = require("../../src/util");
 | 
				
			||||||
const StatusPage = require("../model/status_page");
 | 
					const StatusPage = require("../model/status_page");
 | 
				
			||||||
const { UptimeKumaServer } = require("../uptime-kuma-server");
 | 
					const { UptimeKumaServer } = require("../uptime-kuma-server");
 | 
				
			||||||
const { UptimeCacheList } = require("../uptime-cache-list");
 | 
					const { UptimeCacheList } = require("../uptime-cache-list");
 | 
				
			||||||
const { makeBadge } = require("badge-maker");
 | 
					const { makeBadge } = require("badge-maker");
 | 
				
			||||||
const { badgeConstants } = require("../config");
 | 
					 | 
				
			||||||
const { Prometheus } = require("../prometheus");
 | 
					const { Prometheus } = require("../prometheus");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let router = express.Router();
 | 
					let router = express.Router();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ const StatusPage = require("../model/status_page");
 | 
				
			|||||||
const { allowDevAllOrigin, sendHttpError } = require("../util-server");
 | 
					const { allowDevAllOrigin, sendHttpError } = require("../util-server");
 | 
				
			||||||
const { R } = require("redbean-node");
 | 
					const { R } = require("redbean-node");
 | 
				
			||||||
const Monitor = require("../model/monitor");
 | 
					const Monitor = require("../model/monitor");
 | 
				
			||||||
const { badgeConstants } = require("../config");
 | 
					const { badgeConstants } = require("../../src/util");
 | 
				
			||||||
const { makeBadge } = require("badge-maker");
 | 
					const { makeBadge } = require("badge-maker");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let router = express.Router();
 | 
					let router = express.Router();
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,7 @@ const notp = require("notp");
 | 
				
			|||||||
const base32 = require("thirty-two");
 | 
					const base32 = require("thirty-two");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const { UptimeKumaServer } = require("./uptime-kuma-server");
 | 
					const { UptimeKumaServer } = require("./uptime-kuma-server");
 | 
				
			||||||
const server = UptimeKumaServer.getInstance(args);
 | 
					const server = UptimeKumaServer.getInstance();
 | 
				
			||||||
const io = module.exports.io = server.io;
 | 
					const io = module.exports.io = server.io;
 | 
				
			||||||
const app = server.app;
 | 
					const app = server.app;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -91,7 +91,7 @@ const Monitor = require("./model/monitor");
 | 
				
			|||||||
const User = require("./model/user");
 | 
					const User = require("./model/user");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
log.debug("server", "Importing Settings");
 | 
					log.debug("server", "Importing Settings");
 | 
				
			||||||
const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, FBSD, doubleCheckPassword, startE2eTests, shake256, SHAKE256_LENGTH
 | 
					const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, doubleCheckPassword, startE2eTests, shake256, SHAKE256_LENGTH
 | 
				
			||||||
} = require("./util-server");
 | 
					} = require("./util-server");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
log.debug("server", "Importing Notification");
 | 
					log.debug("server", "Importing Notification");
 | 
				
			||||||
@@ -115,19 +115,13 @@ const passwordHash = require("./password-hash");
 | 
				
			|||||||
const checkVersion = require("./check-version");
 | 
					const checkVersion = require("./check-version");
 | 
				
			||||||
log.info("server", "Version: " + checkVersion.version);
 | 
					log.info("server", "Version: " + checkVersion.version);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
 | 
					const hostname = config.hostname;
 | 
				
			||||||
// Dual-stack support for (::)
 | 
					 | 
				
			||||||
// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
 | 
					 | 
				
			||||||
let hostEnv = FBSD ? null : process.env.HOST;
 | 
					 | 
				
			||||||
let hostname = args.host || process.env.UPTIME_KUMA_HOST || hostEnv;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
if (hostname) {
 | 
					if (hostname) {
 | 
				
			||||||
    log.info("server", "Custom hostname: " + hostname);
 | 
					    log.info("server", "Custom hostname: " + hostname);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const port = [ args.port, process.env.UPTIME_KUMA_PORT, process.env.PORT, 3001 ]
 | 
					const port = config.port;
 | 
				
			||||||
    .map(portValue => parseInt(portValue))
 | 
					 | 
				
			||||||
    .find(portValue => !isNaN(portValue));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false;
 | 
					const disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false;
 | 
				
			||||||
const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined;
 | 
					const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined;
 | 
				
			||||||
@@ -1157,6 +1151,8 @@ let needSetup = false;
 | 
				
			|||||||
                let user = await doubleCheckPassword(socket, password.currentPassword);
 | 
					                let user = await doubleCheckPassword(socket, password.currentPassword);
 | 
				
			||||||
                await user.resetPassword(password.newPassword);
 | 
					                await user.resetPassword(password.newPassword);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                server.disconnectAllSocketClient(user.id, socket.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                callback({
 | 
					                callback({
 | 
				
			||||||
                    ok: true,
 | 
					                    ok: true,
 | 
				
			||||||
                    msg: "Password has been updated successfully.",
 | 
					                    msg: "Password has been updated successfully.",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -78,4 +78,14 @@ module.exports.generalSocketHandler = (socket, server) => {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Disconnect all other socket clients of the user
 | 
				
			||||||
 | 
					    socket.on("disconnectOtherSocketClients", async () => {
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            checkLogin(socket);
 | 
				
			||||||
 | 
					            server.disconnectAllSocketClients(socket.userID, socket.id);
 | 
				
			||||||
 | 
					        } catch (e) {
 | 
				
			||||||
 | 
					            log.warn("disconnectAllSocketClients", e.message);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ const { Settings } = require("./settings");
 | 
				
			|||||||
const dayjs = require("dayjs");
 | 
					const dayjs = require("dayjs");
 | 
				
			||||||
const childProcessAsync = require("promisify-child-process");
 | 
					const childProcessAsync = require("promisify-child-process");
 | 
				
			||||||
const path = require("path");
 | 
					const path = require("path");
 | 
				
			||||||
 | 
					const { isSSL, sslKey, sslCert, sslKeyPassphrase } = require("./config");
 | 
				
			||||||
// DO NOT IMPORT HERE IF THE MODULES USED `UptimeKumaServer.getInstance()`, put at the bottom of this file instead.
 | 
					// DO NOT IMPORT HERE IF THE MODULES USED `UptimeKumaServer.getInstance()`, put at the bottom of this file instead.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@@ -62,22 +63,17 @@ class UptimeKumaServer {
 | 
				
			|||||||
     */
 | 
					     */
 | 
				
			||||||
    jwtSecret = null;
 | 
					    jwtSecret = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static getInstance(args) {
 | 
					    static getInstance() {
 | 
				
			||||||
        if (UptimeKumaServer.instance == null) {
 | 
					        if (UptimeKumaServer.instance == null) {
 | 
				
			||||||
            UptimeKumaServer.instance = new UptimeKumaServer(args);
 | 
					            UptimeKumaServer.instance = new UptimeKumaServer();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return UptimeKumaServer.instance;
 | 
					        return UptimeKumaServer.instance;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(args) {
 | 
					    constructor() {
 | 
				
			||||||
        // SSL
 | 
					 | 
				
			||||||
        const sslKey = args["ssl-key"] || process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || undefined;
 | 
					 | 
				
			||||||
        const sslCert = args["ssl-cert"] || process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined;
 | 
					 | 
				
			||||||
        const sslKeyPassphrase = args["ssl-key-passphrase"] || process.env.UPTIME_KUMA_SSL_KEY_PASSPHRASE || process.env.SSL_KEY_PASSPHRASE || undefined;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        log.info("server", "Creating express and socket.io instance");
 | 
					        log.info("server", "Creating express and socket.io instance");
 | 
				
			||||||
        this.app = express();
 | 
					        this.app = express();
 | 
				
			||||||
        if (sslKey && sslCert) {
 | 
					        if (isSSL) {
 | 
				
			||||||
            log.info("server", "Server Type: HTTPS");
 | 
					            log.info("server", "Server Type: HTTPS");
 | 
				
			||||||
            this.httpServer = https.createServer({
 | 
					            this.httpServer = https.createServer({
 | 
				
			||||||
                key: fs.readFileSync(sslKey),
 | 
					                key: fs.readFileSync(sslKey),
 | 
				
			||||||
@@ -422,6 +418,25 @@ class UptimeKumaServer {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Force connected sockets of a user to refresh and disconnect.
 | 
				
			||||||
 | 
					     * Used for resetting password.
 | 
				
			||||||
 | 
					     * @param {string} userID
 | 
				
			||||||
 | 
					     * @param {string?} currentSocketID
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    disconnectAllSocketClients(userID, currentSocketID = undefined) {
 | 
				
			||||||
 | 
					        for (const socket of this.io.sockets.sockets.values()) {
 | 
				
			||||||
 | 
					            if (socket.userID === userID && socket.id !== currentSocketID) {
 | 
				
			||||||
 | 
					                try {
 | 
				
			||||||
 | 
					                    socket.emit("refresh");
 | 
				
			||||||
 | 
					                    socket.disconnect();
 | 
				
			||||||
 | 
					                } catch (e) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
const tcpp = require("tcp-ping");
 | 
					const tcpp = require("tcp-ping");
 | 
				
			||||||
const ping = require("@louislam/ping");
 | 
					const ping = require("@louislam/ping");
 | 
				
			||||||
const { R } = require("redbean-node");
 | 
					const { R } = require("redbean-node");
 | 
				
			||||||
const { log, genSecret } = require("../src/util");
 | 
					const { log, genSecret, badgeConstants } = require("../src/util");
 | 
				
			||||||
const passwordHash = require("./password-hash");
 | 
					const passwordHash = require("./password-hash");
 | 
				
			||||||
const { Resolver } = require("dns");
 | 
					const { Resolver } = require("dns");
 | 
				
			||||||
const childProcess = require("child_process");
 | 
					const childProcess = require("child_process");
 | 
				
			||||||
@@ -9,7 +9,6 @@ const iconv = require("iconv-lite");
 | 
				
			|||||||
const chardet = require("chardet");
 | 
					const chardet = require("chardet");
 | 
				
			||||||
const mqtt = require("mqtt");
 | 
					const mqtt = require("mqtt");
 | 
				
			||||||
const chroma = require("chroma-js");
 | 
					const chroma = require("chroma-js");
 | 
				
			||||||
const { badgeConstants } = require("./config");
 | 
					 | 
				
			||||||
const mssql = require("mssql");
 | 
					const mssql = require("mssql");
 | 
				
			||||||
const { Client } = require("pg");
 | 
					const { Client } = require("pg");
 | 
				
			||||||
const postgresConParse = require("pg-connection-string").parse;
 | 
					const postgresConParse = require("pg-connection-string").parse;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -135,7 +135,7 @@
 | 
				
			|||||||
<script lang="ts">
 | 
					<script lang="ts">
 | 
				
			||||||
import { Modal } from "bootstrap";
 | 
					import { Modal } from "bootstrap";
 | 
				
			||||||
import CopyableInput from "./CopyableInput.vue";
 | 
					import CopyableInput from "./CopyableInput.vue";
 | 
				
			||||||
import { default as serverConfig } from "../../server/config.js";
 | 
					import { badgeConstants } from "../util.ts";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
    components: {
 | 
					    components: {
 | 
				
			||||||
@@ -230,7 +230,7 @@ export default {
 | 
				
			|||||||
                    "labelColor",
 | 
					                    "labelColor",
 | 
				
			||||||
                ],
 | 
					                ],
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            badgeConstants: serverConfig.badgeConstants,
 | 
					            badgeConstants,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -288,6 +288,10 @@ export default {
 | 
				
			|||||||
            socket.on("initServerTimezone", () => {
 | 
					            socket.on("initServerTimezone", () => {
 | 
				
			||||||
                socket.emit("initServerTimezone", dayjs.tz.guess());
 | 
					                socket.emit("initServerTimezone", dayjs.tz.guess());
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            socket.on("refresh", () => {
 | 
				
			||||||
 | 
					                location.reload();
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /**
 | 
					        /**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -848,9 +848,8 @@ import NotificationDialog from "../components/NotificationDialog.vue";
 | 
				
			|||||||
import DockerHostDialog from "../components/DockerHostDialog.vue";
 | 
					import DockerHostDialog from "../components/DockerHostDialog.vue";
 | 
				
			||||||
import ProxyDialog from "../components/ProxyDialog.vue";
 | 
					import ProxyDialog from "../components/ProxyDialog.vue";
 | 
				
			||||||
import TagsManager from "../components/TagsManager.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, sleep } from "../util.ts";
 | 
				
			||||||
import { hostNameRegexPattern } from "../util-frontend";
 | 
					import { hostNameRegexPattern } from "../util-frontend";
 | 
				
			||||||
import { sleep } from "../util";
 | 
					 | 
				
			||||||
import HiddenInput from "../components/HiddenInput.vue";
 | 
					import HiddenInput from "../components/HiddenInput.vue";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const toast = useToast();
 | 
					const toast = useToast();
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								src/util.js
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								src/util.js
									
									
									
									
									
								
							@@ -7,7 +7,7 @@
 | 
				
			|||||||
// Backend uses the compiled file util.js
 | 
					// Backend uses the compiled file util.js
 | 
				
			||||||
// Frontend uses util.ts
 | 
					// Frontend uses util.ts
 | 
				
			||||||
Object.defineProperty(exports, "__esModule", { value: true });
 | 
					Object.defineProperty(exports, "__esModule", { value: true });
 | 
				
			||||||
exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
 | 
					exports.localToUTC = exports.utcToLocal = exports.utcToISODateTime = exports.isoToUTCDateTime = exports.parseTimeFromTimeObject = exports.parseTimeObject = exports.getMaintenanceRelativeURL = exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.badgeConstants = exports.MIN_INTERVAL_SECOND = exports.MAX_INTERVAL_SECOND = exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = exports.SQL_DATETIME_FORMAT = exports.SQL_DATE_FORMAT = exports.STATUS_PAGE_MAINTENANCE = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.MAINTENANCE = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
 | 
				
			||||||
const dayjs = require("dayjs");
 | 
					const dayjs = require("dayjs");
 | 
				
			||||||
exports.isDev = process.env.NODE_ENV === "development";
 | 
					exports.isDev = process.env.NODE_ENV === "development";
 | 
				
			||||||
exports.appName = "Uptime Kuma";
 | 
					exports.appName = "Uptime Kuma";
 | 
				
			||||||
@@ -24,6 +24,25 @@ exports.SQL_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
 | 
				
			|||||||
exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
 | 
					exports.SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
 | 
				
			||||||
exports.MAX_INTERVAL_SECOND = 2073600; // 24 days
 | 
					exports.MAX_INTERVAL_SECOND = 2073600; // 24 days
 | 
				
			||||||
exports.MIN_INTERVAL_SECOND = 20; // 20 seconds
 | 
					exports.MIN_INTERVAL_SECOND = 20; // 20 seconds
 | 
				
			||||||
 | 
					exports.badgeConstants = {
 | 
				
			||||||
 | 
					    naColor: "#999",
 | 
				
			||||||
 | 
					    defaultUpColor: "#66c20a",
 | 
				
			||||||
 | 
					    defaultWarnColor: "#eed202",
 | 
				
			||||||
 | 
					    defaultDownColor: "#c2290a",
 | 
				
			||||||
 | 
					    defaultPendingColor: "#f8a306",
 | 
				
			||||||
 | 
					    defaultMaintenanceColor: "#1747f5",
 | 
				
			||||||
 | 
					    defaultPingColor: "blue",
 | 
				
			||||||
 | 
					    defaultStyle: "flat",
 | 
				
			||||||
 | 
					    defaultPingValueSuffix: "ms",
 | 
				
			||||||
 | 
					    defaultPingLabelSuffix: "h",
 | 
				
			||||||
 | 
					    defaultUptimeValueSuffix: "%",
 | 
				
			||||||
 | 
					    defaultUptimeLabelSuffix: "h",
 | 
				
			||||||
 | 
					    defaultCertExpValueSuffix: " days",
 | 
				
			||||||
 | 
					    defaultCertExpLabelSuffix: "h",
 | 
				
			||||||
 | 
					    // Values Come From Default Notification Times
 | 
				
			||||||
 | 
					    defaultCertExpireWarnDays: "14",
 | 
				
			||||||
 | 
					    defaultCertExpireDownDays: "7"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
/** Flip the status of s */
 | 
					/** Flip the status of s */
 | 
				
			||||||
function flipStatus(s) {
 | 
					function flipStatus(s) {
 | 
				
			||||||
    if (s === exports.UP) {
 | 
					    if (s === exports.UP) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										20
									
								
								src/util.ts
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								src/util.ts
									
									
									
									
									
								
							@@ -29,6 +29,26 @@ export const SQL_DATETIME_FORMAT_WITHOUT_SECOND = "YYYY-MM-DD HH:mm";
 | 
				
			|||||||
export const MAX_INTERVAL_SECOND = 2073600; // 24 days
 | 
					export const MAX_INTERVAL_SECOND = 2073600; // 24 days
 | 
				
			||||||
export const MIN_INTERVAL_SECOND = 20; // 20 seconds
 | 
					export const MIN_INTERVAL_SECOND = 20; // 20 seconds
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export const badgeConstants = {
 | 
				
			||||||
 | 
					    naColor: "#999",
 | 
				
			||||||
 | 
					    defaultUpColor: "#66c20a",
 | 
				
			||||||
 | 
					    defaultWarnColor: "#eed202",
 | 
				
			||||||
 | 
					    defaultDownColor: "#c2290a",
 | 
				
			||||||
 | 
					    defaultPendingColor: "#f8a306",
 | 
				
			||||||
 | 
					    defaultMaintenanceColor: "#1747f5",
 | 
				
			||||||
 | 
					    defaultPingColor: "blue",  // as defined by badge-maker / shields.io
 | 
				
			||||||
 | 
					    defaultStyle: "flat",
 | 
				
			||||||
 | 
					    defaultPingValueSuffix: "ms",
 | 
				
			||||||
 | 
					    defaultPingLabelSuffix: "h",
 | 
				
			||||||
 | 
					    defaultUptimeValueSuffix: "%",
 | 
				
			||||||
 | 
					    defaultUptimeLabelSuffix: "h",
 | 
				
			||||||
 | 
					    defaultCertExpValueSuffix: " days",
 | 
				
			||||||
 | 
					    defaultCertExpLabelSuffix: "h",
 | 
				
			||||||
 | 
					    // Values Come From Default Notification Times
 | 
				
			||||||
 | 
					    defaultCertExpireWarnDays: "14",
 | 
				
			||||||
 | 
					    defaultCertExpireDownDays: "7"
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Flip the status of s */
 | 
					/** Flip the status of s */
 | 
				
			||||||
export function flipStatus(s: number) {
 | 
					export function flipStatus(s: number) {
 | 
				
			||||||
    if (s === UP) {
 | 
					    if (s === UP) {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user