Merge remote-tracking branch 'origin/master' into feat/add-auth-header-to-webhook-notification-#1919

This commit is contained in:
Louis Lam 2022-12-05 17:52:02 +08:00
commit 5196abfd36
11 changed files with 1072 additions and 844 deletions

View file

@ -4,5 +4,5 @@ WORKDIR /app
# Install apprise, iputils for non-root ping, setpriv # Install apprise, iputils for non-root ping, setpriv
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \ RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
pip3 --no-cache-dir install apprise==1.0.0 && \ pip3 --no-cache-dir install apprise==1.2.0 && \
rm -rf /root/.cache rm -rf /root/.cache

View file

@ -11,7 +11,7 @@ WORKDIR /app
RUN apt update && \ RUN apt update && \
apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \ apt --yes --no-install-recommends install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
sqlite3 iputils-ping util-linux dumb-init && \ sqlite3 iputils-ping util-linux dumb-init && \
pip3 --no-cache-dir install apprise==1.0.0 && \ pip3 --no-cache-dir install apprise==1.2.0 && \
rm -rf /var/lib/apt/lists/* && \ rm -rf /var/lib/apt/lists/* && \
apt --yes autoremove apt --yes autoremove

View file

@ -5,7 +5,7 @@ const util = require("../src/util");
util.polyfill(); util.polyfill();
const oldVersion = pkg.version; const oldVersion = pkg.version;
const newVersion = oldVersion + "-nightly"; const newVersion = oldVersion + "-nightly-" + util.genSecret(8);
console.log("Old Version: " + oldVersion); console.log("Old Version: " + oldVersion);
console.log("New Version: " + newVersion); console.log("New Version: " + newVersion);

1825
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,6 @@
"start": "npm run start-server", "start": "npm run start-server",
"start-server": "node server/server.js", "start-server": "node server/server.js",
"start-server-dev": "cross-env NODE_ENV=development node server/server.js", "start-server-dev": "cross-env NODE_ENV=development node server/server.js",
"start-server-watch-dev": "cross-env NODE_ENV=development node --watch server/server.js",
"build": "vite build --config ./config/vite.config.js", "build": "vite build --config ./config/vite.config.js",
"test": "node test/prepare-test-server.js && npm run jest-backend", "test": "node test/prepare-test-server.js && npm run jest-backend",
"test-with-build": "npm run build && npm test", "test-with-build": "npm run build && npm test",
@ -64,11 +63,11 @@
"cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\"" "cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\""
}, },
"dependencies": { "dependencies": {
"@grpc/grpc-js": "^1.7.0", "@grpc/grpc-js": "~1.7.3",
"@louislam/sqlite3": "15.1.2", "@louislam/sqlite3": "15.1.2",
"args-parser": "~1.3.0", "args-parser": "~1.3.0",
"axios": "~0.27.0", "axios": "~0.27.0",
"axios-ntlm": "~1.3.0", "axios-ntlm": "1.3.0",
"badge-maker": "~3.3.1", "badge-maker": "~3.3.1",
"bcryptjs": "~2.4.3", "bcryptjs": "~2.4.3",
"bree": "~7.1.5", "bree": "~7.1.5",
@ -95,6 +94,7 @@
"limiter": "~2.1.0", "limiter": "~2.1.0",
"mqtt": "~4.3.7", "mqtt": "~4.3.7",
"mssql": "~8.1.4", "mssql": "~8.1.4",
"mysql2": "~2.3.3",
"node-cloudflared-tunnel": "~1.0.9", "node-cloudflared-tunnel": "~1.0.9",
"node-radius-client": "~1.0.0", "node-radius-client": "~1.0.0",
"nodemailer": "~6.6.5", "nodemailer": "~6.6.5",
@ -133,7 +133,7 @@
"chart.js": "~3.6.2", "chart.js": "~3.6.2",
"chartjs-adapter-dayjs": "~1.0.0", "chartjs-adapter-dayjs": "~1.0.0",
"concurrently": "^7.1.0", "concurrently": "^7.1.0",
"core-js": "~3.18.3", "core-js": "~3.26.1",
"cross-env": "~7.0.3", "cross-env": "~7.0.3",
"cypress": "^10.1.0", "cypress": "^10.1.0",
"delay": "^5.0.0", "delay": "^5.0.0",

View file

@ -3,7 +3,7 @@ const dayjs = require("dayjs");
const axios = require("axios"); const axios = require("axios");
const { Prometheus } = require("../prometheus"); const { Prometheus } = require("../prometheus");
const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger } = require("../../src/util"); const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger } = require("../../src/util");
const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery } = require("../util-server"); const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery } = require("../util-server");
const { R } = require("redbean-node"); const { R } = require("redbean-node");
const { BeanModel } = require("redbean-node/dist/bean-model"); const { BeanModel } = require("redbean-node/dist/bean-model");
const { Notification } = require("../notification"); const { Notification } = require("../notification");
@ -267,17 +267,22 @@ class Monitor extends BeanModel {
log.debug("monitor", `[${this.name}] Prepare Options for axios`); log.debug("monitor", `[${this.name}] Prepare Options for axios`);
// Axios Options
const options = { const options = {
url: this.url, url: this.url,
method: (this.method || "get").toLowerCase(), method: (this.method || "get").toLowerCase(),
...(this.body ? { data: JSON.parse(this.body) } : {}), ...(this.body ? { data: JSON.parse(this.body) } : {}),
timeout: this.interval * 1000 * 0.8, timeout: this.interval * 1000 * 0.8,
headers: { headers: {
// Fix #2253
// Read more: https://stackoverflow.com/questions/1759956/curl-error-18-transfer-closed-with-outstanding-read-data-remaining
"Accept-Encoding": "gzip, deflate",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"User-Agent": "Uptime-Kuma/" + version, "User-Agent": "Uptime-Kuma/" + version,
...(this.headers ? JSON.parse(this.headers) : {}), ...(this.headers ? JSON.parse(this.headers) : {}),
...(basicAuthHeader), ...(basicAuthHeader),
}, },
decompress: true,
maxRedirects: this.maxredirects, maxRedirects: this.maxredirects,
validateStatus: (status) => { validateStatus: (status) => {
return checkStatusCode(status, this.getAcceptedStatuscodes()); return checkStatusCode(status, this.getAcceptedStatuscodes());
@ -578,6 +583,14 @@ class Monitor extends BeanModel {
await postgresQuery(this.databaseConnectionString, this.databaseQuery); await postgresQuery(this.databaseConnectionString, this.databaseQuery);
bean.msg = "";
bean.status = UP;
bean.ping = dayjs().valueOf() - startTime;
} else if (this.type === "mysql") {
let startTime = dayjs().valueOf();
await mysqlQuery(this.databaseConnectionString, this.databaseQuery);
bean.msg = ""; bean.msg = "";
bean.status = UP; bean.status = UP;
bean.ping = dayjs().valueOf() - startTime; bean.ping = dayjs().valueOf() - startTime;

View file

@ -7,7 +7,7 @@ const { UptimeKumaServer } = require("./uptime-kuma-server");
class Proxy { class Proxy {
static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks4" ]; static SUPPORTED_PROXY_PROTOCOLS = [ "http", "https", "socks", "socks5", "socks5h", "socks4" ];
/** /**
* Saves and updates given proxy entity * Saves and updates given proxy entity
@ -126,6 +126,7 @@ class Proxy {
break; break;
case "socks": case "socks":
case "socks5": case "socks5":
case "socks5h":
case "socks4": case "socks4":
agent = new SocksProxyAgent({ agent = new SocksProxyAgent({
...httpAgentOptions, ...httpAgentOptions,

View file

@ -13,6 +13,7 @@ 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;
const mysql = require("mysql2");
const { NtlmClient } = require("axios-ntlm"); const { NtlmClient } = require("axios-ntlm");
const { Settings } = require("./settings"); const { Settings } = require("./settings");
const grpc = require("@grpc/grpc-js"); const grpc = require("@grpc/grpc-js");
@ -294,6 +295,28 @@ exports.postgresQuery = function (connectionString, query) {
}); });
}; };
/**
* Run a query on MySQL/MariaDB
* @param {string} connectionString The database connection string
* @param {string} query The query to validate the database with
* @returns {Promise<(string[]|Object[]|Object)>}
*/
exports.mysqlQuery = function (connectionString, query) {
return new Promise((resolve, reject) => {
const connection = mysql.createConnection(connectionString);
connection.promise().query(query)
.then(res => {
resolve(res);
})
.catch(err => {
reject(err);
})
.finally(() => {
connection.end();
});
});
};
/** /**
* Query radius server * Query radius server
* @param {string} hostname Hostname of radius server * @param {string} hostname Hostname of radius server

View file

@ -17,6 +17,7 @@
<option value="http">HTTP</option> <option value="http">HTTP</option>
<option value="socks">SOCKS</option> <option value="socks">SOCKS</option>
<option value="socks5">SOCKS v5</option> <option value="socks5">SOCKS v5</option>
<option value="socks5h">SOCKS v5 (+DNS)</option>
<option value="socks4">SOCKS v4</option> <option value="socks4">SOCKS v4</option>
</select> </select>
</div> </div>

View file

@ -623,12 +623,25 @@ export default {
lastDay4: "4-ти последен ден на месеца", lastDay4: "4-ти последен ден на месеца",
"No Maintenance": "Няма поддръжка", "No Maintenance": "Няма поддръжка",
pauseMaintenanceMsg: "Сигурни ли сте, че желаете да направите пауза?", pauseMaintenanceMsg: "Сигурни ли сте, че желаете да направите пауза?",
"maintenanceStatus-under-maintenance": "В режим подръжка", "maintenanceStatus-under-maintenance": "В режим поддръжка",
"maintenanceStatus-inactive": "Неактивен", "maintenanceStatus-inactive": "Неактивна",
"maintenanceStatus-scheduled": "Планиран", "maintenanceStatus-scheduled": "Планирана",
"maintenanceStatus-ended": "Прилючена", "maintenanceStatus-ended": "Приключена",
"maintenanceStatus-unknown": "Неизвестен", "maintenanceStatus-unknown": "Неизвестна",
"Display Timezone": "Покажи часова зона", "Display Timezone": "Покажи часова зона",
"Server Timezone": "Часова зона на сървъра", "Server Timezone": "Часова зона на сървъра",
statusPageMaintenanceEndDate: "Край", statusPageMaintenanceEndDate: "Край",
enableGRPCTls: "Разреши изпращане на gRPC заявка с TLS връзка",
grpcMethodDescription: "Името на метода се форматира в \"cammelCase\", например sayHello, check, и т.н.",
smseagle: "SMSEagle",
smseagleTo: "Тел. номер(а)",
smseagleGroup: "Име на група/и от тел. указател",
smseagleContact: "Име(на) от тел. указател",
smseagleRecipientType: "Получател тип",
smseagleRecipient: "Получател(и) (при повече от един разделете със запетая)",
smseagleToken: "API токен за достъп",
smseagleUrl: "Вашият SMSEagle URL на устройството",
smseagleEncoding: "Изпрати като Unicode",
smseaglePriority: "Приоритет на съобщението (0-9, по подразбиране = 0)",
IconUrl: "Икона URL адрес",
}; };

View file

@ -49,11 +49,14 @@
MQTT MQTT
</option> </option>
<option value="sqlserver"> <option value="sqlserver">
SQL Server Microsoft SQL Server
</option> </option>
<option value="postgres"> <option value="postgres">
PostgreSQL PostgreSQL
</option> </option>
<option value="mysql">
MySQL/MariaDB
</option>
<option value="radius"> <option value="radius">
Radius Radius
</option> </option>
@ -244,8 +247,8 @@
</div> </div>
</template> </template>
<!-- SQL Server and PostgreSQL --> <!-- SQL Server / PostgreSQL / MySQL -->
<template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres'"> <template v-if="monitor.type === 'sqlserver' || monitor.type === 'postgres' || monitor.type === 'mysql'">
<div class="my-3"> <div class="my-3">
<label for="sqlConnectionString" class="form-label">{{ $t("Connection String") }}</label> <label for="sqlConnectionString" class="form-label">{{ $t("Connection String") }}</label>
@ -255,6 +258,9 @@
<template v-if="monitor.type === 'postgres'"> <template v-if="monitor.type === 'postgres'">
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="postgres://username:password@host:port/database"> <input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="postgres://username:password@host:port/database">
</template> </template>
<template v-if="monitor.type === 'mysql'">
<input id="sqlConnectionString" v-model="monitor.databaseConnectionString" type="text" class="form-control" placeholder="mysql://username:password@host:port/database">
</template>
</div> </div>
<div class="my-3"> <div class="my-3">
<label for="sqlQuery" class="form-label">{{ $t("Query") }}</label> <label for="sqlQuery" class="form-label">{{ $t("Query") }}</label>