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 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/extra/reset-password.js b/extra/reset-password.js index be0395897..1b48dffd7 100644 --- a/extra/reset-password.js +++ b/extra/reset-password.js @@ -12,50 +12,59 @@ 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) { + const user = await R.findOne("user"); + 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/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/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 9fe6ffd43..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"); @@ -55,6 +55,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, @@ -138,11 +141,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.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) @@ -152,7 +159,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; @@ -172,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/server.js b/server/server.js index 376e7bb3f..0e5a9d80f 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"); @@ -78,13 +75,19 @@ const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.p const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || args["ssl-key"] || undefined; const sslCert = process.env.UPTIME_KUMA_SSL_CERT || 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} */ const testMode = !!args["test"] || false; -if (demoMode) { +if (config.demoMode) { console.log("==== Demo Mode ===="); } @@ -275,7 +278,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, twofa_verification_opts); if (verify && verify.delta == 0) { callback({ @@ -393,7 +396,7 @@ exports.entryPage = "dashboard"; socket.userID, ]); - let verify = notp.totp.verify(token, user.twofa_secret); + let verify = notp.totp.verify(token, user.twofa_secret, twofa_verification_opts); if (verify && verify.delta == 0) { callback({ @@ -519,6 +522,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; @@ -1044,6 +1050,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/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/assets/app.scss b/src/assets/app.scss index 2cbec5c01..e1a5d052d 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; } 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/languages/en.js b/src/languages/en.js index 1fc176823..3f3ed1594 100644 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -283,4 +283,10 @@ export default { promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS", "Feishu WebHookUrl": "Feishu WebHookUrl", // End notification form + Method: "Method", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + HeadersInvalidFormat: "The request headers are not valid JSON: ", + BodyInvalidFormat: "The request body is not valid JSON: ", }; diff --git a/src/languages/id-ID.js b/src/languages/id-ID.js index 30540db5a..5cb38ea6d 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?", + 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?", 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: "Lanjut", + 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,25 +81,25 @@ 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", + "I understand, please disable": "Saya mengerti, silakan dinonaktifkan", Confirm: "Konfirmasi", Yes: "Ya", No: "Tidak", @@ -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. 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", @@ -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})", @@ -194,22 +194,22 @@ export default { "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}", - "Basic Settings": "Pengaturan dasar", - "User ID": "User ID", + "Access Token": "Token Akses", + "Channel access token": "Token akses saluran", + "Line Developers Console": "Konsol Pengembang Line", + 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 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 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.", - 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 }; diff --git a/src/languages/nl-NL.js b/src/languages/nl-NL.js index 5c3225530..170b4a3ce 100644 --- a/src/languages/nl-NL.js +++ b/src/languages/nl-NL.js @@ -198,4 +198,12 @@ export default { pushbullet: "Pushbullet", line: "Line Messenger", mattermost: "Mattermost", + Method: "Methode", + Body: "Body", + Headers: "Headers", + PushUrl: "Push URL", + 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: "{\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 424b95fe5..b23490218 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -46,7 +46,7 @@
{{ $t("Not available, please setup.") }}
@@ -215,6 +216,51 @@
+
+
+
+ {{ $t("HTTP Options") }}
+
+
+
Apakah Anda yakin ingin menonaktifkan autentikasi?
-Ini untuk mereka yang memiliki otentikasi pihak ketiga diletakkan di depan Uptime Kuma, misalnya akses Cloudflare.
-Gunakan dengan hati-hati.
+Apakah Anda yakin ingin menonaktifkan autentikasi?
+Ini untuk mereka yang memiliki autentikasi pihak ketiga diletakkan di depan Uptime Kuma, misalnya akses Cloudflare.
+Gunakan dengan hati-hati.
diff --git a/test/backend.spec.js b/test/backend.spec.js index ea04439a8..bd73d2022 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(); + }, 120000); });