Merge branch 'master' of https://github.com/louislam/uptime-kuma into uptime-badges

This commit is contained in:
Jens Neuber 2022-04-20 10:10:14 +02:00
commit e103ac8335
186 changed files with 15120 additions and 5251 deletions

View file

@ -1,18 +1,19 @@
const tcpp = require("tcp-ping");
const Ping = require("./ping-lite");
const { R } = require("redbean-node");
const { debug } = require("../src/util");
const { log, genSecret } = require("../src/util");
const passwordHash = require("./password-hash");
const dayjs = require("dayjs");
const { Resolver } = require("dns");
const child_process = require("child_process");
const childProcess = require("child_process");
const iconv = require("iconv-lite");
const chardet = require("chardet");
const fs = require("fs");
const nodeJsUtil = require("util");
const mqtt = require("mqtt");
const chroma = require("chroma-js");
const { badgeConstants } = require("./config");
// From ping-lite
exports.WIN = /^win/.test(process.platform);
exports.LIN = /^linux/.test(process.platform);
@ -29,12 +30,12 @@ exports.initJWTSecret = async () => {
"jwtSecret",
]);
if (! jwtSecretBean) {
if (!jwtSecretBean) {
jwtSecretBean = R.dispense("setting");
jwtSecretBean.key = "jwtSecret";
}
jwtSecretBean.value = passwordHash.generate(dayjs() + "");
jwtSecretBean.value = passwordHash.generate(genSecret());
await R.store(jwtSecretBean);
return jwtSecretBean;
};
@ -91,11 +92,68 @@ exports.pingAsync = function (hostname, ipv6 = false) {
});
};
exports.dnsResolve = function (hostname, resolver_server, rrtype) {
const resolver = new Resolver();
resolver.setServers([resolver_server]);
exports.mqttAsync = function (hostname, topic, okMessage, options = {}) {
return new Promise((resolve, reject) => {
if (rrtype == "PTR") {
const { port, username, password, interval = 20 } = options;
// Adds MQTT protocol to the hostname if not already present
if (!/^(?:http|mqtt)s?:\/\//.test(hostname)) {
hostname = "mqtt://" + hostname;
}
const timeoutID = setTimeout(() => {
log.debug("mqtt", "MQTT timeout triggered");
client.end();
reject(new Error("Timeout"));
}, interval * 1000 * 0.8);
log.debug("mqtt", "MQTT connecting");
let client = mqtt.connect(hostname, {
port,
username,
password
});
client.on("connect", () => {
log.debug("mqtt", "MQTT connected");
try {
log.debug("mqtt", "MQTT subscribe topic");
client.subscribe(topic);
} catch (e) {
client.end();
clearTimeout(timeoutID);
reject(new Error("Cannot subscribe topic"));
}
});
client.on("error", (error) => {
client.end();
clearTimeout(timeoutID);
reject(error);
});
client.on("message", (messageTopic, message) => {
if (messageTopic == topic) {
client.end();
clearTimeout(timeoutID);
if (okMessage != null && okMessage !== "" && message.toString() !== okMessage) {
reject(new Error(`Message Mismatch - Topic: ${messageTopic}; Message: ${message.toString()}`));
} else {
resolve(`Topic: ${messageTopic}; Message: ${message.toString()}`);
}
}
});
});
};
exports.dnsResolve = function (hostname, resolverServer, rrtype) {
const resolver = new Resolver();
resolver.setServers([ resolverServer ]);
return new Promise((resolve, reject) => {
if (rrtype === "PTR") {
resolver.reverse(hostname, (err, records) => {
if (err) {
reject(err);
@ -122,7 +180,7 @@ exports.setting = async function (key) {
try {
const v = JSON.parse(value);
debug(`Get Setting: ${key}: ${v}`);
log.debug("util", `Get Setting: ${key}: ${v}`);
return v;
} catch (e) {
return value;
@ -209,7 +267,7 @@ const parseCertificateInfo = function (info) {
const existingList = {};
while (link) {
debug(`[${i}] ${link.fingerprint}`);
log.debug("cert", `[${i}] ${link.fingerprint}`);
if (!link.valid_from || !link.valid_to) {
break;
@ -224,7 +282,7 @@ const parseCertificateInfo = function (info) {
if (link.issuerCertificate == null) {
break;
} else if (link.issuerCertificate.fingerprint in existingList) {
debug(`[Last] ${link.issuerCertificate.fingerprint}`);
log.debug("cert", `[Last] ${link.issuerCertificate.fingerprint}`);
link.issuerCertificate = null;
break;
} else {
@ -245,7 +303,7 @@ exports.checkCertificate = function (res) {
const info = res.request.res.socket.getPeerCertificate(true);
const valid = res.request.res.socket.authorized || false;
debug("Parsing Certificate Info");
log.debug("cert", "Parsing Certificate Info");
const parsedInfo = parseCertificateInfo(info);
return {
@ -260,19 +318,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 {
@ -287,13 +345,13 @@ exports.getTotalClientInRoom = (io, roomName) => {
const sockets = io.sockets;
if (! sockets) {
if (!sockets) {
return 0;
}
const adapter = sockets.adapter;
if (! adapter) {
if (!adapter) {
return 0;
}
@ -318,15 +376,37 @@ exports.allowAllOrigin = (res) => {
};
exports.checkLogin = (socket) => {
if (! socket.userID) {
if (!socket.userID) {
throw new Error("You are not logged in.");
}
};
/**
* For logged-in users, double-check the password
* @param socket
* @param currentPassword
* @returns {Promise<Bean>}
*/
exports.doubleCheckPassword = async (socket, currentPassword) => {
if (typeof currentPassword !== "string") {
throw new Error("Wrong data type?");
}
let user = await R.findOne("user", " id = ? AND active = 1 ", [
socket.userID,
]);
if (!user || !passwordHash.verify(currentPassword, user.password)) {
throw new Error("Incorrect current password");
}
return user;
};
exports.startUnitTest = async () => {
console.log("Starting unit test...");
const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm";
const child = child_process.spawn(npm, ["run", "jest"]);
const child = childProcess.spawn(npm, [ "run", "jest" ]);
child.stdout.on("data", (data) => {
console.log(data.toString());
@ -348,7 +428,6 @@ exports.startUnitTest = async () => {
*/
exports.convertToUTF8 = (body) => {
const guessEncoding = chardet.detect(body);
//debug("Guess Encoding: " + guessEncoding);
const str = iconv.decode(body, guessEncoding);
return str.toString();
};