Merge branch 'master' into mqtt2

# Conflicts:
#	server/database.js
#	server/util-server.js
This commit is contained in:
Louis Lam
2022-04-17 19:46:33 +08:00
58 changed files with 456 additions and 168 deletions

View File

@@ -1,4 +1,3 @@
const { checkLogin } = require("./util-server");
const { R } = require("redbean-node");
class TwoFA {

View File

@@ -98,7 +98,7 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove
async function sendProxyList(socket) {
const timeLogger = new TimeLogger();
const list = await R.find("proxy", " user_id = ? ", [socket.userID]);
const list = await R.find("proxy", " user_id = ? ", [ socket.userID ]);
io.to(socket.userID).emit("proxyList", list.map(bean => bean.export()));
timeLogger.print("Send Proxy List");

View File

@@ -56,6 +56,7 @@ class Database {
"patch-status-page.sql": true,
"patch-proxy.sql": true,
"patch-monitor-expiry-notification.sql": true,
"patch-status-page-footer-css.sql": true,
"patch-added-mqtt-monitor.sql": true,
}

View File

@@ -30,7 +30,7 @@ const DEFAULT_KEEP_PERIOD = 180;
try {
await R.exec(
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
[parsedPeriod]
[ parsedPeriod ]
);
} catch (e) {
log(`Failed to clear old data: ${e.message}`);

View File

@@ -9,7 +9,7 @@ const log = function (any) {
};
const exit = function (error) {
if (error && error != 0) {
if (error && error !== 0) {
process.exit(error);
} else {
if (parentPort) {

View File

@@ -42,7 +42,7 @@ class Monitor extends BeanModel {
/**
* Return an object that ready to parse to JSON
*/
async toJSON() {
async toJSON(includeSensitiveData = true) {
let notificationIDList = {};
@@ -56,15 +56,11 @@ class Monitor extends BeanModel {
const tags = await this.getTags();
return {
let data = {
id: this.id,
name: this.name,
url: this.url,
method: this.method,
body: this.body,
headers: this.headers,
basic_auth_user: this.basic_auth_user,
basic_auth_pass: this.basic_auth_pass,
hostname: this.hostname,
port: this.port,
maxretries: this.maxretries,
@@ -82,7 +78,6 @@ class Monitor extends BeanModel {
dns_resolve_type: this.dns_resolve_type,
dns_resolve_server: this.dns_resolve_server,
dns_last_result: this.dns_last_result,
pushToken: this.pushToken,
proxyId: this.proxy_id,
notificationIDList,
tags: tags,
@@ -91,10 +86,23 @@ class Monitor extends BeanModel {
mqttTopic: this.mqttTopic,
mqttSuccessMessage: this.mqttSuccessMessage
};
if (includeSensitiveData) {
data = {
...data,
headers: this.headers,
body: this.body,
basic_auth_user: this.basic_auth_user,
basic_auth_pass: this.basic_auth_pass,
pushToken: this.pushToken,
};
}
return data;
}
async getTags() {
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [this.id]);
return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [ this.id ]);
}
/**
@@ -266,7 +274,7 @@ class Monitor extends BeanModel {
log.debug("monitor", "Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
}
if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID == this.id) {
if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID === this.id) {
log.info("monitor", res.data);
}
@@ -306,24 +314,24 @@ class Monitor extends BeanModel {
let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.dns_resolve_type);
bean.ping = dayjs().valueOf() - startTime;
if (this.dns_resolve_type == "A" || this.dns_resolve_type == "AAAA" || this.dns_resolve_type == "TXT") {
if (this.dns_resolve_type === "A" || this.dns_resolve_type === "AAAA" || this.dns_resolve_type === "TXT") {
dnsMessage += "Records: ";
dnsMessage += dnsRes.join(" | ");
} else if (this.dns_resolve_type == "CNAME" || this.dns_resolve_type == "PTR") {
} else if (this.dns_resolve_type === "CNAME" || this.dns_resolve_type === "PTR") {
dnsMessage = dnsRes[0];
} else if (this.dns_resolve_type == "CAA") {
} else if (this.dns_resolve_type === "CAA") {
dnsMessage = dnsRes[0].issue;
} else if (this.dns_resolve_type == "MX") {
} else if (this.dns_resolve_type === "MX") {
dnsRes.forEach(record => {
dnsMessage += `Hostname: ${record.exchange} - Priority: ${record.priority} | `;
});
dnsMessage = dnsMessage.slice(0, -2);
} else if (this.dns_resolve_type == "NS") {
} else if (this.dns_resolve_type === "NS") {
dnsMessage += "Servers: ";
dnsMessage += dnsRes.join(" | ");
} else if (this.dns_resolve_type == "SOA") {
} else if (this.dns_resolve_type === "SOA") {
dnsMessage += `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`;
} else if (this.dns_resolve_type == "SRV") {
} else if (this.dns_resolve_type === "SRV") {
dnsRes.forEach(record => {
dnsMessage += `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight} | `;
});
@@ -620,11 +628,11 @@ class Monitor extends BeanModel {
}
static async sendCertInfo(io, monitorID, userID) {
let tls_info = await R.findOne("monitor_tls_info", "monitor_id = ?", [
let tlsInfo = await R.findOne("monitor_tls_info", "monitor_id = ?", [
monitorID,
]);
if (tls_info != null) {
io.to(userID).emit("certInfo", monitorID, tls_info.info_json);
if (tlsInfo != null) {
io.to(userID).emit("certInfo", monitorID, tlsInfo.info_json);
}
}
@@ -738,7 +746,7 @@ class Monitor extends BeanModel {
for (let notification of notificationList) {
try {
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(), bean.toJSON());
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(false), bean.toJSON());
} catch (e) {
log.error("monitor", "Cannot send notification to " + notification.name);
log.error("monitor", e);

View File

@@ -92,6 +92,9 @@ class StatusPage extends BeanModel {
published: !!this.published,
showTags: !!this.show_tags,
domainNameList: this.getDomainNameList(),
customCSS: this.custom_css,
footerText: this.footer_text,
showPoweredBy: !!this.show_powered_by,
};
}
@@ -104,6 +107,9 @@ class StatusPage extends BeanModel {
theme: this.theme,
published: !!this.published,
showTags: !!this.show_tags,
customCSS: this.custom_css,
footerText: this.footer_text,
showPoweredBy: !!this.show_powered_by,
};
}

View File

@@ -40,17 +40,17 @@ class Alerta extends NotificationProvider {
await axios.post(alertaUrl, postData, config);
} else {
let datadup = Object.assign( {
correlate: ["service_up", "service_down"],
correlate: [ "service_up", "service_down" ],
event: monitorJSON["type"],
group: "uptimekuma-" + monitorJSON["type"],
resource: monitorJSON["name"],
}, data );
if (heartbeatJSON["status"] == DOWN) {
if (heartbeatJSON["status"] === DOWN) {
datadup.severity = notification.alertaAlertState; // critical
datadup.text = "Service " + monitorJSON["type"] + " is down.";
await axios.post(alertaUrl, datadup, config);
} else if (heartbeatJSON["status"] == UP) {
} else if (heartbeatJSON["status"] === UP) {
datadup.severity = notification.alertaRecoverState; // cleaned
datadup.text = "Service " + monitorJSON["type"] + " is up.";
await axios.post(alertaUrl, datadup, config);

View File

@@ -64,7 +64,7 @@ class AliyunSMS extends NotificationProvider {
};
let result = await axios(config);
if (result.data.Message == "OK") {
if (result.data.Message === "OK") {
return true;
}
return false;

View File

@@ -1,12 +1,12 @@
const NotificationProvider = require("./notification-provider");
const child_process = require("child_process");
const childProcess = require("child_process");
class Apprise extends NotificationProvider {
name = "apprise";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let s = child_process.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL]);
let s = childProcess.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL ]);
let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found";

View File

@@ -28,12 +28,12 @@ class Bark extends NotificationProvider {
barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === UP) {
let title = "UptimeKuma Monitor Up";
return await this.postNotification(title, msg, barkEndpoint);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) {
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
let title = "UptimeKuma Monitor Down";
return await this.postNotification(title, msg, barkEndpoint);
}

View File

@@ -50,7 +50,7 @@ class DingDing extends NotificationProvider {
};
let result = await axios(config);
if (result.data.errmsg == "ok") {
if (result.data.errmsg === "ok") {
return true;
}
return false;

View File

@@ -35,7 +35,7 @@ class Discord extends NotificationProvider {
}
// If heartbeatJSON is not null, we go into the normal alerting loop.
if (heartbeatJSON["status"] == DOWN) {
if (heartbeatJSON["status"] === DOWN) {
let discorddowndata = {
username: discordDisplayName,
embeds: [{
@@ -70,7 +70,7 @@ class Discord extends NotificationProvider {
await axios.post(notification.discordWebhookUrl, discorddowndata);
return okMsg;
} else if (heartbeatJSON["status"] == UP) {
} else if (heartbeatJSON["status"] === UP) {
let discordupdata = {
username: discordDisplayName,
embeds: [{

View File

@@ -21,7 +21,7 @@ class Feishu extends NotificationProvider {
return okMsg;
}
if (heartbeatJSON["status"] == DOWN) {
if (heartbeatJSON["status"] === DOWN) {
let downdata = {
msg_type: "post",
content: {
@@ -48,7 +48,7 @@ class Feishu extends NotificationProvider {
return okMsg;
}
if (heartbeatJSON["status"] == UP) {
if (heartbeatJSON["status"] === UP) {
let updata = {
msg_type: "post",
content: {

View File

@@ -18,7 +18,7 @@ class Gorush extends NotificationProvider {
let data = {
"notifications": [
{
"tokens": [notification.gorushDeviceToken],
"tokens": [ notification.gorushDeviceToken ],
"platform": platformMapping[notification.gorushPlatform],
"message": msg,
// Optional

View File

@@ -27,7 +27,7 @@ class Line extends NotificationProvider {
]
};
await axios.post(lineAPIUrl, testMessage, config);
} else if (heartbeatJSON["status"] == DOWN) {
} else if (heartbeatJSON["status"] === DOWN) {
let downMessage = {
"to": notification.lineUserID,
"messages": [
@@ -38,7 +38,7 @@ class Line extends NotificationProvider {
]
};
await axios.post(lineAPIUrl, downMessage, config);
} else if (heartbeatJSON["status"] == UP) {
} else if (heartbeatJSON["status"] === UP) {
let upMessage = {
"to": notification.lineUserID,
"messages": [

View File

@@ -20,7 +20,7 @@ class LunaSea extends NotificationProvider {
return okMsg;
}
if (heartbeatJSON["status"] == DOWN) {
if (heartbeatJSON["status"] === DOWN) {
let downdata = {
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
@@ -29,7 +29,7 @@ class LunaSea extends NotificationProvider {
return okMsg;
}
if (heartbeatJSON["status"] == UP) {
if (heartbeatJSON["status"] === UP) {
let updata = {
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],

View File

@@ -29,7 +29,7 @@ class Mattermost extends NotificationProvider {
const mattermostIconEmoji = notification.mattermosticonemo;
const mattermostIconUrl = notification.mattermosticonurl;
if (heartbeatJSON["status"] == DOWN) {
if (heartbeatJSON["status"] === DOWN) {
let mattermostdowndata = {
username: mattermostUserName,
text: "Uptime Kuma Alert",
@@ -73,7 +73,7 @@ class Mattermost extends NotificationProvider {
mattermostdowndata
);
return okMsg;
} else if (heartbeatJSON["status"] == UP) {
} else if (heartbeatJSON["status"] === UP) {
let mattermostupdata = {
username: mattermostUserName,
text: "Uptime Kuma Alert",

View File

@@ -10,7 +10,7 @@ class Octopush extends NotificationProvider {
try {
// Default - V2
if (notification.octopushVersion == 2 || !notification.octopushVersion) {
if (notification.octopushVersion === 2 || !notification.octopushVersion) {
let config = {
headers: {
"api-key": notification.octopushAPIKey,
@@ -31,13 +31,13 @@ class Octopush extends NotificationProvider {
"sender": notification.octopushSenderName
};
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config);
} else if (notification.octopushVersion == 1) {
} else if (notification.octopushVersion === 1) {
let data = {
"user_login": notification.octopushDMLogin,
"api_key": notification.octopushDMAPIKey,
"sms_recipients": notification.octopushDMPhoneNumber,
"sms_sender": notification.octopushDMSenderName,
"sms_type": (notification.octopushDMSMSType == "sms_premium") ? "FR" : "XXX",
"sms_type": (notification.octopushDMSMSType === "sms_premium") ? "FR" : "XXX",
"transactional": "1",
//octopush not supporting non ascii char
"sms_text": msg.replace(/[^\x00-\x7F]/g, ""),

View File

@@ -27,7 +27,7 @@ class OneBot extends NotificationProvider {
"auto_escape": true,
"message": pushText,
};
if (notification.msgType == "group") {
if (notification.msgType === "group") {
data["message_type"] = "group";
data["group_id"] = notification.recieverId;
} else {

View File

@@ -25,14 +25,14 @@ class Pushbullet extends NotificationProvider {
"body": "Testing Successful.",
};
await axios.post(pushbulletUrl, testdata, config);
} else if (heartbeatJSON["status"] == DOWN) {
} else if (heartbeatJSON["status"] === DOWN) {
let downdata = {
"type": "note",
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
};
await axios.post(pushbulletUrl, downdata, config);
} else if (heartbeatJSON["status"] == UP) {
} else if (heartbeatJSON["status"] === UP) {
let updata = {
"type": "note",
"title": "UptimeKuma Alert: " + monitorJSON["name"],

View File

@@ -0,0 +1,52 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class PushDeer extends NotificationProvider {
name = "PushDeer";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
let pushdeerlink = "https://api2.pushdeer.com/message/push";
let valid = msg != null && monitorJSON != null && heartbeatJSON != null;
let title;
if (valid && heartbeatJSON.status === UP) {
title = "## Uptime Kuma: " + monitorJSON.name + " up";
} else if (valid && heartbeatJSON.status === DOWN) {
title = "## Uptime Kuma: " + monitorJSON.name + " down";
} else {
title = "## Uptime Kuma Message";
}
let data = {
"pushkey": notification.pushdeerKey,
"text": title,
"desp": msg.replace(/\n/g, "\n\n"),
"type": "markdown",
};
try {
let res = await axios.post(pushdeerlink, data);
if ("error" in res.data) {
let error = res.data.error;
this.throwGeneralAxiosError(error);
}
if (res.data.content.result.length === 0) {
let error = "Invalid PushDeer key";
this.throwGeneralAxiosError(error);
} else if (JSON.parse(res.data.content.result[0]).success !== "ok") {
let error = "Unknown error";
this.throwGeneralAxiosError(error);
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = PushDeer;

View File

@@ -1,6 +1,6 @@
const nodemailer = require("nodemailer");
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
const { DOWN } = require("../../src/util");
class SMTP extends NotificationProvider {

View File

@@ -26,10 +26,10 @@ class WeCom extends NotificationProvider {
composeMessage(heartbeatJSON, msg) {
let title;
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === UP) {
title = "UptimeKuma Monitor Up";
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) {
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) {
title = "UptimeKuma Monitor Down";
}
if (msg != null) {

View File

@@ -32,6 +32,7 @@ const GoogleChat = require("./notification-providers/google-chat");
const Gorush = require("./notification-providers/gorush");
const Alerta = require("./notification-providers/alerta");
const OneBot = require("./notification-providers/onebot");
const PushDeer = require("./notification-providers/pushdeer");
class Notification {
@@ -75,6 +76,7 @@ class Notification {
new Gorush(),
new Alerta(),
new OneBot(),
new PushDeer(),
];
for (let item of list) {

View File

@@ -9,24 +9,24 @@ const commonLabels = [
"monitor_port",
];
const monitor_cert_days_remaining = new PrometheusClient.Gauge({
const monitorCertDaysRemaining = new PrometheusClient.Gauge({
name: "monitor_cert_days_remaining",
help: "The number of days remaining until the certificate expires",
labelNames: commonLabels
});
const monitor_cert_is_valid = new PrometheusClient.Gauge({
const monitorCertIsValid = new PrometheusClient.Gauge({
name: "monitor_cert_is_valid",
help: "Is the certificate still valid? (1 = Yes, 0= No)",
labelNames: commonLabels
});
const monitor_response_time = new PrometheusClient.Gauge({
const monitorResponseTime = new PrometheusClient.Gauge({
name: "monitor_response_time",
help: "Monitor Response Time (ms)",
labelNames: commonLabels
});
const monitor_status = new PrometheusClient.Gauge({
const monitorStatus = new PrometheusClient.Gauge({
name: "monitor_status",
help: "Monitor Status (1 = UP, 0= DOWN)",
labelNames: commonLabels
@@ -49,13 +49,13 @@ class Prometheus {
if (typeof tlsInfo !== "undefined") {
try {
let isValid = 0;
if (tlsInfo.valid == true) {
let isValid;
if (tlsInfo.valid === true) {
isValid = 1;
} else {
isValid = 0;
}
monitor_cert_is_valid.set(this.monitorLabelValues, isValid);
monitorCertIsValid.set(this.monitorLabelValues, isValid);
} catch (e) {
log.error("prometheus", "Caught error");
log.error("prometheus", e);
@@ -63,7 +63,7 @@ class Prometheus {
try {
if (tlsInfo.certInfo != null) {
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining);
monitorCertDaysRemaining.set(this.monitorLabelValues, tlsInfo.certInfo.daysRemaining);
}
} catch (e) {
log.error("prometheus", "Caught error");
@@ -72,7 +72,7 @@ class Prometheus {
}
try {
monitor_status.set(this.monitorLabelValues, heartbeat.status);
monitorStatus.set(this.monitorLabelValues, heartbeat.status);
} catch (e) {
log.error("prometheus", "Caught error");
log.error("prometheus", e);
@@ -80,10 +80,10 @@ class Prometheus {
try {
if (typeof heartbeat.ping === "number") {
monitor_response_time.set(this.monitorLabelValues, heartbeat.ping);
monitorResponseTime.set(this.monitorLabelValues, heartbeat.ping);
} else {
// Is it good?
monitor_response_time.set(this.monitorLabelValues, -1);
monitorResponseTime.set(this.monitorLabelValues, -1);
}
} catch (e) {
log.error("prometheus", "Caught error");
@@ -93,10 +93,10 @@ class Prometheus {
remove() {
try {
monitor_cert_days_remaining.remove(this.monitorLabelValues);
monitor_cert_is_valid.remove(this.monitorLabelValues);
monitor_response_time.remove(this.monitorLabelValues);
monitor_status.remove(this.monitorLabelValues);
monitorCertDaysRemaining.remove(this.monitorLabelValues);
monitorCertIsValid.remove(this.monitorLabelValues);
monitorResponseTime.remove(this.monitorLabelValues);
monitorStatus.remove(this.monitorLabelValues);
} catch (e) {
console.error(e);
}

View File

@@ -7,7 +7,7 @@ const server = require("./server");
class Proxy {
static SUPPORTED_PROXY_PROTOCOLS = ["http", "https", "socks", "socks5", "socks4"]
static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks4" ]
/**
* Saves and updates given proxy entity
@@ -21,7 +21,7 @@ class Proxy {
let bean;
if (proxyID) {
bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [proxyID, userID]);
bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
if (!bean) {
throw new Error("proxy not found");
@@ -71,14 +71,14 @@ class Proxy {
* @return {Promise<void>}
*/
static async delete(proxyID, userID) {
const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [proxyID, userID]);
const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]);
if (!bean) {
throw new Error("proxy not found");
}
// Delete removed proxy from monitors if exists
await R.exec("UPDATE monitor SET proxy_id = null WHERE proxy_id = ?", [proxyID]);
await R.exec("UPDATE monitor SET proxy_id = null WHERE proxy_id = ?", [ proxyID ]);
// Delete proxy from list
await R.trash(bean);
@@ -172,12 +172,12 @@ class Proxy {
*/
async function applyProxyEveryMonitor(proxyID, userID) {
// Find all monitors with id and proxy id
const monitors = await R.getAll("SELECT id, proxy_id FROM monitor WHERE user_id = ?", [userID]);
const monitors = await R.getAll("SELECT id, proxy_id FROM monitor WHERE user_id = ?", [ userID ]);
// Update proxy id not match with given proxy id
for (const monitor of monitors) {
if (monitor.proxy_id !== proxyID) {
await R.exec("UPDATE monitor SET proxy_id = ? WHERE id = ?", [proxyID, monitor.id]);
await R.exec("UPDATE monitor SET proxy_id = ? WHERE id = ?", [ proxyID, monitor.id ]);
}
}
}

View File

@@ -1,5 +1,5 @@
let express = require("express");
const { allowDevAllOrigin, getSettings, setting } = require("../util-server");
const { allowDevAllOrigin } = require("../util-server");
const { R } = require("redbean-node");
const server = require("../server");
const apicache = require("../modules/apicache");
@@ -195,14 +195,6 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques
}
});
/**
* Default is published
* @returns {Promise<boolean>}
*/
async function isPublished() {
return true;
}
function send403(res, msg = "") {
res.status(403).json({
"status": "fail",

View File

@@ -11,7 +11,7 @@ if (nodeVersion < requiredVersion) {
}
const args = require("args-parser")(process.argv);
const { sleep, log, getRandomInt, genSecret, debug } = require("../src/util");
const { sleep, log, getRandomInt, genSecret, debug, isDev } = require("../src/util");
const config = require("./config");
log.info("server", "Welcome to Uptime Kuma");
@@ -108,7 +108,7 @@ if (hostname) {
log.info("server", "Custom hostname: " + hostname);
}
const port = [args.port, process.env.UPTIME_KUMA_PORT, process.env.PORT, 3001]
const port = [ args.port, process.env.UPTIME_KUMA_PORT, process.env.PORT, 3001 ]
.map(portValue => parseInt(portValue))
.find(portValue => !isNaN(portValue));
@@ -119,7 +119,7 @@ const disableFrameSameOrigin = args["disable-frame-sameorigin"] || !!process.env
const cloudflaredToken = args["cloudflared-token"] || process.env.UPTIME_KUMA_CLOUDFLARED_TOKEN || undefined;
// 2FA / notp verification defaults
const twofa_verification_opts = {
const twoFAVerifyOptions = {
"window": 1,
"time": 30
};
@@ -175,6 +175,7 @@ app.use(function (req, res, next) {
/**
* Total WebSocket client connected to server currently, no actual use
*
* @type {number}
*/
let totalClient = 0;
@@ -234,6 +235,13 @@ try {
}
});
if (isDev) {
app.post("/test-webhook", async (request, response) => {
log.debug("test", request.body);
response.send("OK");
});
}
// Robots.txt
app.get("/robots.txt", async (_request, response) => {
let txt = "User-agent: *\nDisallow:";
@@ -379,7 +387,7 @@ try {
}
if (data.token) {
let verify = notp.totp.verify(data.token, user.twofa_secret, twofa_verification_opts);
let verify = notp.totp.verify(data.token, user.twofa_secret, twoFAVerifyOptions);
if (user.twofa_last_token !== data.token && verify) {
afterLogin(socket, user);
@@ -546,7 +554,7 @@ try {
socket.userID,
]);
let verify = notp.totp.verify(token, user.twofa_secret, twofa_verification_opts);
let verify = notp.totp.verify(token, user.twofa_secret, twoFAVerifyOptions);
if (user.twofa_last_token !== token && verify) {
callback({
@@ -1239,7 +1247,7 @@ try {
const exists = proxies.find(item => item.id === proxy.id);
// Do not process when proxy already exists in import handle is skip and keep
if (["skip", "keep"].includes(importHandle) && !exists) {
if ([ "skip", "keep" ].includes(importHandle) && !exists) {
return;
}

View File

@@ -155,6 +155,9 @@ module.exports.statusPageSocketHandler = (socket) => {
//statusPage.search_engine_index = ;
statusPage.show_tags = config.showTags;
//statusPage.password = null;
statusPage.footer_text = config.footerText;
statusPage.custom_css = config.customCSS;
statusPage.show_powered_by = config.showPoweredBy;
statusPage.modified_date = R.isoDateTime();
await R.store(statusPage);

View File

@@ -146,11 +146,11 @@ exports.mqttAsync = function (hostname, topic, okMessage, options = {}) {
});
};
exports.dnsResolve = function (hostname, resolver_server, rrtype) {
exports.dnsResolve = function (hostname, resolverServer, rrtype) {
const resolver = new Resolver();
resolver.setServers([resolver_server]);
resolver.setServers([ resolverServer ]);
return new Promise((resolve, reject) => {
if (rrtype == "PTR") {
if (rrtype === "PTR") {
resolver.reverse(hostname, (err, records) => {
if (err) {
reject(err);
@@ -315,19 +315,19 @@ exports.checkCertificate = function (res) {
// Return: true if the status code is within the accepted ranges, false otherwise
// Will throw an error if the provided status code is not a valid range string or code string
exports.checkStatusCode = function (status, accepted_codes) {
if (accepted_codes == null || accepted_codes.length === 0) {
exports.checkStatusCode = function (status, acceptedCodes) {
if (acceptedCodes == null || acceptedCodes.length === 0) {
return false;
}
for (const code_range of accepted_codes) {
const code_range_split = code_range.split("-").map(string => parseInt(string));
if (code_range_split.length === 1) {
if (status === code_range_split[0]) {
for (const codeRange of acceptedCodes) {
const codeRangeSplit = codeRange.split("-").map(string => parseInt(string));
if (codeRangeSplit.length === 1) {
if (status === codeRangeSplit[0]) {
return true;
}
} else if (code_range_split.length === 2) {
if (status >= code_range_split[0] && status <= code_range_split[1]) {
} else if (codeRangeSplit.length === 2) {
if (status >= codeRangeSplit[0] && status <= codeRangeSplit[1]) {
return true;
}
} else {
@@ -403,7 +403,7 @@ exports.doubleCheckPassword = async (socket, currentPassword) => {
exports.startUnitTest = async () => {
console.log("Starting unit test...");
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
const child = childProcess.spawn(npm, ["run", "jest"]);
const child = childProcess.spawn(npm, [ "run", "jest" ]);
child.stdout.on("data", (data) => {
console.log(data.toString());