mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-07-21 14:08:53 -04:00
Merge remote-tracking branch 'origin/master' into 2.0.X
# Conflicts: # docker/alpine-base.dockerfile # docker/debian-base.dockerfile # docker/dockerfile # package.json # server/database.js # server/jobs/util-worker.js # server/model/maintenance.js # server/model/monitor.js # server/routers/api-router.js # server/server.js # server/uptime-kuma-server.js
This commit is contained in:
commit
16a1a66e09
185 changed files with 17203 additions and 18978 deletions
|
@ -19,6 +19,11 @@ const nodeVersion = parseInt(process.versions.node.split(".")[0]);
|
|||
const requiredVersion = 14;
|
||||
console.log(`Your Node.js version: ${nodeVersion}`);
|
||||
|
||||
// See more: https://github.com/louislam/uptime-kuma/issues/3138
|
||||
if (nodeVersion >= 20) {
|
||||
console.warn("\x1b[31m%s\x1b[0m", "Warning: Uptime Kuma is currently not stable on Node.js >= 20, please use Node.js 18.");
|
||||
}
|
||||
|
||||
if (nodeVersion < requiredVersion) {
|
||||
console.error(`Error: Your Node.js version is not supported, please upgrade to Node.js >= ${requiredVersion}.`);
|
||||
process.exit(-1);
|
||||
|
@ -87,7 +92,7 @@ log.debug("server", "Importing Background Jobs");
|
|||
const { initBackgroundJobs, stopBackgroundJobs } = require("./jobs");
|
||||
const { loginRateLimiter, twoFaRateLimiter } = require("./rate-limiter");
|
||||
|
||||
const { basicAuth } = require("./auth");
|
||||
const { apiAuth } = require("./auth");
|
||||
const { login } = require("./auth");
|
||||
const passwordHash = require("./password-hash");
|
||||
|
||||
|
@ -129,7 +134,7 @@ if (config.demoMode) {
|
|||
}
|
||||
|
||||
// Must be after io instantiation
|
||||
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList } = require("./client");
|
||||
const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client");
|
||||
const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler");
|
||||
const databaseSocketHandler = require("./socket-handlers/database-socket-handler");
|
||||
const TwoFA = require("./2fa");
|
||||
|
@ -138,10 +143,13 @@ const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudfl
|
|||
const { proxySocketHandler } = require("./socket-handlers/proxy-socket-handler");
|
||||
const { dockerSocketHandler } = require("./socket-handlers/docker-socket-handler");
|
||||
const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-socket-handler");
|
||||
const { apiKeySocketHandler } = require("./socket-handlers/api-key-socket-handler");
|
||||
const { generalSocketHandler } = require("./socket-handlers/general-socket-handler");
|
||||
const { Settings } = require("./settings");
|
||||
const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent");
|
||||
const { pluginsHandler } = require("./socket-handlers/plugins-handler");
|
||||
const apicache = require("./modules/apicache");
|
||||
const { resetChrome } = require("./monitor-types/real-browser-monitor-type");
|
||||
const { EmbeddedMariaDB } = require("./embedded-mariadb");
|
||||
const { SetupDatabase } = require("./setup-database");
|
||||
|
||||
|
@ -156,12 +164,6 @@ app.use(function (req, res, next) {
|
|||
next();
|
||||
});
|
||||
|
||||
/**
|
||||
* Use for decode the auth object
|
||||
* @type {null}
|
||||
*/
|
||||
let jwtSecret = null;
|
||||
|
||||
/**
|
||||
* Show Setup Page
|
||||
* @type {boolean}
|
||||
|
@ -248,7 +250,7 @@ let needSetup = false;
|
|||
|
||||
// Prometheus API metrics /metrics
|
||||
// With Basic Auth using the first user's username/password
|
||||
app.get("/metrics", basicAuth, prometheusAPIMetrics());
|
||||
app.get("/metrics", apiAuth, prometheusAPIMetrics());
|
||||
|
||||
app.use("/", expressStaticGzip("dist", {
|
||||
enableBrotli: true,
|
||||
|
@ -298,7 +300,7 @@ let needSetup = false;
|
|||
log.info("auth", `Login by token. IP=${clientIP}`);
|
||||
|
||||
try {
|
||||
let decoded = jwt.verify(token, jwtSecret);
|
||||
let decoded = jwt.verify(token, server.jwtSecret);
|
||||
|
||||
log.info("auth", "Username from JWT: " + decoded.username);
|
||||
|
||||
|
@ -369,7 +371,7 @@ let needSetup = false;
|
|||
ok: true,
|
||||
token: jwt.sign({
|
||||
username: data.username,
|
||||
}, jwtSecret),
|
||||
}, server.jwtSecret),
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -399,7 +401,7 @@ let needSetup = false;
|
|||
ok: true,
|
||||
token: jwt.sign({
|
||||
username: data.username,
|
||||
}, jwtSecret),
|
||||
}, server.jwtSecret),
|
||||
});
|
||||
} else {
|
||||
|
||||
|
@ -688,6 +690,7 @@ let needSetup = false;
|
|||
// Edit a monitor
|
||||
socket.on("editMonitor", async (monitor, callback) => {
|
||||
try {
|
||||
let removeGroupChildren = false;
|
||||
checkLogin(socket);
|
||||
|
||||
let bean = await R.findOne("monitor", " id = ? ", [ monitor.id ]);
|
||||
|
@ -696,10 +699,22 @@ let needSetup = false;
|
|||
throw new Error("Permission denied.");
|
||||
}
|
||||
|
||||
// Reset Prometheus labels
|
||||
server.monitorList[monitor.id]?.prometheus()?.remove();
|
||||
// Check if Parent is Descendant (would cause endless loop)
|
||||
if (monitor.parent !== null) {
|
||||
const childIDs = await Monitor.getAllChildrenIDs(monitor.id);
|
||||
if (childIDs.includes(monitor.parent)) {
|
||||
throw new Error("Invalid Monitor Group");
|
||||
}
|
||||
}
|
||||
|
||||
// Remove children if monitor type has changed (from group to non-group)
|
||||
if (bean.type === "group" && monitor.type !== bean.type) {
|
||||
removeGroupChildren = true;
|
||||
}
|
||||
|
||||
bean.name = monitor.name;
|
||||
bean.description = monitor.description;
|
||||
bean.parent = monitor.parent;
|
||||
bean.type = monitor.type;
|
||||
bean.url = monitor.url;
|
||||
bean.method = monitor.method;
|
||||
|
@ -707,6 +722,9 @@ let needSetup = false;
|
|||
bean.headers = monitor.headers;
|
||||
bean.basic_auth_user = monitor.basic_auth_user;
|
||||
bean.basic_auth_pass = monitor.basic_auth_pass;
|
||||
bean.tlsCa = monitor.tlsCa;
|
||||
bean.tlsCert = monitor.tlsCert;
|
||||
bean.tlsKey = monitor.tlsKey;
|
||||
bean.interval = monitor.interval;
|
||||
bean.retryInterval = monitor.retryInterval;
|
||||
bean.resendInterval = monitor.resendInterval;
|
||||
|
@ -753,14 +771,19 @@ let needSetup = false;
|
|||
bean.radiusCalledStationId = monitor.radiusCalledStationId;
|
||||
bean.radiusCallingStationId = monitor.radiusCallingStationId;
|
||||
bean.radiusSecret = monitor.radiusSecret;
|
||||
bean.httpBodyEncoding = monitor.httpBodyEncoding;
|
||||
|
||||
bean.validate();
|
||||
|
||||
await R.store(bean);
|
||||
|
||||
if (removeGroupChildren) {
|
||||
await Monitor.unlinkAllChildren(monitor.id);
|
||||
}
|
||||
|
||||
await updateMonitorNotification(bean.id, monitor.notificationIDList);
|
||||
|
||||
if (bean.active) {
|
||||
if (bean.isActive()) {
|
||||
await restartMonitor(socket.userID, bean.id);
|
||||
}
|
||||
|
||||
|
@ -906,11 +929,20 @@ let needSetup = false;
|
|||
delete server.monitorList[monitorID];
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
await R.exec("DELETE FROM monitor WHERE id = ? AND user_id = ? ", [
|
||||
monitorID,
|
||||
socket.userID,
|
||||
]);
|
||||
|
||||
// Fix #2880
|
||||
apicache.clear();
|
||||
|
||||
const endTime = Date.now();
|
||||
|
||||
log.info("DB", `Delete Monitor completed in : ${endTime - startTime} ms`);
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Deleted Successfully.",
|
||||
|
@ -1154,6 +1186,8 @@ let needSetup = false;
|
|||
await doubleCheckPassword(socket, currentPassword);
|
||||
}
|
||||
|
||||
const previousChromeExecutable = await Settings.get("chromeExecutable");
|
||||
|
||||
await setSettings("general", data);
|
||||
server.entryPage = data.entryPage;
|
||||
|
||||
|
@ -1164,6 +1198,12 @@ let needSetup = false;
|
|||
await server.setTimezone(data.serverTimezone);
|
||||
}
|
||||
|
||||
// If Chrome Executable is changed, need to reset the browser
|
||||
if (previousChromeExecutable !== data.chromeExecutable) {
|
||||
log.info("settings", "Chrome executable is changed. Resetting Chrome...");
|
||||
await resetChrome();
|
||||
}
|
||||
|
||||
callback({
|
||||
ok: true,
|
||||
msg: "Saved"
|
||||
|
@ -1347,6 +1387,7 @@ let needSetup = false;
|
|||
let monitor = {
|
||||
// Define the new variable from earlier here
|
||||
name: monitorListData[i].name,
|
||||
description: monitorListData[i].description,
|
||||
type: monitorListData[i].type,
|
||||
url: monitorListData[i].url,
|
||||
method: monitorListData[i].method || "GET",
|
||||
|
@ -1370,7 +1411,7 @@ let needSetup = false;
|
|||
accepted_statuscodes: monitorListData[i].accepted_statuscodes,
|
||||
dns_resolve_type: monitorListData[i].dns_resolve_type,
|
||||
dns_resolve_server: monitorListData[i].dns_resolve_server,
|
||||
notificationIDList: {},
|
||||
notificationIDList: monitorListData[i].notificationIDList,
|
||||
proxy_id: monitorListData[i].proxy_id || null,
|
||||
};
|
||||
|
||||
|
@ -1530,6 +1571,7 @@ let needSetup = false;
|
|||
proxySocketHandler(socket);
|
||||
dockerSocketHandler(socket);
|
||||
maintenanceSocketHandler(socket);
|
||||
apiKeySocketHandler(socket);
|
||||
generalSocketHandler(socket, server);
|
||||
pluginsHandler(socket, server);
|
||||
|
||||
|
@ -1575,7 +1617,7 @@ let needSetup = false;
|
|||
}
|
||||
});
|
||||
|
||||
initBackgroundJobs(args);
|
||||
await initBackgroundJobs();
|
||||
|
||||
// Start cloudflared at the end if configured
|
||||
await cloudflaredAutoStart(cloudflaredToken);
|
||||
|
@ -1638,6 +1680,7 @@ async function afterLogin(socket, user) {
|
|||
sendNotificationList(socket);
|
||||
sendProxyList(socket);
|
||||
sendDockerHostList(socket);
|
||||
sendAPIKeyList(socket);
|
||||
|
||||
await sleep(500);
|
||||
|
||||
|
@ -1695,7 +1738,7 @@ async function initDatabase(testMode = false) {
|
|||
needSetup = true;
|
||||
}
|
||||
|
||||
jwtSecret = jwtSecretBean.value;
|
||||
server.jwtSecret = jwtSecretBean.value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue