From 319edddae5633133b2c19c1518289fcbfcfb8a46 Mon Sep 17 00:00:00 2001 From: Amirparsa Baghdadi <76398455+amirparsadd@users.noreply.github.com> Date: Thu, 13 Nov 2025 18:04:01 +0330 Subject: [PATCH 01/29] feat: Multi number notifications for SMSIR (#6346) --- server/notification-providers/smsir.js | 47 ++++++++++++++++---------- src/components/notifications/SMSIR.vue | 4 +-- src/lang/en.json | 3 +- 3 files changed, 33 insertions(+), 21 deletions(-) diff --git a/server/notification-providers/smsir.js b/server/notification-providers/smsir.js index 159eccb2c..2adc46b3d 100644 --- a/server/notification-providers/smsir.js +++ b/server/notification-providers/smsir.js @@ -21,26 +21,37 @@ class SMSIR extends NotificationProvider { }; config = this.getAxiosConfigWithProxy(config); - let formattedMobile = notification.smsirNumber; - if (formattedMobile.length === 11 && formattedMobile.startsWith("09") && String(parseInt(formattedMobile)) === formattedMobile.substring(1)) { - // 09xxxxxxxxx Format - formattedMobile = formattedMobile.substring(1); - } + const formattedMobiles = notification.smsirNumber + .split(",") + .map(mobile => { + if (mobile.length === 11 && mobile.startsWith("09") && String(parseInt(mobile)) === mobile.substring(1)) { + // 09xxxxxxxxx Format + return mobile.substring(1); + } - await axios.post( - url, - { - mobile: formattedMobile, - templateId: parseInt(notification.smsirTemplate), - parameters: [ + return mobile; + }); + + // Run multiple network requests at once + const requestPromises = formattedMobiles + .map(mobile => { + axios.post( + url, { - name: "uptkumaalert", - value: msg - } - ] - }, - config - ); + mobile: mobile, + templateId: parseInt(notification.smsirTemplate), + parameters: [ + { + name: "uptkumaalert", + value: msg + } + ] + }, + config + ); + }); + + await Promise.all(requestPromises); return okMsg; } catch (error) { diff --git a/src/components/notifications/SMSIR.vue b/src/components/notifications/SMSIR.vue index e5e0e6407..6ae6e96c3 100644 --- a/src/components/notifications/SMSIR.vue +++ b/src/components/notifications/SMSIR.vue @@ -4,8 +4,8 @@
- - + +
diff --git a/src/lang/en.json b/src/lang/en.json index e1c2d8ab2..beecc5e4f 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -1186,5 +1186,6 @@ "Number of retry attempts if webhook fails": "Number of retry attempts (every 60-180 seconds) if the webhook fails.", "Maximum Retries": "Maximum Retries", "Template ID": "Template ID", - "wayToGetClickSMSIRTemplateID": "Your template must contain an {uptkumaalert} field. You can create a new template {here}." + "wayToGetClickSMSIRTemplateID": "Your template must contain an {uptkumaalert} field. You can create a new template {here}.", + "Recipient Numbers": "Recipient Numbers" } From dda1a3f4427aa3431e717f00ee189a4fe056a02b Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sat, 15 Nov 2025 21:55:38 +0100 Subject: [PATCH 02/29] Chore:extracted the redis monitor to a different monitoring type (#4393) Co-authored-by: Louis Lam --- package-lock.json | 105 +++++++++----------- package.json | 2 +- server/model/monitor.js | 9 +- server/monitor-types/redis.js | 57 +++++++++++ server/uptime-kuma-server.js | 3 + server/util-server.js | 39 -------- test/manual-test-radius-tls/certs/redis.crt | 19 ++++ test/manual-test-radius-tls/certs/redis.key | 28 ++++++ test/manual-test-radius-tls/compose.yaml | 15 +++ test/manual-test-radius/compose.yaml | 8 ++ 10 files changed, 180 insertions(+), 105 deletions(-) create mode 100644 server/monitor-types/redis.js create mode 100644 test/manual-test-radius-tls/certs/redis.crt create mode 100644 test/manual-test-radius-tls/certs/redis.key create mode 100644 test/manual-test-radius-tls/compose.yaml create mode 100644 test/manual-test-radius/compose.yaml diff --git a/package-lock.json b/package-lock.json index 420b7a923..36c6c3bc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -76,7 +76,7 @@ "qs": "~6.10.4", "radius": "~1.1.4", "redbean-node": "~0.3.0", - "redis": "~4.5.1", + "redis": "~5.9.0", "semver": "~7.5.4", "socket.io": "~4.8.0", "socket.io-client": "~4.8.0", @@ -2718,62 +2718,63 @@ "license": "BSD-3-Clause" }, "node_modules/@redis/bloom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz", - "integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.9.0.tgz", + "integrity": "sha512-W9D8yfKTWl4tP8lkC3MRYkMz4OfbuzE/W8iObe0jFgoRmgMfkBV+Vj38gvIqZPImtY0WB34YZkX3amYuQebvRQ==", "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "^5.9.0" } }, "node_modules/@redis/client": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", - "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.9.0.tgz", + "integrity": "sha512-EI0Ti5pojD2p7TmcS7RRa+AJVahdQvP/urpcSbK/K9Rlk6+dwMJTQ354pCNGCwfke8x4yKr5+iH85wcERSkwLQ==", "license": "MIT", "dependencies": { - "cluster-key-slot": "1.1.1", - "generic-pool": "3.9.0", - "yallist": "4.0.0" + "cluster-key-slot": "1.1.2" }, "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/graph": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", - "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" + "node": ">= 18" } }, "node_modules/@redis/json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", - "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.9.0.tgz", + "integrity": "sha512-Bm2jjLYaXdUWPb9RaEywxnjmzw7dWKDZI4MS79mTWPV16R982jVWBj6lY2ZGelJbwxHtEVg4/FSVgYDkuO/MxA==", "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "^5.9.0" } }, "node_modules/@redis/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", - "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.9.0.tgz", + "integrity": "sha512-jdk2csmJ29DlpvCIb2ySjix2co14/0iwIT3C0I+7ZaToXgPbgBMB+zfEilSuncI2F9JcVxHki0YtLA0xX3VdpA==", "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "^5.9.0" } }, "node_modules/@redis/time-series": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", - "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.9.0.tgz", + "integrity": "sha512-W6ILxcyOqhnI7ELKjJXOktIg3w4+aBHugDbVpgVLPZ+YDjObis1M0v7ZzwlpXhlpwsfePfipeSK+KWNuymk52w==", "license": "MIT", + "engines": { + "node": ">= 18" + }, "peerDependencies": { - "@redis/client": "^1.0.0" + "@redis/client": "^5.9.0" } }, "node_modules/@rollup/rollup-android-arm-eabi": { @@ -6116,9 +6117,9 @@ } }, "node_modules/cluster-key-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", - "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", "license": "Apache-2.0", "engines": { "node": ">=0.10.0" @@ -8927,15 +8928,6 @@ "node": ">= 0.4" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -13508,20 +13500,19 @@ } }, "node_modules/redis": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/redis/-/redis-4.5.1.tgz", - "integrity": "sha512-oxXSoIqMJCQVBTfxP6BNTCtDMyh9G6Vi5wjdPdV/sRKkufyZslDqCScSGcOr6XGR/reAWZefz7E4leM31RgdBA==", + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-5.9.0.tgz", + "integrity": "sha512-E8dQVLSyH6UE/C9darFuwq4usOPrqfZ1864kI4RFbr5Oj9ioB9qPF0oJMwX7s8mf6sPYrz84x/Dx1PGF3/0EaQ==", "license": "MIT", - "workspaces": [ - "./packages/*" - ], "dependencies": { - "@redis/bloom": "1.1.0", - "@redis/client": "1.4.2", - "@redis/graph": "1.1.0", - "@redis/json": "1.0.4", - "@redis/search": "1.1.0", - "@redis/time-series": "1.0.4" + "@redis/bloom": "5.9.0", + "@redis/client": "5.9.0", + "@redis/json": "5.9.0", + "@redis/search": "5.9.0", + "@redis/time-series": "5.9.0" + }, + "engines": { + "node": ">= 18" } }, "node_modules/reflect.getprototypeof": { diff --git a/package.json b/package.json index d9614df7f..9e3c7bf84 100644 --- a/package.json +++ b/package.json @@ -137,7 +137,7 @@ "radius": "~1.1.4", "node-radius-utils": "~1.2.0", "redbean-node": "~0.3.0", - "redis": "~4.5.1", + "redis": "~5.9.0", "semver": "~7.5.4", "socket.io": "~4.8.0", "socket.io-client": "~4.8.0", diff --git a/server/model/monitor.js b/server/model/monitor.js index 398378292..a442c0ab5 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -9,7 +9,7 @@ const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MI PING_PER_REQUEST_TIMEOUT_MIN, PING_PER_REQUEST_TIMEOUT_MAX, PING_PER_REQUEST_TIMEOUT_DEFAULT } = require("../../src/util"); const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery, - redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal + kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); @@ -851,13 +851,6 @@ class Monitor extends BeanModel { bean.msg = resp.code; bean.status = UP; bean.ping = dayjs().valueOf() - startTime; - } else if (this.type === "redis") { - let startTime = dayjs().valueOf(); - - bean.msg = await redisPingAsync(this.databaseConnectionString, !this.ignoreTls); - bean.status = UP; - bean.ping = dayjs().valueOf() - startTime; - } else if (this.type in UptimeKumaServer.monitorTypeList) { let startTime = dayjs().valueOf(); const monitorType = UptimeKumaServer.monitorTypeList[this.type]; diff --git a/server/monitor-types/redis.js b/server/monitor-types/redis.js new file mode 100644 index 000000000..72b078eb2 --- /dev/null +++ b/server/monitor-types/redis.js @@ -0,0 +1,57 @@ +const { MonitorType } = require("./monitor-type"); +const { UP } = require("../../src/util"); +const redis = require("redis"); + +class RedisMonitorType extends MonitorType { + name = "redis"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, _server) { + heartbeat.msg = await this.redisPingAsync(monitor.databaseConnectionString, !monitor.ignoreTls); + heartbeat.status = UP; + } + + /** + * Redis server ping + * @param {string} dsn The redis connection string + * @param {boolean} rejectUnauthorized If false, allows unverified server certificates. + * @returns {Promise} Response from redis server + */ + redisPingAsync(dsn, rejectUnauthorized) { + return new Promise((resolve, reject) => { + const client = redis.createClient({ + url: dsn, + socket: { + rejectUnauthorized + } + }); + client.on("error", (err) => { + if (client.isOpen) { + client.disconnect(); + } + reject(err); + }); + client.connect().then(() => { + if (!client.isOpen) { + client.emit("error", new Error("connection isn't open")); + } + client.ping().then((res, err) => { + if (client.isOpen) { + client.disconnect(); + } + if (err) { + reject(err); + } else { + resolve(res); + } + }).catch(error => reject(error)); + }); + }); + } +} + +module.exports = { + RedisMonitorType, +}; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index a04e6bd49..3c84bf646 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -119,6 +119,7 @@ class UptimeKumaServer { UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); UptimeKumaServer.monitorTypeList["manual"] = new ManualMonitorType(); + UptimeKumaServer.monitorTypeList["redis"] = new RedisMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -560,4 +561,6 @@ const { SNMPMonitorType } = require("./monitor-types/snmp"); const { MongodbMonitorType } = require("./monitor-types/mongodb"); const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); const { ManualMonitorType } = require("./monitor-types/manual"); +const { RedisMonitorType } = require("./monitor-types/redis"); const Monitor = require("./model/monitor"); + diff --git a/server/util-server.js b/server/util-server.js index 462b80578..3de6e777f 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -20,7 +20,6 @@ const { Settings } = require("./settings"); const grpc = require("@grpc/grpc-js"); const protojs = require("protobufjs"); const RadiusClient = require("./radius-client"); -const redis = require("redis"); const oidc = require("openid-client"); const tls = require("tls"); const { exists } = require("fs"); @@ -523,44 +522,6 @@ exports.radius = function ( }); }; -/** - * Redis server ping - * @param {string} dsn The redis connection string - * @param {boolean} rejectUnauthorized If false, allows unverified server certificates. - * @returns {Promise} Response from server - */ -exports.redisPingAsync = function (dsn, rejectUnauthorized) { - return new Promise((resolve, reject) => { - const client = redis.createClient({ - url: dsn, - socket: { - rejectUnauthorized - } - }); - client.on("error", (err) => { - if (client.isOpen) { - client.disconnect(); - } - reject(err); - }); - client.connect().then(() => { - if (!client.isOpen) { - client.emit("error", new Error("connection isn't open")); - } - client.ping().then((res, err) => { - if (client.isOpen) { - client.disconnect(); - } - if (err) { - reject(err); - } else { - resolve(res); - } - }).catch(error => reject(error)); - }); - }); -}; - /** * Retrieve value of setting based on key * @param {string} key Key of setting to retrieve diff --git a/test/manual-test-radius-tls/certs/redis.crt b/test/manual-test-radius-tls/certs/redis.crt new file mode 100644 index 000000000..29e371978 --- /dev/null +++ b/test/manual-test-radius-tls/certs/redis.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDCTCCAfGgAwIBAgIUF6AMqH3K5nlbnWuHAMu12MUjqCUwDQYJKoZIhvcNAQEL +BQAwFDESMBAGA1UEAwwJbG9jYWxob3N0MB4XDTI1MTExNTIwMTk0OFoXDTI2MTEx +NTIwMTk0OFowFDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEF +AAOCAQ8AMIIBCgKCAQEAtRVPm2BOFyaRoFVP3g+OO8YYvUUzVnMlp8T+FkQUWQ3g +Xzk3k059ca67uPhfujRQ0S+e4FTPyHPrbCh73aTtFfpg1BTlEcuOAXUpxrtSpXbY +D4XvO5OZK3QmFIkUOfOMoJoi0Iv75CgVlcGnQOxPY5A12+uyzMNGPFWBX42qgeW9 +huijfqE3jwN2gM05ryA6EBk1TIewUTMycTFI3t3YLJyZdNMG4kmphIJ/Ie6Na4u3 +YaKXp9o+VCN8t5bd/IYhFW8PznlXbv2NU83ARjmfk7Vc0OrvTUsr9+NTPOdFFoCp +sAbxogO/hZpv3UtX9lzk22MpzcBbpzPodXAikNZeswIDAQABo1MwUTAdBgNVHQ4E +FgQU9PhfZPxI1PB50DdRrI82U1cRPvkwHwYDVR0jBBgwFoAU9PhfZPxI1PB50DdR +rI82U1cRPvkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAclr4 +M5PjA1nqTZfbdaerA5uvyPnIdjc6Ms6ZvP75h6kHxvUJj9kcoSbg/2nqyCY6UJod +oOPTJZppB+xfHD6ahPLO30IPw1HPr+OfTaiwBoZMnjGn08p5dAjyG0hAyHciDClY +UAxQld+5NNI82QEx5BJ3mcpO5Mi36SW7Kck2TnCza6JxjOmtFi4BLMFsnRD9Vepu +vIvu3DrCxnpYdCV6zUT55414NKCPsut7YHqkDc4gOUHcQ0QOQSRwhaGpLnkfwihe +DkHgJvcBlBOMcr2UCQvXPwPPP1dJ4Y9OQrjGxCnSeDy89cu5/6z/ZBy2ygGHehGZ +zx5PrQLiqgdChdwb6w== +-----END CERTIFICATE----- diff --git a/test/manual-test-radius-tls/certs/redis.key b/test/manual-test-radius-tls/certs/redis.key new file mode 100644 index 000000000..a3e02b210 --- /dev/null +++ b/test/manual-test-radius-tls/certs/redis.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC1FU+bYE4XJpGg +VU/eD447xhi9RTNWcyWnxP4WRBRZDeBfOTeTTn1xrru4+F+6NFDRL57gVM/Ic+ts +KHvdpO0V+mDUFOURy44BdSnGu1KldtgPhe87k5krdCYUiRQ584ygmiLQi/vkKBWV +wadA7E9jkDXb67LMw0Y8VYFfjaqB5b2G6KN+oTePA3aAzTmvIDoQGTVMh7BRMzJx +MUje3dgsnJl00wbiSamEgn8h7o1ri7dhopen2j5UI3y3lt38hiEVbw/OeVdu/Y1T +zcBGOZ+TtVzQ6u9NSyv341M850UWgKmwBvGiA7+Fmm/dS1f2XOTbYynNwFunM+h1 +cCKQ1l6zAgMBAAECggEAcfZ4hEOmwcEfMzWdrxZBIHM6jJtphMWw9BXxBthPqgAm +ricXR9jE7+/U6sM9k7VrC0uaBHq7zd7OUeJkmgg6wXMyzyZbR8jAlUBES3MGv2W8 +8oALIIZyhjtx38ipdxNE9KossOz4WQ21D+uxNBXEnNdcXgzHGUDoCf6SDi3dGiQI +kloSkoyuHv3HiJdmUCII0EWVoDW0YnhKs4xpYwt0xlQ3IFA1FeqhYN3GwDb7hnp4 +HmefiydHW+rWPgXPzI3tIo6LgN+nMBPAAa95u9XfswRmBcZIhTxzlg7HaJJ1yP2B +HmyJBG20HX1RY0IHAgAQy2jA2HPIRdpQNU2FJGi34QKBgQDvMDRqr6qQjLSq8dkG +H7olc10gZHHTyY25aQG+m54SXMEdmU5zhbMoShnfQ/HVtWCAd3b5kwUBSjXacQiL +kMBV6S5+FQ+27nfgx8szqUJJi09iU43xcBDYSyJCohkM/HrHSElN3c1Y9//SneqJ +Zjeg+80+p7LvsgMM4MOKad0DowKBgQDBz5o9m9FZ+nHC1eXwUYVYNXA9wter9Erd +WosPWKnhGTJ2mNebn0aSVlagiZtyMUMps4IyWEvBHMIt0wJz2T5v+SDx9VN0si7q +Jy1i1uDO56tSHDZaN+QT/WDeaHTpzl3I28K7lqM6PDx1KQ/kqlTnWHD3wnXQ2Hfh +xXYgdeNpsQKBgQDaT+w3yBhtERBByrZkIYc8cXx5eVRvktJ5fX9rIwx3BBP7WRdC +17B7QI82ugQ8I+1ttBxylR8HW12mAG9lO3xhrZCS4dRTCnt+Pb2ZbI6lI7MUMuEm +kju9v24I1Xz53mSOCctmd+DaqJjl+t68BAEYPVvLKTNoFdk04t13M0LX8wKBgQCU +7+/M5oA0UES6AFxKmKsLRU2y+Jd6miop/tmcentZ814XS49tFTJLZLP/fKALWhYN +5tfnzniwt2P1iRF6a3kS3XVW2zs+E2wAHwk+ynhKKDg8yldub0MDpZSaddVak274 +2wDD3ZgkOYQQWPTQuaCzhACUNUkKrD88Ld2ARnfzkQKBgGTEOwN+aaOn/bU9Dm+y +Xg1tezMmxFcnewZVak+91xU6K+PS9B3GbszAs5MMYXo3UQXCUlXUI71XI7WG50LJ +NmwClF05ZcH/qYpp1mK/w6i+7VnqN0RAkD0hA3AyivmF5VCI/hzZanxLnPDvMbxS +wpjLPuBRTukoNvxJGT16z8L+ +-----END PRIVATE KEY----- diff --git a/test/manual-test-radius-tls/compose.yaml b/test/manual-test-radius-tls/compose.yaml new file mode 100644 index 000000000..d6ff8337c --- /dev/null +++ b/test/manual-test-radius-tls/compose.yaml @@ -0,0 +1,15 @@ +# Start the server: +# docker compose up +services: + redis: + image: redis:latest + ports: + - "6380:6380" + volumes: + - ./certs:/certs + command: > + redis-server + --tls-port 6380 --port 0 + --tls-cert-file /certs/redis.crt + --tls-key-file /certs/redis.key + --tls-auth-clients no diff --git a/test/manual-test-radius/compose.yaml b/test/manual-test-radius/compose.yaml new file mode 100644 index 000000000..7f2b1fc81 --- /dev/null +++ b/test/manual-test-radius/compose.yaml @@ -0,0 +1,8 @@ +# Start the server: +# docker compose up +services: + redis: + image: redis:latest + ports: + - "6379:6379" + command: redis-server --port 6379 From f9751bfd81fee622a3cc6ef9eba11894fc245978 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sun, 16 Nov 2025 22:40:35 +0800 Subject: [PATCH 03/29] Update security reporting instructions in SECURITY.md (#6355) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- SECURITY.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index ad252370b..34111c258 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -8,7 +8,8 @@ do not send a notification, I probably will miss it without this. -Do not use the public issue tracker or discuss it in public as it will cause +- Do not report any upstream dependency issues / scan result by any tools. It will be closed immediately without explanations. Unless you have PoC to prove that the upstream issue affected Uptime Kuma. +- Do not use the public issue tracker or discuss it in public as it will cause more damage. ## Do you accept other 3rd-party bug bounty platforms? From 2e3b31716d0e40ab1b24b2297d4d0f828c2eb004 Mon Sep 17 00:00:00 2001 From: SomeoneVeryCool Date: Mon, 17 Nov 2025 13:21:08 -0500 Subject: [PATCH 04/29] feat: Add Messaging Service SID option for Twilio (#6347) Co-authored-by: Frank Elsinga --- server/notification-providers/twilio.js | 3 +++ src/components/notifications/Twilio.vue | 27 +++++++++++++++---------- src/lang/en.json | 3 +++ 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/server/notification-providers/twilio.js b/server/notification-providers/twilio.js index f198f3623..60a7b60e9 100644 --- a/server/notification-providers/twilio.js +++ b/server/notification-providers/twilio.js @@ -25,6 +25,9 @@ class Twilio extends NotificationProvider { data.append("To", notification.twilioToNumber); data.append("From", notification.twilioFromNumber); data.append("Body", msg); + if (notification.twilioMessagingServiceSID) { + data.append("MessagingServiceSid", notification.twilioMessagingServiceSID); + } await axios.post(`https://api.twilio.com/2010-04-01/Accounts/${(notification.twilioAccountSID)}/Messages.json`, data, config); diff --git a/src/components/notifications/Twilio.vue b/src/components/notifications/Twilio.vue index d923866b0..3dfe162bc 100644 --- a/src/components/notifications/Twilio.vue +++ b/src/components/notifications/Twilio.vue @@ -1,32 +1,37 @@