mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-11 07:02:36 +02:00
Merge branch 'louislam:master' into master
This commit is contained in:
commit
90bcec5204
17 changed files with 315 additions and 140 deletions
|
@ -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
|
||||
|
||||
|
|
13
db/patch-http-monitor-method-body-and-headers.sql
Normal file
13
db/patch-http-monitor-method-body-and-headers.sql
Normal file
|
@ -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;
|
|
@ -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,
|
||||
};
|
||||
|
|
7
server/config.js
Normal file
7
server/config.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
const args = require("args-parser")(process.argv);
|
||||
const demoMode = args["demo"] || false;
|
||||
|
||||
module.exports = {
|
||||
args,
|
||||
demoMode
|
||||
};
|
|
@ -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,
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -14,6 +14,10 @@ h2 {
|
|||
font-size: 26px;
|
||||
}
|
||||
|
||||
textarea.form-control {
|
||||
border-radius: 19px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
}
|
||||
|
||||
.multiselect__tag {
|
||||
border-radius: 50rem;
|
||||
border-radius: $border-radius;
|
||||
margin-bottom: 0;
|
||||
padding: 6px 26px 6px 10px;
|
||||
background: $primary !important;
|
||||
|
|
|
@ -186,7 +186,7 @@ export default {
|
|||
.beat {
|
||||
display: inline-block;
|
||||
background-color: $primary;
|
||||
border-radius: 50rem;
|
||||
border-radius: $border-radius;
|
||||
|
||||
&.empty {
|
||||
background-color: aliceblue;
|
||||
|
|
|
@ -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: ",
|
||||
};
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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}",
|
||||
};
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
|
||||
<!-- Push URL -->
|
||||
<div v-if="monitor.type === 'push' " class="my-3">
|
||||
<label for="push-url" class="form-label">{{ $t("Push URL") }}</label>
|
||||
<label for="push-url" class="form-label">{{ $t("PushUrl") }}</label>
|
||||
<CopyableInput id="push-url" v-model="pushURL" type="url" disabled="disabled" />
|
||||
<div class="form-text">
|
||||
You should call this url every {{ monitor.interval }} seconds.<br />
|
||||
|
@ -196,6 +196,7 @@
|
|||
<div class="col-md-6">
|
||||
<div v-if="$root.isMobile" class="mt-3" />
|
||||
|
||||
<!-- Notifications -->
|
||||
<h2 class="mb-2">{{ $t("Notifications") }}</h2>
|
||||
<p v-if="$root.notificationList.length === 0">
|
||||
{{ $t("Not available, please setup.") }}
|
||||
|
@ -215,6 +216,51 @@
|
|||
<button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
|
||||
{{ $t("Setup Notification") }}
|
||||
</button>
|
||||
|
||||
<!-- HTTP Options -->
|
||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' ">
|
||||
<h2 class="mt-5 mb-2">{{ $t("HTTP Options") }}</h2>
|
||||
|
||||
<!-- Method -->
|
||||
<div class="my-3">
|
||||
<label for="method" class="form-label">{{ $t("Method") }}</label>
|
||||
<select id="method" v-model="monitor.method" class="form-select">
|
||||
<option value="GET">
|
||||
GET
|
||||
</option>
|
||||
<option value="POST">
|
||||
POST
|
||||
</option>
|
||||
<option value="PUT">
|
||||
PUT
|
||||
</option>
|
||||
<option value="PATCH">
|
||||
PATCH
|
||||
</option>
|
||||
<option value="DELETE">
|
||||
DELETE
|
||||
</option>
|
||||
<option value="HEAD">
|
||||
HEAD
|
||||
</option>
|
||||
<option value="OPTIONS">
|
||||
OPTIONS
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Body -->
|
||||
<div class="my-3">
|
||||
<label for="body" class="form-label">{{ $t("Body") }}</label>
|
||||
<textarea id="body" v-model="monitor.body" class="form-control" :placeholder="bodyPlaceholder"></textarea>
|
||||
</div>
|
||||
|
||||
<!-- Headers -->
|
||||
<div class="my-3">
|
||||
<label for="headers" class="form-label">{{ $t("Headers") }}</label>
|
||||
<textarea id="headers" v-model="monitor.headers" class="form-control" :placeholder="headersPlaceholder"></textarea>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -286,6 +332,14 @@ export default {
|
|||
|
||||
pushURL() {
|
||||
return this.$root.baseURL + "/api/push/" + this.monitor.pushToken + "?msg=OK&ping=";
|
||||
},
|
||||
|
||||
bodyPlaceholder() {
|
||||
return this.decodeHtml("{\n\t\"id\": 124357,\n\t\"username\": \"admin\",\n\t\"password\": \"myAdminPassword\"\n}");
|
||||
},
|
||||
|
||||
headersPlaceholder() {
|
||||
return this.decodeHtml("{\n\t\"Authorization\": \"Bearer abc123\",\n\t\"Content-Type\": \"application/json\"\n}");
|
||||
}
|
||||
|
||||
},
|
||||
|
@ -296,7 +350,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;
|
||||
}
|
||||
|
@ -350,6 +404,7 @@ export default {
|
|||
type: "http",
|
||||
name: "",
|
||||
url: "https://",
|
||||
method: "GET",
|
||||
interval: 60,
|
||||
retryInterval: this.interval,
|
||||
maxretries: 0,
|
||||
|
@ -384,9 +439,43 @@ export default {
|
|||
|
||||
},
|
||||
|
||||
isInputValid() {
|
||||
if (this.monitor.body) {
|
||||
try {
|
||||
JSON.parse(this.monitor.body);
|
||||
} catch (err) {
|
||||
toast.error(this.$t("BodyInvalidFormat") + err.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (this.monitor.headers) {
|
||||
try {
|
||||
JSON.parse(this.monitor.headers);
|
||||
} catch (err) {
|
||||
toast.error(this.$t("HeadersInvalidFormat") + err.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
async submit() {
|
||||
this.processing = true;
|
||||
|
||||
if (!this.isInputValid()) {
|
||||
this.processing = false;
|
||||
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) => {
|
||||
|
||||
|
@ -419,12 +508,22 @@ export default {
|
|||
addedNotification(id) {
|
||||
this.monitor.notificationIDList[id] = true;
|
||||
},
|
||||
|
||||
decodeHtml(html) {
|
||||
const txt = document.createElement("textarea");
|
||||
txt.innerHTML = html;
|
||||
return txt.value;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
.shadow-box {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
textarea {
|
||||
min-height: 200px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -334,9 +334,9 @@
|
|||
</template>
|
||||
|
||||
<template v-else-if="$i18n.locale === 'id-ID' ">
|
||||
<p> Apakah Anda yakin ingin <strong>menonaktifkan autentikasi</strong>? </p>
|
||||
<p> Ini untuk <strong>mereka yang memiliki otentikasi pihak ketiga</strong> diletakkan di depan Uptime Kuma, misalnya akses Cloudflare. </p>
|
||||
<p> Gunakan dengan hati-hati. </p>
|
||||
<p>Apakah Anda yakin ingin <strong>menonaktifkan autentikasi</strong>?</p>
|
||||
<p>Ini untuk <strong>mereka yang memiliki autentikasi pihak ketiga</strong> diletakkan di depan Uptime Kuma, misalnya akses Cloudflare.</p>
|
||||
<p>Gunakan dengan hati-hati.</p>
|
||||
</template>
|
||||
|
||||
<template v-else-if="$i18n.locale === 'ru-RU' ">
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
Loading…
Add table
Reference in a new issue