From 3f0b85e5a88d65e88b7df138ae237e7cd90dbd41 Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sat, 2 Oct 2021 16:48:27 +0200 Subject: [PATCH 01/24] feat(http-requests): add support for methods, body and headers for http --- ...h-http-monitor-method-body-and-headers.sql | 13 +++ server/database.js | 1 + server/model/monitor.js | 37 +++++++- server/server.js | 6 ++ src/assets/app.scss | 6 +- src/assets/multiselect.scss | 2 +- src/components/HeartbeatBar.vue | 2 +- src/pages/EditMonitor.vue | 84 ++++++++++++++++++- 8 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 db/patch-http-monitor-method-body-and-headers.sql diff --git a/db/patch-http-monitor-method-body-and-headers.sql b/db/patch-http-monitor-method-body-and-headers.sql new file mode 100644 index 000000000..dc2526b4f --- /dev/null +++ b/db/patch-http-monitor-method-body-and-headers.sql @@ -0,0 +1,13 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE monitor + ADD method TEXT default 'GET' not null; + +ALTER TABLE monitor + ADD body TEXT default null; + +ALTER TABLE monitor + ADD headers TEXT default null; + +COMMIT; diff --git a/server/database.js b/server/database.js index 47eca2835..297df655a 100644 --- a/server/database.js +++ b/server/database.js @@ -49,6 +49,7 @@ class Database { "patch-incident-table.sql": true, "patch-group-table.sql": true, "patch-monitor-push_token.sql": true, + "patch-http-monitor-method-body-and-headers.sql": true, } /** diff --git a/server/model/monitor.js b/server/model/monitor.js index c551fa7d7..dc95753db 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -53,6 +53,9 @@ class Monitor extends BeanModel { id: this.id, name: this.name, url: this.url, + method: this.method, + body: this.body, + headers: this.headers, hostname: this.hostname, port: this.port, maxretries: this.maxretries, @@ -95,6 +98,31 @@ class Monitor extends BeanModel { return JSON.parse(this.accepted_statuscodes_json); } + /** + * Convert header string into an object: + * eg: + * + * Authorization: Basic + * Content-Type: application/json + * + * into + * + * { + * "Authorization": "Basic ", + * "Content-Type": "application/json" + * } + **/ + getParsedHeaders() { + if (!this.headers || !this.headers.includes(":")) { + return {}; + } + return Object.fromEntries(this.headers.split("\n").map(header => { + const trimmedHeader = header.trim(); + const firstColonIndex = trimmedHeader.indexOf(":"); + return [trimmedHeader.slice(0, firstColonIndex), trimmedHeader.slice(firstColonIndex + 1) || ""]; + }).filter(arr => !!arr[0] && !!arr[1])); + } + start(io) { let previousBeat = null; let retries = 0; @@ -136,11 +164,15 @@ class Monitor extends BeanModel { // Do not do any queries/high loading things before the "bean.ping" let startTime = dayjs().valueOf(); - let res = await axios.get(this.url, { + const options = { + url: this.url, + method: (this.method || "get").toLowerCase(), + ...(this.body ? { data: JSON.parse(this.body) } : {}), timeout: this.interval * 1000 * 0.8, headers: { "Accept": "*/*", "User-Agent": "Uptime-Kuma/" + version, + ...this.getParsedHeaders(), }, httpsAgent: new https.Agent({ maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) @@ -150,7 +182,8 @@ class Monitor extends BeanModel { validateStatus: (status) => { return checkStatusCode(status, this.getAcceptedStatuscodes()); }, - }); + }; + let res = await axios.request(options); bean.msg = `${res.status} - ${res.statusText}`; bean.ping = dayjs().valueOf() - startTime; diff --git a/server/server.js b/server/server.js index 0fbe8325b..6d1a939f3 100644 --- a/server/server.js +++ b/server/server.js @@ -505,6 +505,9 @@ exports.entryPage = "dashboard"; bean.name = monitor.name; bean.type = monitor.type; bean.url = monitor.url; + bean.method = monitor.method; + bean.body = monitor.body; + bean.headers = monitor.headers; bean.interval = monitor.interval; bean.retryInterval = monitor.retryInterval; bean.hostname = monitor.hostname; @@ -1028,6 +1031,9 @@ exports.entryPage = "dashboard"; name: monitorListData[i].name, type: monitorListData[i].type, url: monitorListData[i].url, + method: monitorListData[i].method || "GET", + body: monitorListData[i].body, + headers: monitorListData[i].headers, interval: monitorListData[i].interval, retryInterval: retryInterval, hostname: monitorListData[i].hostname, diff --git a/src/assets/app.scss b/src/assets/app.scss index 34a4560c5..fdb57b431 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -14,6 +14,10 @@ h2 { font-size: 26px; } +textarea.form-control { + border-radius: 19px; +} + ::-webkit-scrollbar { width: 10px; } @@ -413,4 +417,4 @@ h2 { // Localization -@import "localization.scss"; \ No newline at end of file +@import "localization.scss"; diff --git a/src/assets/multiselect.scss b/src/assets/multiselect.scss index 300230769..53b47c16e 100644 --- a/src/assets/multiselect.scss +++ b/src/assets/multiselect.scss @@ -21,7 +21,7 @@ } .multiselect__tag { - border-radius: 50rem; + border-radius: $border-radius; margin-bottom: 0; padding: 6px 26px 6px 10px; background: $primary !important; diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index 4dc2c712c..e62b95dfb 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -186,7 +186,7 @@ export default { .beat { display: inline-block; background-color: $primary; - border-radius: 50rem; + border-radius: $border-radius; &.empty { background-color: aliceblue; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 96f221e8b..e63f49862 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -44,6 +44,46 @@ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
@@ -285,6 +325,18 @@ export default { pushURL() { return this.$root.baseURL + "/api/push/" + this.monitor.pushToken + "?msg=OK&ping="; + }, + + bodyPlaceholder() { + return `{ + "id": 124357, + "username": "admin", + "password": "myAdminPassword" +}`; + }, + + headersPlaceholder() { + return "Authorization: Bearer abc123\nContent-Type: application/json"; } }, @@ -295,7 +347,7 @@ export default { }, "monitor.interval"(value, oldValue) { - // Link interval and retryInerval if they are the same value. + // Link interval and retryInterval if they are the same value. if (this.monitor.retryInterval === oldValue) { this.monitor.retryInterval = value; } @@ -349,6 +401,7 @@ export default { type: "http", name: "", url: "https://", + method: "GET", interval: 60, retryInterval: this.interval, maxretries: 0, @@ -383,9 +436,32 @@ export default { }, + isInputValid() { + if (this.monitor.body) { + try { + JSON.parse(this.monitor.body); + } catch (err) { + toast.error(this.$t("The request body is not valid json: ") + err.message); + return false; + } + } + if (this.monitor.headers) { + if (!/^([^:]+:.*)([\s]+[^:]+:.*)+$/g.test(this.monitor.headers)) { + toast.error(this.$t("Headers do not have a valid format: \"key: valuekey: value...\"")); + return false; + } + } + return true; + }, + async submit() { this.processing = true; + if (!this.isInputValid()) { + this.processing = false; + return; + } + if (this.isAdd) { this.$root.add(this.monitor, async (res) => { @@ -422,8 +498,12 @@ export default { }; - From 7ee89fab5c19dc9acc11a041b3abd03fe934d03b Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Mon, 4 Oct 2021 11:29:43 +0200 Subject: [PATCH 02/24] fix(edit-monitor): Make json capitalised Co-authored-by: Adam Stachowicz --- src/pages/EditMonitor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index e63f49862..30cf1da0b 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -441,7 +441,7 @@ export default { try { JSON.parse(this.monitor.body); } catch (err) { - toast.error(this.$t("The request body is not valid json: ") + err.message); + toast.error(this.$t("The request body is not valid JSON: ") + err.message); return false; } } From afeb424dc05b45586967edb6ea9f2ec429b6a2ad Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Tue, 5 Oct 2021 09:20:24 +0200 Subject: [PATCH 03/24] fix(edit-monitor): add translations to en.js --- src/languages/en.js | 8 ++++++++ src/pages/EditMonitor.vue | 14 +++++--------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 46298b015..db3928da3 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -195,4 +195,12 @@ export default { "pushbullet": "Pushbullet", "line": "Line Messenger", "mattermost": "Mattermost", + Method: "Method", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + HeadersInvalidFormat: "Headers do not have a valid format: \"key: value key: value ...\"", + BodyInvalidFormat: "The request body is not valid JSON: ", + BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}", + HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 30cf1da0b..df3b211fd 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -86,7 +86,7 @@
- +
You should call this url every {{ monitor.interval }} seconds.
@@ -328,15 +328,11 @@ export default { }, bodyPlaceholder() { - return `{ - "id": 124357, - "username": "admin", - "password": "myAdminPassword" -}`; + return this.$t("BodyPlaceholder"); }, headersPlaceholder() { - return "Authorization: Bearer abc123\nContent-Type: application/json"; + return this.$t("HeadersPlaceholder"); } }, @@ -441,13 +437,13 @@ export default { try { JSON.parse(this.monitor.body); } catch (err) { - toast.error(this.$t("The request body is not valid JSON: ") + err.message); + toast.error(this.$t("BodyInvalidFormat") + err.message); return false; } } if (this.monitor.headers) { if (!/^([^:]+:.*)([\s]+[^:]+:.*)+$/g.test(this.monitor.headers)) { - toast.error(this.$t("Headers do not have a valid format: \"key: valuekey: value...\"")); + toast.error(this.$t("HeadersInvalidFormat")); return false; } } From a0ffa42b42ea2ecd4408c0fa94aaddc50994f31b Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Tue, 5 Oct 2021 18:21:31 +0200 Subject: [PATCH 04/24] fix(translations): add translations for method body and headers to dutch --- src/languages/nl-NL.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/languages/nl-NL.js b/src/languages/nl-NL.js index 5fa9d4e1a..af08bfc7c 100644 --- a/src/languages/nl-NL.js +++ b/src/languages/nl-NL.js @@ -179,4 +179,12 @@ export default { "Add a monitor": "Add a monitor", "Edit Status Page": "Edit Status Page", "Go to Dashboard": "Go to Dashboard", + Method: "Methode", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + HeadersInvalidFormat: "Headers hebben een incorrect formaat: \"key: waarde key: waarde ...\"", + BodyInvalidFormat: "De request body is geen geldige JSON: ", + BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"gebruikersnaam\": \"admin\",\n\t\"wachtwoord\": \"mijnAdminWachtwoord\"\n}", + HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", }; From c3c273f9df86a7f1c17dfa827afb455c9d61381b Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sat, 9 Oct 2021 11:20:33 +0200 Subject: [PATCH 05/24] fix(edit-monitor): fix regex to allow a single header --- src/pages/EditMonitor.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 96448c6d4..852a266f9 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -442,7 +442,7 @@ export default { } } if (this.monitor.headers) { - if (!/^([^:]+:.*)([\s]+[^:]+:.*)+$/g.test(this.monitor.headers)) { + if (!/^([^:]+:.*)([\s]+[^:]+:.*)*$/g.test(this.monitor.headers)) { toast.error(this.$t("HeadersInvalidFormat")); return false; } From b8093e909b764ebc48573a2e57ed39eb6e3127f3 Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sat, 9 Oct 2021 11:38:12 +0200 Subject: [PATCH 06/24] fix(edit-monitor): fix minification of translations containing { } --- src/languages/en.js | 5 ++--- src/languages/nl-NL.js | 2 +- src/pages/EditMonitor.vue | 10 ++++++++-- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 8b1c28d3d..7871f0fe7 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -277,17 +277,16 @@ export default { promosmsTypeEco: "SMS ECO - cheap but slow and often overloaded. Limited only to Polish recipients.", promosmsTypeFlash: "SMS FLASH - Message will automatically show on recipient device. Limited only to Polish recipients.", promosmsTypeFull: "SMS FULL - Premium tier of SMS, You can use Your Sender Name (You need to register name first). Reliable for alerts.", - promosmsTypeFull: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).", + promosmsTypeSpeed: "SMS SPEED - Highest priority in system. Very quick and reliable but costly (about twice of SMS FULL price).", promosmsPhoneNumber: "Phone number (for Polish recipient You can skip area codes)", promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS", // End notification form - "Status Page": "Status Page", Method: "Method", Body: "Body", Headers: "Headers", PushUrl: "Push URL", HeadersInvalidFormat: "Headers do not have a valid format: \"key: value key: value ...\"", BodyInvalidFormat: "The request body is not valid JSON: ", - BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}", + BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}", HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", }; diff --git a/src/languages/nl-NL.js b/src/languages/nl-NL.js index a9e8f6a37..33d84cd5a 100644 --- a/src/languages/nl-NL.js +++ b/src/languages/nl-NL.js @@ -204,6 +204,6 @@ export default { PushUrl: "Push URL", HeadersInvalidFormat: "Headers hebben een incorrect formaat: \"key: waarde key: waarde ...\"", BodyInvalidFormat: "De request body is geen geldige JSON: ", - BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"gebruikersnaam\": \"admin\",\n\t\"wachtwoord\": \"mijnAdminWachtwoord\"\n}", + BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"gebruikersnaam\": \"admin\",\n\t\"wachtwoord\": \"mijnAdminWachtwoord\"\n}", HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 852a266f9..5074dab95 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -328,11 +328,11 @@ export default { }, bodyPlaceholder() { - return this.$t("BodyPlaceholder"); + return this.decodeHtml(this.$t("BodyPlaceholder")); }, headersPlaceholder() { - return this.$t("HeadersPlaceholder"); + return this.decodeHtml(this.$t("HeadersPlaceholder")); } }, @@ -490,6 +490,12 @@ export default { addedNotification(id) { this.monitor.notificationIDList[id] = true; }, + + decodeHtml(html) { + const txt = document.createElement("textarea"); + txt.innerHTML = html; + return txt.value; + } }, }; From d71d27220be2bc9832f8a5860172bce32ca9191c Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sat, 9 Oct 2021 12:42:32 +0200 Subject: [PATCH 07/24] fix(edit-monitor): store headers as JSON --- server/model/monitor.js | 27 +-------------------------- src/languages/en.js | 4 ++-- src/languages/nl-NL.js | 4 ++-- src/pages/EditMonitor.vue | 6 ++++-- 4 files changed, 9 insertions(+), 32 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 33ad82f0b..2738898fd 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -99,31 +99,6 @@ class Monitor extends BeanModel { return JSON.parse(this.accepted_statuscodes_json); } - /** - * Convert header string into an object: - * eg: - * - * Authorization: Basic - * Content-Type: application/json - * - * into - * - * { - * "Authorization": "Basic ", - * "Content-Type": "application/json" - * } - **/ - getParsedHeaders() { - if (!this.headers || !this.headers.includes(":")) { - return {}; - } - return Object.fromEntries(this.headers.split("\n").map(header => { - const trimmedHeader = header.trim(); - const firstColonIndex = trimmedHeader.indexOf(":"); - return [trimmedHeader.slice(0, firstColonIndex), trimmedHeader.slice(firstColonIndex + 1) || ""]; - }).filter(arr => !!arr[0] && !!arr[1])); - } - start(io) { let previousBeat = null; let retries = 0; @@ -173,7 +148,7 @@ class Monitor extends BeanModel { headers: { "Accept": "*/*", "User-Agent": "Uptime-Kuma/" + version, - ...this.getParsedHeaders(), + ...JSON.parse(this.headers), }, httpsAgent: new https.Agent({ maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) diff --git a/src/languages/en.js b/src/languages/en.js index 7871f0fe7..a5ad24e05 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -285,8 +285,8 @@ export default { Body: "Body", Headers: "Headers", PushUrl: "Push URL", - HeadersInvalidFormat: "Headers do not have a valid format: \"key: value key: value ...\"", + HeadersInvalidFormat: "The request headers are not valid JSON: ", BodyInvalidFormat: "The request body is not valid JSON: ", BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}", - HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", + HeadersPlaceholder: "{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}", }; diff --git a/src/languages/nl-NL.js b/src/languages/nl-NL.js index 33d84cd5a..170b4a3ce 100644 --- a/src/languages/nl-NL.js +++ b/src/languages/nl-NL.js @@ -202,8 +202,8 @@ export default { Body: "Body", Headers: "Headers", PushUrl: "Push URL", - HeadersInvalidFormat: "Headers hebben een incorrect formaat: \"key: waarde key: waarde ...\"", + HeadersInvalidFormat: "The request headers is geen geldige JSON: ", BodyInvalidFormat: "De request body is geen geldige JSON: ", BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"gebruikersnaam\": \"admin\",\n\t\"wachtwoord\": \"mijnAdminWachtwoord\"\n}", - HeadersPlaceholder: "Authorization: Bearer abc123\nContent-Type: application/json", + HeadersPlaceholder: "{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 5074dab95..ed8b359e4 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -442,8 +442,10 @@ export default { } } if (this.monitor.headers) { - if (!/^([^:]+:.*)([\s]+[^:]+:.*)*$/g.test(this.monitor.headers)) { - toast.error(this.$t("HeadersInvalidFormat")); + try { + JSON.parse(this.monitor.headers); + } catch (err) { + toast.error(this.$t("HeadersInvalidFormat") + err.message); return false; } } From 5137c80c07d8a0781e585d35c86b58252663907e Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sat, 9 Oct 2021 21:51:24 +0200 Subject: [PATCH 08/24] fix(monitor): handle empty headers --- server/model/monitor.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 2738898fd..e2029c5e6 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -148,10 +148,10 @@ class Monitor extends BeanModel { headers: { "Accept": "*/*", "User-Agent": "Uptime-Kuma/" + version, - ...JSON.parse(this.headers), + ...(this.headers ? JSON.parse(this.headers) : {}), }, httpsAgent: new https.Agent({ - maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + maxCachedSessions: 0, // Use "{}"om agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: ! this.getIgnoreTls(), }), maxRedirects: this.maxredirects, From 5445c2a2ffec9cb4c87529e7afdf87737ccfba13 Mon Sep 17 00:00:00 2001 From: Bert Verhelst Date: Sun, 10 Oct 2021 18:41:29 +0200 Subject: [PATCH 09/24] fix(monitor): revert unintentional change to comment --- server/model/monitor.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 094b1c695..21d36000b 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -152,7 +152,7 @@ class Monitor extends BeanModel { ...(this.headers ? JSON.parse(this.headers) : {}), }, httpsAgent: new https.Agent({ - maxCachedSessions: 0, // Use "{}"om agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: ! this.getIgnoreTls(), }), maxRedirects: this.maxredirects, From b5b391c73b1757b3cc6580b679196921328835ea Mon Sep 17 00:00:00 2001 From: Andreas Brett Date: Sun, 10 Oct 2021 22:13:18 +0200 Subject: [PATCH 10/24] avoid default values for token verification override default values: window=1, window size=30 (see https://github.com/louislam/uptime-kuma/issues/640) --- server/server.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index 67095ff53..e5f3335ff 100644 --- a/server/server.js +++ b/server/server.js @@ -265,7 +265,7 @@ exports.entryPage = "dashboard"; } if (data.token) { - let verify = notp.totp.verify(data.token, user.twofa_secret); + let verify = notp.totp.verify(data.token, user.twofa_secret, {"window": 1, "time": 30}); if (verify && verify.delta == 0) { callback({ @@ -383,7 +383,7 @@ exports.entryPage = "dashboard"; socket.userID, ]); - let verify = notp.totp.verify(token, user.twofa_secret); + let verify = notp.totp.verify(token, user.twofa_secret, {"window": 1, "time": 30}); if (verify && verify.delta == 0) { callback({ From e223e826a376b6601dd8ec8e93b71b3a8752f50f Mon Sep 17 00:00:00 2001 From: Andreas Brett Date: Mon, 11 Oct 2021 01:02:54 +0200 Subject: [PATCH 11/24] linting --- server/server.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/server.js b/server/server.js index e5f3335ff..10ec87007 100644 --- a/server/server.js +++ b/server/server.js @@ -265,7 +265,8 @@ exports.entryPage = "dashboard"; } if (data.token) { - let verify = notp.totp.verify(data.token, user.twofa_secret, {"window": 1, "time": 30}); + let verify = notp.totp.verify(data.token, user.twofa_secret, { "window": 1, + "time": 30 }); if (verify && verify.delta == 0) { callback({ @@ -383,7 +384,8 @@ exports.entryPage = "dashboard"; socket.userID, ]); - let verify = notp.totp.verify(token, user.twofa_secret, {"window": 1, "time": 30}); + let verify = notp.totp.verify(token, user.twofa_secret, { "window": 1, + "time": 30 }); if (verify && verify.delta == 0) { callback({ From 2538bd04ce41361481b0252bb00b94aeea1a50f3 Mon Sep 17 00:00:00 2001 From: Andreas Brett Date: Mon, 11 Oct 2021 20:18:40 +0200 Subject: [PATCH 12/24] notp verification defaults --- server/server.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/server/server.js b/server/server.js index 10ec87007..416cfe1f0 100644 --- a/server/server.js +++ b/server/server.js @@ -68,6 +68,12 @@ const port = parseInt(process.env.PORT || args.port || 3001); const sslKey = process.env.SSL_KEY || args["ssl-key"] || undefined; const sslCert = process.env.SSL_CERT || args["ssl-cert"] || undefined; +// 2FA / notp verification defaults +const twofa_verification_opts = { + "window": 1, + "time": 30 +} + /** * Run unit test after the server is ready * @type {boolean} @@ -265,8 +271,7 @@ exports.entryPage = "dashboard"; } if (data.token) { - let verify = notp.totp.verify(data.token, user.twofa_secret, { "window": 1, - "time": 30 }); + let verify = notp.totp.verify(data.token, user.twofa_secret, twofa_verification_opts); if (verify && verify.delta == 0) { callback({ @@ -384,8 +389,7 @@ exports.entryPage = "dashboard"; socket.userID, ]); - let verify = notp.totp.verify(token, user.twofa_secret, { "window": 1, - "time": 30 }); + let verify = notp.totp.verify(token, user.twofa_secret, twofa_verification_opts); if (verify && verify.delta == 0) { callback({ From cd211a6be7c5d4eb0f90055f6ad164b7467de40b Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Fri, 15 Oct 2021 18:36:40 +0800 Subject: [PATCH 13/24] [http options] fine tune --- server/model/monitor.js | 4 ++ server/util-server.js | 2 +- src/languages/en.js | 2 - src/pages/EditMonitor.vue | 90 +++++++++++++++++++++------------------ 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/server/model/monitor.js b/server/model/monitor.js index 85c07cb71..6ec97372c 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -180,6 +180,10 @@ class Monitor extends BeanModel { debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms"); } + if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID == this.id) { + console.log(res.data); + } + if (this.type === "http") { bean.status = UP; } else { diff --git a/server/util-server.js b/server/util-server.js index a65af74a4..7fd613ceb 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -327,7 +327,7 @@ exports.startUnitTest = async () => { */ exports.convertToUTF8 = (body) => { const guessEncoding = chardet.detect(body); - debug("Guess Encoding: " + guessEncoding); + //debug("Guess Encoding: " + guessEncoding); const str = iconv.decode(body, guessEncoding); return str.toString(); }; diff --git a/src/languages/en.js b/src/languages/en.js index fac34a370..aef14c81e 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -288,6 +288,4 @@ export default { PushUrl: "Push URL", HeadersInvalidFormat: "The request headers are not valid JSON: ", BodyInvalidFormat: "The request body is not valid JSON: ", - BodyPlaceholder: "{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}", - HeadersPlaceholder: "{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}", }; diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 374c14e76..f88614415 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -44,46 +44,6 @@
- -
- - -
- - -
- - -
- - -
- - -
-
@@ -235,6 +195,7 @@
+

{{ $t("Notifications") }}

{{ $t("Not available, please setup.") }} @@ -254,6 +215,51 @@ + + +

@@ -328,11 +334,11 @@ export default { }, bodyPlaceholder() { - return this.decodeHtml(this.$t("BodyPlaceholder")); + return this.decodeHtml("{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}"); }, headersPlaceholder() { - return this.decodeHtml(this.$t("HeadersPlaceholder")); + return this.decodeHtml("{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}"); } }, From 7ac0ab2e340dfb782bca0b5c9b96bce169390ea0 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Fri, 15 Oct 2021 18:57:27 +0800 Subject: [PATCH 14/24] [http options] beautify the json format when clicked the save button --- src/pages/EditMonitor.vue | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index f88614415..dd3d62bb4 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -466,6 +466,15 @@ export default { return; } + // Beautiful the JSON format + if (this.monitor.body) { + this.monitor.body = JSON.stringify(JSON.parse(this.monitor.body), null, 4); + } + + if (this.monitor.headers) { + this.monitor.headers = JSON.stringify(JSON.parse(this.monitor.headers), null, 4); + } + if (this.isAdd) { this.$root.add(this.monitor, async (res) => { From e1eeb44e7f052ebd31dfe18a52cbaf89ad2c9834 Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Fri, 15 Oct 2021 19:44:29 +0800 Subject: [PATCH 15/24] Update SECURITY.md --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 48ab9a72f..a0b2562f4 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -9,8 +9,8 @@ currently being supported with security updates. | Version | Supported | | ------- | ------------------ | -| 1.7.X | :white_check_mark: | -| < 1.7 | ❌ | +| 1.8.X | :white_check_mark: | +| <= 1.7.X | ❌ | ### Upgradable Docker Tags From 7276f34d90e18397c3c4a6fa461c1d813a63c9cf Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 16 Oct 2021 00:57:26 +0800 Subject: [PATCH 16/24] fix reset-password --- server/config.js | 7 +++++++ server/model/monitor.js | 2 +- server/server.js | 7 ++----- 3 files changed, 10 insertions(+), 6 deletions(-) create mode 100644 server/config.js diff --git a/server/config.js b/server/config.js new file mode 100644 index 000000000..24ccfaa14 --- /dev/null +++ b/server/config.js @@ -0,0 +1,7 @@ +const args = require("args-parser")(process.argv); +const demoMode = args["demo"] || false; + +module.exports = { + args, + demoMode +}; diff --git a/server/model/monitor.js b/server/model/monitor.js index 6ec97372c..4049a9937 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -11,7 +11,7 @@ const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalCli const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); const { Notification } = require("../notification"); -const { demoMode } = require("../server"); +const { demoMode } = require("../config"); const version = require("../../package.json").version; const apicache = require("../modules/apicache"); diff --git a/server/server.js b/server/server.js index c7615cbd1..8d994d3b6 100644 --- a/server/server.js +++ b/server/server.js @@ -1,6 +1,7 @@ console.log("Welcome to Uptime Kuma"); const args = require("args-parser")(process.argv); const { sleep, debug, getRandomInt, genSecret } = require("../src/util"); +const config = require("./config"); debug(args); @@ -8,10 +9,6 @@ if (! process.env.NODE_ENV) { process.env.NODE_ENV = "production"; } -// Demo Mode? -const demoMode = args["demo"] || false; -exports.demoMode = demoMode; - console.log("Node Env: " + process.env.NODE_ENV); console.log("Importing Node libraries"); @@ -84,7 +81,7 @@ const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || args */ const testMode = !!args["test"] || false; -if (demoMode) { +if (config.demoMode) { console.log("==== Demo Mode ===="); } From 4d26825cbeda1c60761745867a1c4a03e23831ac Mon Sep 17 00:00:00 2001 From: Louis Lam Date: Sat, 16 Oct 2021 01:33:44 +0800 Subject: [PATCH 17/24] [test] reset-password --- extra/reset-password.js | 62 ++++++++++++++++++++++++----------------- test/backend.spec.js | 17 +++++++---- 2 files changed, 48 insertions(+), 31 deletions(-) diff --git a/extra/reset-password.js b/extra/reset-password.js index be0395897..272351ed4 100644 --- a/extra/reset-password.js +++ b/extra/reset-password.js @@ -12,50 +12,60 @@ const rl = readline.createInterface({ output: process.stdout }); -(async () => { +const main = async () => { Database.init(args); await Database.connect(); try { const user = await R.findOne("user"); - if (! user) { - throw new Error("user not found, have you installed?"); - } - - console.log("Found user: " + user.username); - - while (true) { - let password = await question("New Password: "); - let confirmPassword = await question("Confirm New Password: "); - - if (password === confirmPassword) { - await user.resetPassword(password); - - // Reset all sessions by reset jwt secret - await initJWTSecret(); - - rl.close(); - break; - } else { - console.log("Passwords do not match, please try again."); + // No need to actually reset the password for testing, just make sure no connection problem. It is ok for now. + if (!process.env.TEST_BACKEND) { + if (! user) { + throw new Error("user not found, have you installed?"); } - } - console.log("Password reset successfully."); + console.log("Found user: " + user.username); + + while (true) { + let password = await question("New Password: "); + let confirmPassword = await question("Confirm New Password: "); + + if (password === confirmPassword) { + await user.resetPassword(password); + + // Reset all sessions by reset jwt secret + await initJWTSecret(); + + break; + } else { + console.log("Passwords do not match, please try again."); + } + } + console.log("Password reset successfully."); + } } catch (e) { console.error("Error: " + e.message); } await Database.close(); + rl.close(); - console.log("Finished. You should restart the Uptime Kuma server.") -})(); + console.log("Finished."); +}; function question(question) { return new Promise((resolve) => { rl.question(question, (answer) => { resolve(answer); - }) + }); }); } + +if (!process.env.TEST_BACKEND) { + main(); +} + +module.exports = { + main, +}; diff --git a/test/backend.spec.js b/test/backend.spec.js index ea04439a8..b47d375c5 100644 --- a/test/backend.spec.js +++ b/test/backend.spec.js @@ -1,11 +1,11 @@ -const { genSecret } = require("../src/util"); - -beforeAll(() => { - -}); +const { genSecret, sleep } = require("../src/util"); describe("Test genSecret", () => { + beforeAll(() => { + + }); + it("should be correct length", () => { let secret = genSecret(-1); expect(secret).toEqual(""); @@ -34,4 +34,11 @@ describe("Test genSecret", () => { expect(secret).toContain("A"); expect(secret).toContain("9"); }); + +}); + +describe("Test reset-password", () => { + it("should able to run", async () => { + await require("../extra/reset-password").main(); + }); }); From ed3a55839769bfdab05ec8166b5888d221a31a9e Mon Sep 17 00:00:00 2001 From: januridp Date: Sat, 16 Oct 2021 07:15:01 +0700 Subject: [PATCH 18/24] Fix(Language): Bahasa Indonesia (Indonesian) --- src/languages/id-ID.js | 166 ++++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 83 deletions(-) diff --git a/src/languages/id-ID.js b/src/languages/id-ID.js index 30540db5a..2d3a1f2a9 100644 --- a/src/languages/id-ID.js +++ b/src/languages/id-ID.js @@ -1,44 +1,44 @@ export default { - languageName: "Indonesia", + languageName: "Bahasa Indonesia (Indonesian)", checkEverySecond: "Cek Setiap {0} detik.", retryCheckEverySecond: "Coba lagi setiap {0} detik.", retriesDescription: "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim", ignoreTLSError: "Abaikan kesalahan TLS/SSL untuk situs web HTTPS", upsideDownModeDescription: "Balikkan statusnya. Jika layanan dapat dijangkau, TIDAK AKTIF.", maxRedirectDescription: "Jumlah maksimum pengalihan untuk diikuti. Setel ke 0 untuk menonaktifkan pengalihan.", - acceptedStatusCodesDescription: "Pilih kode status yang dianggap sebagai respons yang berhasil.", + acceptedStatusCodesDescription: "Pilih kode status yang dianggap sebagai tanggapan yang berhasil.", passwordNotMatchMsg: "Sandi kedua tidak cocok.", notificationDescription: "Harap atur notifikasi ke monitor agar berfungsi.", keywordDescription: "Cari kata kunci dalam code html atau JSON huruf besar-kecil berpengaruh", pauseDashboardHome: "Jeda", - deleteMonitorMsg: "Apakah anda mau menghapus monitor ini?", - deleteNotificationMsg: "Apakah anda mau menghapus notifikasi ini untuk semua monitor?", - resoverserverDescription: "Cloudflare adalah server default, Anda dapat mengubah server resolver kapan saja.", - rrtypeDescription: "Pilih RR-Type yang mau anda monitor", - pauseMonitorMsg: "Apakah anda yakin mau menjeda?", - enableDefaultNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara default. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.", - clearEventsMsg: "Apakah anda yakin mau menghapus semua event di monitor ini?", - clearHeartbeatsMsg: "Apakah anda yakin mau menghapus semua heartbeats di monitor ini?", - confirmClearStatisticsMsg: "Apakah anda yakin mau menghapus semua statistik?", + deleteMonitorMsg: "Apakah Anda mau menghapus monitor ini?", + deleteNotificationMsg: "Apakah Anda mau menghapus notifikasi ini untuk semua monitor?", + resoverserverDescription: "Cloudflare adalah server bawaan, Anda dapat mengubah server resolver kapan saja.", + rrtypeDescription: "Pilih RR-Type yang mau Anda monitor", + pauseMonitorMsg: "Apakah Anda yakin mau menjeda?", + enablebawaanNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara bawaan. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.", + clearEventsMsg: "Apakah Anda yakin mau menghapus semua event di monitor ini?", + clearHeartbeatsMsg: "Apakah Anda yakin mau menghapus semua heartbeats di monitor ini?", + confirmClearStatisticsMsg: "Apakah Anda yakin mau menghapus semua statistik?", importHandleDescription: "Pilih 'Lewati yang ada' jika Anda ingin melewati setiap monitor atau notifikasi dengan nama yang sama. 'Timpa' akan menghapus setiap monitor dan notifikasi yang ada.", confirmImportMsg: "Apakah Anda yakin untuk mengimpor cadangan? Pastikan Anda telah memilih opsi impor yang tepat.", twoFAVerifyLabel: "Silakan ketik token Anda untuk memverifikasi bahwa 2FA berfungsi", - tokenValidSettingsMsg: "Tokennya valid! Anda sekarang dapat menyimpan pengaturan 2FA.", + tokenValidSettingsMsg: "Tokennya benar! Anda sekarang dapat menyimpan pengaturan 2FA.", confirmEnableTwoFAMsg: "Apakah Anda yakin ingin mengaktifkan 2FA?", confirmDisableTwoFAMsg: "Apakah Anda yakin ingin menonaktifkan 2FA?", Settings: "Pengaturan", - Dashboard: "Dashboard", - "New Update": "Update Baru", + Dashboard: "Dasbor", + "New Update": "Pembaruan Baru", Language: "Bahasa", Appearance: "Tampilan", Theme: "Tema", - General: "General", + General: "Umum", Version: "Versi", - "Check Update On GitHub": "Cek Update di GitHub", - List: "List", + "Check Update On GitHub": "Cek Pembaruan di GitHub", + List: "Daftar", Add: "Tambah", "Add New Monitor": "Tambah Monitor Baru", - "Quick Stats": "Statistik Cepat", + "Quick Stats": "Statistik", Up: "Aktif", Down: "Tidak Aktif", Pending: "Tertunda", @@ -48,9 +48,9 @@ export default { Status: "Status", DateTime: "Tanggal Waktu", Message: "Pesan", - "No important events": "Tidak ada Event penting", - Resume: "Melanjutkan", - Edit: "Rubah", + "No important events": "Tidak ada peristiwa penting", + Resume: "Lanjutkan", + Edit: "Ubah", Delete: "Hapus", Current: "Saat ini", Uptime: "Waktu aktif", @@ -60,20 +60,20 @@ export default { "-day": "-hari", hour: "Jam", "-hour": "-Jam", - Response: "Respon", + Response: "Tanggapan", Ping: "Ping", "Monitor Type": "Tipe Monitor", Keyword: "Keyword", - "Friendly Name": "Friendly Name", + "Friendly Name": "Nama yang Ramah", URL: "URL", Hostname: "Hostname", Port: "Port", - "Heartbeat Interval": "Interval Heartbeat ", - Retries: "Retries", - "Heartbeat Retry Interval": "Interval Heartbeat Mencoba kembali ", - Advanced: "Advanced", + "Heartbeat Interval": "Jarak Waktu Heartbeat ", + Retries: "Coba lagi", + "Heartbeat Retry Interval": "Jarak Waktu Heartbeat Mencoba kembali ", + Advanced: "Tingkat Lanjut", "Upside Down Mode": "Mode Terbalik", - "Max. Redirects": "Maksimal Redirect/Pengalihan", + "Max. Redirects": "Maksimal Pengalihan", "Accepted Status Codes": "Kode Status yang Diterima", Save: "Simpan", Notifications: "Notifikasi", @@ -81,22 +81,22 @@ export default { "Setup Notification": "Setel Notifikasi", Light: "Terang", Dark: "Gelap", - Auto: "Automatis", - "Theme - Heartbeat Bar": "Theme - Heartbeat Bar", + Auto: "Otomatis", + "Theme - Heartbeat Bar": "Tema - Heartbeat Bar", Normal: "Normal", Bottom: "Bawah", None: "Tidak ada", Timezone: "Zona Waktu", "Search Engine Visibility": "Visibilitas Mesin Pencari", "Allow indexing": "Mengizinkan untuk diindex", - "Discourage search engines from indexing site": "Mencegah mesin pencari untuk mengindex site", + "Discourage search engines from indexing site": "Mencegah mesin pencari untuk mengindex situs", "Change Password": "Ganti Sandi", "Current Password": "Sandi Lama", "New Password": "Sandi Baru", "Repeat New Password": "Ulangi Sandi Baru", "Update Password": "Perbarui Kata Sandi", - "Disable Auth": "Nonaktifkan auth", - "Enable Auth": "Aktifkan Auth", + "Disable Auth": "Nonaktifkan Autentikasi", + "Enable Auth": "Aktifkan Autentikasi", Logout: "Keluar", Leave: "Pergi", "I understand, please disable": "Saya mengerti, silahkan dinonaktifkan", @@ -107,35 +107,35 @@ export default { Password: "Sandi", "Remember me": "Ingat saya", Login: "Masuk", - "No Monitors, please": "Tidak ada monitor, silahkan", - "add one": "tambah baru", + "No Monitors, please": "Tidak ada monitor, silakan", + "add one": "tambahkan satu", "Notification Type": "Tipe Notifikasi", - Email: "Email", - Test: "Test", - "Certificate Info": "Info Sertifikasi ", + Email: "Surel", + Test: "Tes", + "Certificate Info": "Info Sertifikasi", "Resolver Server": "Resolver Server", "Resource Record Type": "Resource Record Type", "Last Result": "Hasil Terakhir", - "Create your admin account": "Buat admin akun anda", + "Create your admin account": "Buat admin akun Anda", "Repeat Password": "Ulangi Sandi", - "Import Backup": "Impor Backup", - "Export Backup": "Expor Backup", + "Import Backup": "Impor Cadangan", + "Export Backup": "Expor Cadangan", Export: "Expor", Import: "Impor", respTime: "Tanggapan. Waktu (milidetik)", notAvailableShort: "N/A", - "Default enabled": "Default diaktifkan", + "Default enabled": "bawaan diaktifkan", "Apply on all existing monitors": "Terapkan pada semua monitor yang ada", Create: "Buat", "Clear Data": "Bersihkan Data", - Events: "Event", + Events: "Peristiwa", Heartbeats: "Heartbeats", - "Auto Get": "Auto Get", - backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam file JSON.", - backupDescription2: "Catatan: Data sejarah dan event tidak disertakan.", - backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam file ekspor, harap simpan dengan hati-hati.", - alertNoFile: "Silakan pilih file untuk diimpor.", - alertWrongFileType: "Silakan pilih file JSON .", + "Auto Get": "Ambil Otomatis", + backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam berkas JSON.", + backupDescription2: "Catatan: Data sejarah dan peristiwa tidak disertakan.", + backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam berkas ekspor, harap simpan dengan hati-hati.", + alertNoFile: "Silakan pilih berkas untuk diimpor.", + alertWrongFileType: "Silakan pilih berkas JSON .", "Clear all statistics": "Hapus semua statistik", "Skip existing": "Lewati yang ada", Overwrite: "Timpa", @@ -145,29 +145,29 @@ export default { "Setup 2FA": "Pengaturan 2FA", "Enable 2FA": "Aktifkan 2FA", "Disable 2FA": "Nonaktifkan 2FA", - "2FA Settings": "Settings 2FA", - "Two Factor Authentication": "Otentikasi Dua Faktor", + "2FA Settings": "Pengaturan 2FA", + "Two Factor Authentication": "Autentikasi Dua Faktor", Active: "Aktif", Inactive: "Tidak Aktif", Token: "Token", "Show URI": "Lihat URI", - Tags: "Tag", + Tags: "Tanda", "Add New below or Select...": "Tambahkan Baru di bawah atau Pilih...", - "Tag with this name already exist.": "Tag dengan nama ini sudah ada.", - "Tag with this value already exist.": "Tag dengan nilai ini sudah ada.", + "Tag with this name already exist.": "Tanda dengan nama ini sudah ada.", + "Tag with this value already exist.": "Tanda dengan nilai ini sudah ada.", color: "warna", "value (optional)": "nilai (harus diisi)", - Gray: "Abu Abu", + Gray: "Abu-abu", Red: "Merah", - Orange: "Oranye", + Orange: "Jingga", Green: "Hijau", Blue: "Biru", - Indigo: "Indigo", + Indigo: "Biru Tua", Purple: "Ungu", Pink: "Merah Muda", "Search...": "Cari...", "Avg. Ping": "Rata-rata. Ping", - "Avg. Response": "Rata-rata. Respon", + "Avg. Response": "Rata-rata. Tanggapan", "Entry Page": "Halaman Masuk", statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.", "No Services": "Tidak ada Layanan", @@ -177,7 +177,7 @@ export default { "Add Group": "Tambah Grup", "Add a monitor": "Tambah monitor", "Edit Status Page": "Edit Halaman Status", - "Go to Dashboard": "Lihat Dashboard", + "Go to Dashboard": "Pergi ke Dasbor", "Status Page": "Halaman Status", // Start notification form defaultNotificationName: "{notification} saya Peringatan ({number})", @@ -189,27 +189,27 @@ export default { "Chat ID": "Chat ID", supportTelegramChatID: "Mendukung Obrolan Langsung / Grup / Channel Chat ID", wayToGetTelegramChatID: "Anda bisa mendapatkan chat id Anda dengan mengirim pesan ke bot dan pergi ke url ini untuk melihat chat_id:", - "YOUR BOT TOKEN HERE": "BOT TOKEN ANDA DI SINI", + "YOUR BOT TOKEN HERE": "BOT TOKEN Anda DI SINI", chatIDNotFound: "Chat ID tidak ditemukan, tolong kirim pesan ke bot ini dulu", "webhook": "Webhook", "Post URL": "Post URL", "Content Type": "Tipe konten", - webhookJsonDesc: "{0} bagus untuk server http modern seperti express.js", + webhookJsonDesc: "{0} bagus untuk peladen http modern seperti express.js", webhookFormDataDesc: "{multipart} bagus untuk PHP, Anda hanya perlu mengurai json dengan {decodeFunction}", - "smtp": "Email (SMTP)", + "smtp": "Surel (SMTP)", secureOptionNone: "None / STARTTLS (25, 587)", secureOptionTLS: "TLS (465)", - "Ignore TLS Error": "Ignore TLS Error", - "From Email": "From Email", - "To Email": "To Email", + "Ignore TLS Error": "Abaikan Kesalahan TLS", + "From Email": "Dari Surel", + "To Email": "Ke Surel", smtpCC: "CC", smtpBCC: "BCC", "discord": "Discord", "Discord Webhook URL": "Discord Webhook URL", wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook", "Bot Display Name": "Nama Bot", - "Prefix Custom Message": "Prefix Pesan", - "Hello @everyone is...": "Hallo {'@'}everyone is...", + "Prefix Custom Message": "Awalan Pesan", + "Hello @everyone is...": "Halo {'@'}everyone is...", "teams": "Microsoft Teams", "Webhook URL": "Webhook URL", wayToGetTeamsURL: "Anda dapat mempelajari cara membuat url webhook {0}.", @@ -221,16 +221,16 @@ export default { signalImportant: "PENTING: Anda tidak dapat mencampur grup dan nomor di penerima!", "gotify": "Gotify", "Application Token": "Token Aplikasi", - "Server URL": "Server URL", + "Server URL": "URL Peladen", "Priority": "Prioritas", "slack": "Slack", - "Icon Emoji": "Icon Emoji", - "Channel Name": "Nama Channel", + "Icon Emoji": "Ikon Emoji", + "Channel Name": "Nama Saluran", "Uptime Kuma URL": "Uptime Kuma URL", aboutWebhooks: "Info lain tentang webhook: {0}", - aboutChannelName: "Masukan nama channel di {0} Kolom Nama Channel jika Anda ingin melewati channel webhook. Contoh: #other-channel", - aboutKumaURL: "Jika Anda membiarkan bidang URL Uptime Kuma kosong, itu akan menjadi default ke halaman Project Github.", - emojiCheatSheet: "Emoji cheat sheet: {0}", + aboutChannelName: "Masukan nama saluran di {0} Kolom Nama Saluran jika Anda ingin melewati saluran webhook. Contoh: #saluran-lain", + aboutKumaURL: "Jika Anda membiarkan bidang URL Uptime Kuma kosong, itu akan menjadi bawaan ke halaman Proyek Github.", + emojiCheatSheet: "Lembar contekan emoji: {0}", "rocket.chat": "Rocket.chat", pushover: "Pushover", pushy: "Pushy", @@ -246,7 +246,7 @@ export default { "Message Title": "Judul Pesan", "Notification Sound": "Suara Nofifikasi", "More info on:": "Info lebih lanjut tentang: {0}", - pushoverDesc1: "Prioritas darurat (2) memiliki batas waktu default 30 detik antara percobaan ulang dan akan kadaluwarsa setelah 1 jam.", + pushoverDesc1: "Prioritas darurat (2) memiliki batas waktu bawaan 30 detik antara percobaan ulang dan akan kadaluwarsa setelah 1 jam.", pushoverDesc2: "Jika Anda ingin mengirim pemberitahuan ke perangkat yang berbeda, isi kolom Perangkat.", "SMS Type": "Tipe SMS", octopushTypePremium: "Premium (Cepat - direkomendasikan untuk mengingatkan)", @@ -262,24 +262,24 @@ export default { "Read more": "Baca lebih lajut", appriseInstalled: "Apprise diinstall.", appriseNotInstalled: "Apprise tidak diinstall. {0}", - "Access Token": "Access Token", - "Channel access token": "Channel access token", - "Line Developers Console": "Line Developers Console", - lineDevConsoleTo: "Line Developers Console - {0}", + "Access Token": "Token Akses", + "Channel access token": "Token akses saluran", + "Line Developers Console": "Konsol Pengembang Line", + lineDevConsoleTo: "Konsol Pengembang Baris - {0}", "Basic Settings": "Pengaturan dasar", "User ID": "User ID", "Messaging API": "Messaging API", wayToGetLineChannelToken: "Pertama akses {0}, buat penyedia dan saluran (Messaging API), lalu Anda bisa mendapatkan token akses saluran dan id pengguna dari item menu yang disebutkan di atas.", "Icon URL": "Icon URL", - aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil default. Tidak akan digunakan jika Ikon Emoji diset.", - aboutMattermostChannelName: "Anda dapat mengganti channel default tujuan posting webhook dengan memasukkan nama channel ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel", + aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil bawaan. Tidak akan digunakan jika Ikon Emoji diset.", + aboutMattermostChannelName: "Anda dapat mengganti channel bawaan tujuan posting webhook dengan memasukkan nama channel ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel", "matrix": "Matrix", promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.", promosmsTypeFlash: "SMS FLASH - Pesan akan otomatis muncul di perangkat penerima. Terbatas hanya untuk penerima Polandia.", - promosmsTypeFull: "SMS FULL - SMS tingkat premium, Anda dapat menggunakan Nama Pengirim Anda (Anda harus mendaftarkan nama terlebih dahulu). Dapat diandalkan untuk peringatan.", - promosmsTypeSpeed: "SMS SPEED - Prioritas tertinggi dalam sistem. Sangat cepat dan dapat diandalkan tetapi mahal (sekitar dua kali lipat dari harga SMS FULL).", + promosmsTypeFull: "SMS FULL - SMS tingkat premium, Anda dapat menggunakan Nama Pengirim Anda (Anda harus mendaftarkan nama terlebih dahulu). Dapat diAndalkan untuk peringatan.", + promosmsTypeSpeed: "SMS SPEED - Prioritas tertinggi dalam sistem. Sangat cepat dan dapat diAndalkan tetapi mahal (sekitar dua kali lipat dari harga SMS FULL).", promosmsPhoneNumber: "Nomor telepon (untuk penerima Polandia Anda dapat melewati kode area)", - promosmsSMSSender: "Nama Pengirim SMS : Nama pra-registrasi atau salah satu default: InfoSMS, Info SMS, MaxSMS, INFO, SMS", + promosmsSMSSender: "Nama Pengirim SMS : Nama pra-registrasi atau salah satu bawaan: InfoSMS, Info SMS, MaxSMS, INFO, SMS", "Feishu WebHookUrl": "Feishu WebHookUrl", // End notification form }; From 4e4f94ab9832b151737f609fd7108199f5f28403 Mon Sep 17 00:00:00 2001 From: januridp Date: Sat, 16 Oct 2021 07:29:51 +0700 Subject: [PATCH 19/24] Fix(Language): Bahasa Indonesia (Indonesian) --- src/languages/id-ID.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/languages/id-ID.js b/src/languages/id-ID.js index 2d3a1f2a9..3fb9d1ca2 100644 --- a/src/languages/id-ID.js +++ b/src/languages/id-ID.js @@ -16,7 +16,7 @@ export default { resoverserverDescription: "Cloudflare adalah server bawaan, Anda dapat mengubah server resolver kapan saja.", rrtypeDescription: "Pilih RR-Type yang mau Anda monitor", pauseMonitorMsg: "Apakah Anda yakin mau menjeda?", - enablebawaanNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara bawaan. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.", + enableDefaultNotificationDescription: "Untuk setiap monitor baru, notifikasi ini akan diaktifkan secara bawaan. Anda masih dapat menonaktifkan notifikasi secara terpisah untuk setiap monitor.", clearEventsMsg: "Apakah Anda yakin mau menghapus semua event di monitor ini?", clearHeartbeatsMsg: "Apakah Anda yakin mau menghapus semua heartbeats di monitor ini?", confirmClearStatisticsMsg: "Apakah Anda yakin mau menghapus semua statistik?", @@ -49,7 +49,7 @@ export default { DateTime: "Tanggal Waktu", Message: "Pesan", "No important events": "Tidak ada peristiwa penting", - Resume: "Lanjutkan", + Resume: "Lanjut", Edit: "Ubah", Delete: "Hapus", Current: "Saat ini", @@ -99,7 +99,7 @@ export default { "Enable Auth": "Aktifkan Autentikasi", Logout: "Keluar", Leave: "Pergi", - "I understand, please disable": "Saya mengerti, silahkan dinonaktifkan", + "I understand, please disable": "Saya mengerti, silakan dinonaktifkan", Confirm: "Konfirmasi", Yes: "Ya", No: "Tidak", @@ -124,7 +124,7 @@ export default { Import: "Impor", respTime: "Tanggapan. Waktu (milidetik)", notAvailableShort: "N/A", - "Default enabled": "bawaan diaktifkan", + "Default enabled": "Bawaan diaktifkan", "Apply on all existing monitors": "Terapkan pada semua monitor yang ada", Create: "Buat", "Clear Data": "Bersihkan Data", @@ -135,7 +135,7 @@ export default { backupDescription2: "Catatan: Data sejarah dan peristiwa tidak disertakan.", backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam berkas ekspor, harap simpan dengan hati-hati.", alertNoFile: "Silakan pilih berkas untuk diimpor.", - alertWrongFileType: "Silakan pilih berkas JSON .", + alertWrongFileType: "Silakan pilih berkas JSON.", "Clear all statistics": "Hapus semua statistik", "Skip existing": "Lewati yang ada", Overwrite: "Timpa", @@ -166,8 +166,8 @@ export default { Purple: "Ungu", Pink: "Merah Muda", "Search...": "Cari...", - "Avg. Ping": "Rata-rata. Ping", - "Avg. Response": "Rata-rata. Tanggapan", + "Avg. Ping": "Rata-rata Ping", + "Avg. Response": "Rata-rata Tanggapan", "Entry Page": "Halaman Masuk", statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.", "No Services": "Tidak ada Layanan", @@ -265,14 +265,14 @@ export default { "Access Token": "Token Akses", "Channel access token": "Token akses saluran", "Line Developers Console": "Konsol Pengembang Line", - lineDevConsoleTo: "Konsol Pengembang Baris - {0}", - "Basic Settings": "Pengaturan dasar", - "User ID": "User ID", + lineDevConsoleTo: "Konsol Pengembang Line - {0}", + "Basic Settings": "Pengaturan Dasar", + "User ID": "ID User", "Messaging API": "Messaging API", wayToGetLineChannelToken: "Pertama akses {0}, buat penyedia dan saluran (Messaging API), lalu Anda bisa mendapatkan token akses saluran dan id pengguna dari item menu yang disebutkan di atas.", "Icon URL": "Icon URL", aboutIconURL: "Anda dapat memberikan tautan ke gambar di \"Icon URL\" untuk mengganti gambar profil bawaan. Tidak akan digunakan jika Ikon Emoji diset.", - aboutMattermostChannelName: "Anda dapat mengganti channel bawaan tujuan posting webhook dengan memasukkan nama channel ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel", + aboutMattermostChannelName: "Anda dapat mengganti saluran bawaan tujuan posting webhook dengan memasukkan nama saluran ke dalam Kolom \"Channel Name\". Ini perlu diaktifkan di pengaturan webhook Mattermost. contoh: #other-channel", "matrix": "Matrix", promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.", promosmsTypeFlash: "SMS FLASH - Pesan akan otomatis muncul di perangkat penerima. Terbatas hanya untuk penerima Polandia.", From 76e619c066ee87818f3489ca1110acb0e61ca378 Mon Sep 17 00:00:00 2001 From: januridp Date: Sat, 16 Oct 2021 07:36:07 +0700 Subject: [PATCH 20/24] Fix(Language): Bahasa Indonesia (Indonesian) --- src/pages/Settings.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/pages/Settings.vue b/src/pages/Settings.vue index 0f4fe5a8e..ea56e596e 100644 --- a/src/pages/Settings.vue +++ b/src/pages/Settings.vue @@ -334,9 +334,9 @@