mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-12 15:42:35 +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 |
|
| Version | Supported |
|
||||||
| ------- | ------------------ |
|
| ------- | ------------------ |
|
||||||
| 1.7.X | :white_check_mark: |
|
| 1.8.X | :white_check_mark: |
|
||||||
| < 1.7 | ❌ |
|
| <= 1.7.X | ❌ |
|
||||||
|
|
||||||
### Upgradable Docker Tags
|
### 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
|
output: process.stdout
|
||||||
});
|
});
|
||||||
|
|
||||||
(async () => {
|
const main = async () => {
|
||||||
Database.init(args);
|
Database.init(args);
|
||||||
await Database.connect();
|
await Database.connect();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const user = await R.findOne("user");
|
// 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) {
|
const user = await R.findOne("user");
|
||||||
throw new Error("user not found, have you installed?");
|
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.");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
} catch (e) {
|
||||||
console.error("Error: " + e.message);
|
console.error("Error: " + e.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Database.close();
|
await Database.close();
|
||||||
|
rl.close();
|
||||||
|
|
||||||
console.log("Finished. You should restart the Uptime Kuma server.")
|
console.log("Finished.");
|
||||||
})();
|
};
|
||||||
|
|
||||||
function question(question) {
|
function question(question) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
rl.question(question, (answer) => {
|
rl.question(question, (answer) => {
|
||||||
resolve(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-incident-table.sql": true,
|
||||||
"patch-group-table.sql": true,
|
"patch-group-table.sql": true,
|
||||||
"patch-monitor-push_token.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 { R } = require("redbean-node");
|
||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const { Notification } = require("../notification");
|
const { Notification } = require("../notification");
|
||||||
const { demoMode } = require("../server");
|
const { demoMode } = require("../config");
|
||||||
const version = require("../../package.json").version;
|
const version = require("../../package.json").version;
|
||||||
const apicache = require("../modules/apicache");
|
const apicache = require("../modules/apicache");
|
||||||
|
|
||||||
|
@ -55,6 +55,9 @@ class Monitor extends BeanModel {
|
||||||
id: this.id,
|
id: this.id,
|
||||||
name: this.name,
|
name: this.name,
|
||||||
url: this.url,
|
url: this.url,
|
||||||
|
method: this.method,
|
||||||
|
body: this.body,
|
||||||
|
headers: this.headers,
|
||||||
hostname: this.hostname,
|
hostname: this.hostname,
|
||||||
port: this.port,
|
port: this.port,
|
||||||
maxretries: this.maxretries,
|
maxretries: this.maxretries,
|
||||||
|
@ -138,11 +141,15 @@ class Monitor extends BeanModel {
|
||||||
// Do not do any queries/high loading things before the "bean.ping"
|
// Do not do any queries/high loading things before the "bean.ping"
|
||||||
let startTime = dayjs().valueOf();
|
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,
|
timeout: this.interval * 1000 * 0.8,
|
||||||
headers: {
|
headers: {
|
||||||
"Accept": "*/*",
|
"Accept": "*/*",
|
||||||
"User-Agent": "Uptime-Kuma/" + version,
|
"User-Agent": "Uptime-Kuma/" + version,
|
||||||
|
...(this.headers ? JSON.parse(this.headers) : {}),
|
||||||
},
|
},
|
||||||
httpsAgent: new https.Agent({
|
httpsAgent: new https.Agent({
|
||||||
maxCachedSessions: 0, // Use Custom 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)
|
||||||
|
@ -152,7 +159,8 @@ class Monitor extends BeanModel {
|
||||||
validateStatus: (status) => {
|
validateStatus: (status) => {
|
||||||
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
let res = await axios.request(options);
|
||||||
bean.msg = `${res.status} - ${res.statusText}`;
|
bean.msg = `${res.status} - ${res.statusText}`;
|
||||||
bean.ping = dayjs().valueOf() - startTime;
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
|
|
||||||
|
@ -172,6 +180,10 @@ class Monitor extends BeanModel {
|
||||||
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
|
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") {
|
if (this.type === "http") {
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
console.log("Welcome to Uptime Kuma");
|
console.log("Welcome to Uptime Kuma");
|
||||||
const args = require("args-parser")(process.argv);
|
const args = require("args-parser")(process.argv);
|
||||||
const { sleep, debug, getRandomInt, genSecret } = require("../src/util");
|
const { sleep, debug, getRandomInt, genSecret } = require("../src/util");
|
||||||
|
const config = require("./config");
|
||||||
|
|
||||||
debug(args);
|
debug(args);
|
||||||
|
|
||||||
|
@ -8,10 +9,6 @@ if (! process.env.NODE_ENV) {
|
||||||
process.env.NODE_ENV = "production";
|
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("Node Env: " + process.env.NODE_ENV);
|
||||||
|
|
||||||
console.log("Importing Node libraries");
|
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 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;
|
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
|
* Run unit test after the server is ready
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
*/
|
*/
|
||||||
const testMode = !!args["test"] || false;
|
const testMode = !!args["test"] || false;
|
||||||
|
|
||||||
if (demoMode) {
|
if (config.demoMode) {
|
||||||
console.log("==== Demo Mode ====");
|
console.log("==== Demo Mode ====");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +278,7 @@ exports.entryPage = "dashboard";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.token) {
|
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) {
|
if (verify && verify.delta == 0) {
|
||||||
callback({
|
callback({
|
||||||
|
@ -393,7 +396,7 @@ exports.entryPage = "dashboard";
|
||||||
socket.userID,
|
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) {
|
if (verify && verify.delta == 0) {
|
||||||
callback({
|
callback({
|
||||||
|
@ -519,6 +522,9 @@ exports.entryPage = "dashboard";
|
||||||
bean.name = monitor.name;
|
bean.name = monitor.name;
|
||||||
bean.type = monitor.type;
|
bean.type = monitor.type;
|
||||||
bean.url = monitor.url;
|
bean.url = monitor.url;
|
||||||
|
bean.method = monitor.method;
|
||||||
|
bean.body = monitor.body;
|
||||||
|
bean.headers = monitor.headers;
|
||||||
bean.interval = monitor.interval;
|
bean.interval = monitor.interval;
|
||||||
bean.retryInterval = monitor.retryInterval;
|
bean.retryInterval = monitor.retryInterval;
|
||||||
bean.hostname = monitor.hostname;
|
bean.hostname = monitor.hostname;
|
||||||
|
@ -1044,6 +1050,9 @@ exports.entryPage = "dashboard";
|
||||||
name: monitorListData[i].name,
|
name: monitorListData[i].name,
|
||||||
type: monitorListData[i].type,
|
type: monitorListData[i].type,
|
||||||
url: monitorListData[i].url,
|
url: monitorListData[i].url,
|
||||||
|
method: monitorListData[i].method || "GET",
|
||||||
|
body: monitorListData[i].body,
|
||||||
|
headers: monitorListData[i].headers,
|
||||||
interval: monitorListData[i].interval,
|
interval: monitorListData[i].interval,
|
||||||
retryInterval: retryInterval,
|
retryInterval: retryInterval,
|
||||||
hostname: monitorListData[i].hostname,
|
hostname: monitorListData[i].hostname,
|
||||||
|
|
|
@ -327,7 +327,7 @@ exports.startUnitTest = async () => {
|
||||||
*/
|
*/
|
||||||
exports.convertToUTF8 = (body) => {
|
exports.convertToUTF8 = (body) => {
|
||||||
const guessEncoding = chardet.detect(body);
|
const guessEncoding = chardet.detect(body);
|
||||||
debug("Guess Encoding: " + guessEncoding);
|
//debug("Guess Encoding: " + guessEncoding);
|
||||||
const str = iconv.decode(body, guessEncoding);
|
const str = iconv.decode(body, guessEncoding);
|
||||||
return str.toString();
|
return str.toString();
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,10 @@ h2 {
|
||||||
font-size: 26px;
|
font-size: 26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea.form-control {
|
||||||
|
border-radius: 19px;
|
||||||
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.multiselect__tag {
|
.multiselect__tag {
|
||||||
border-radius: 50rem;
|
border-radius: $border-radius;
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
padding: 6px 26px 6px 10px;
|
padding: 6px 26px 6px 10px;
|
||||||
background: $primary !important;
|
background: $primary !important;
|
||||||
|
|
|
@ -186,7 +186,7 @@ export default {
|
||||||
.beat {
|
.beat {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
background-color: $primary;
|
background-color: $primary;
|
||||||
border-radius: 50rem;
|
border-radius: $border-radius;
|
||||||
|
|
||||||
&.empty {
|
&.empty {
|
||||||
background-color: aliceblue;
|
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",
|
promosmsSMSSender: "SMS Sender Name : Pre-registred name or one of defaults: InfoSMS, SMS Info, MaxSMS, INFO, SMS",
|
||||||
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
||||||
// End notification form
|
// 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 {
|
export default {
|
||||||
languageName: "Indonesia",
|
languageName: "Bahasa Indonesia (Indonesian)",
|
||||||
checkEverySecond: "Cek Setiap {0} detik.",
|
checkEverySecond: "Cek Setiap {0} detik.",
|
||||||
retryCheckEverySecond: "Coba lagi setiap {0} detik.",
|
retryCheckEverySecond: "Coba lagi setiap {0} detik.",
|
||||||
retriesDescription: "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim",
|
retriesDescription: "Percobaan ulang maksimum sebelum layanan dinyatakan tidak aktif dan notifikasi dikirim",
|
||||||
ignoreTLSError: "Abaikan kesalahan TLS/SSL untuk situs web HTTPS",
|
ignoreTLSError: "Abaikan kesalahan TLS/SSL untuk situs web HTTPS",
|
||||||
upsideDownModeDescription: "Balikkan statusnya. Jika layanan dapat dijangkau, TIDAK AKTIF.",
|
upsideDownModeDescription: "Balikkan statusnya. Jika layanan dapat dijangkau, TIDAK AKTIF.",
|
||||||
maxRedirectDescription: "Jumlah maksimum pengalihan untuk diikuti. Setel ke 0 untuk menonaktifkan pengalihan.",
|
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.",
|
passwordNotMatchMsg: "Sandi kedua tidak cocok.",
|
||||||
notificationDescription: "Harap atur notifikasi ke monitor agar berfungsi.",
|
notificationDescription: "Harap atur notifikasi ke monitor agar berfungsi.",
|
||||||
keywordDescription: "Cari kata kunci dalam code html atau JSON huruf besar-kecil berpengaruh",
|
keywordDescription: "Cari kata kunci dalam code html atau JSON huruf besar-kecil berpengaruh",
|
||||||
pauseDashboardHome: "Jeda",
|
pauseDashboardHome: "Jeda",
|
||||||
deleteMonitorMsg: "Apakah anda mau menghapus monitor ini?",
|
deleteMonitorMsg: "Apakah Anda mau menghapus monitor ini?",
|
||||||
deleteNotificationMsg: "Apakah anda mau menghapus notifikasi ini untuk semua monitor?",
|
deleteNotificationMsg: "Apakah Anda mau menghapus notifikasi ini untuk semua monitor?",
|
||||||
resoverserverDescription: "Cloudflare adalah server default, Anda dapat mengubah server resolver kapan saja.",
|
resoverserverDescription: "Cloudflare adalah server bawaan, Anda dapat mengubah server resolver kapan saja.",
|
||||||
rrtypeDescription: "Pilih RR-Type yang mau anda monitor",
|
rrtypeDescription: "Pilih RR-Type yang mau Anda monitor",
|
||||||
pauseMonitorMsg: "Apakah anda yakin mau menjeda?",
|
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.",
|
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?",
|
clearEventsMsg: "Apakah Anda yakin mau menghapus semua event di monitor ini?",
|
||||||
clearHeartbeatsMsg: "Apakah anda yakin mau menghapus semua heartbeats di monitor ini?",
|
clearHeartbeatsMsg: "Apakah Anda yakin mau menghapus semua heartbeats di monitor ini?",
|
||||||
confirmClearStatisticsMsg: "Apakah anda yakin mau menghapus semua statistik?",
|
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.",
|
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.",
|
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",
|
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?",
|
confirmEnableTwoFAMsg: "Apakah Anda yakin ingin mengaktifkan 2FA?",
|
||||||
confirmDisableTwoFAMsg: "Apakah Anda yakin ingin menonaktifkan 2FA?",
|
confirmDisableTwoFAMsg: "Apakah Anda yakin ingin menonaktifkan 2FA?",
|
||||||
Settings: "Pengaturan",
|
Settings: "Pengaturan",
|
||||||
Dashboard: "Dashboard",
|
Dashboard: "Dasbor",
|
||||||
"New Update": "Update Baru",
|
"New Update": "Pembaruan Baru",
|
||||||
Language: "Bahasa",
|
Language: "Bahasa",
|
||||||
Appearance: "Tampilan",
|
Appearance: "Tampilan",
|
||||||
Theme: "Tema",
|
Theme: "Tema",
|
||||||
General: "General",
|
General: "Umum",
|
||||||
Version: "Versi",
|
Version: "Versi",
|
||||||
"Check Update On GitHub": "Cek Update di GitHub",
|
"Check Update On GitHub": "Cek Pembaruan di GitHub",
|
||||||
List: "List",
|
List: "Daftar",
|
||||||
Add: "Tambah",
|
Add: "Tambah",
|
||||||
"Add New Monitor": "Tambah Monitor Baru",
|
"Add New Monitor": "Tambah Monitor Baru",
|
||||||
"Quick Stats": "Statistik Cepat",
|
"Quick Stats": "Statistik",
|
||||||
Up: "Aktif",
|
Up: "Aktif",
|
||||||
Down: "Tidak Aktif",
|
Down: "Tidak Aktif",
|
||||||
Pending: "Tertunda",
|
Pending: "Tertunda",
|
||||||
|
@ -48,9 +48,9 @@ export default {
|
||||||
Status: "Status",
|
Status: "Status",
|
||||||
DateTime: "Tanggal Waktu",
|
DateTime: "Tanggal Waktu",
|
||||||
Message: "Pesan",
|
Message: "Pesan",
|
||||||
"No important events": "Tidak ada Event penting",
|
"No important events": "Tidak ada peristiwa penting",
|
||||||
Resume: "Melanjutkan",
|
Resume: "Lanjut",
|
||||||
Edit: "Rubah",
|
Edit: "Ubah",
|
||||||
Delete: "Hapus",
|
Delete: "Hapus",
|
||||||
Current: "Saat ini",
|
Current: "Saat ini",
|
||||||
Uptime: "Waktu aktif",
|
Uptime: "Waktu aktif",
|
||||||
|
@ -60,20 +60,20 @@ export default {
|
||||||
"-day": "-hari",
|
"-day": "-hari",
|
||||||
hour: "Jam",
|
hour: "Jam",
|
||||||
"-hour": "-Jam",
|
"-hour": "-Jam",
|
||||||
Response: "Respon",
|
Response: "Tanggapan",
|
||||||
Ping: "Ping",
|
Ping: "Ping",
|
||||||
"Monitor Type": "Tipe Monitor",
|
"Monitor Type": "Tipe Monitor",
|
||||||
Keyword: "Keyword",
|
Keyword: "Keyword",
|
||||||
"Friendly Name": "Friendly Name",
|
"Friendly Name": "Nama yang Ramah",
|
||||||
URL: "URL",
|
URL: "URL",
|
||||||
Hostname: "Hostname",
|
Hostname: "Hostname",
|
||||||
Port: "Port",
|
Port: "Port",
|
||||||
"Heartbeat Interval": "Interval Heartbeat ",
|
"Heartbeat Interval": "Jarak Waktu Heartbeat ",
|
||||||
Retries: "Retries",
|
Retries: "Coba lagi",
|
||||||
"Heartbeat Retry Interval": "Interval Heartbeat Mencoba kembali ",
|
"Heartbeat Retry Interval": "Jarak Waktu Heartbeat Mencoba kembali ",
|
||||||
Advanced: "Advanced",
|
Advanced: "Tingkat Lanjut",
|
||||||
"Upside Down Mode": "Mode Terbalik",
|
"Upside Down Mode": "Mode Terbalik",
|
||||||
"Max. Redirects": "Maksimal Redirect/Pengalihan",
|
"Max. Redirects": "Maksimal Pengalihan",
|
||||||
"Accepted Status Codes": "Kode Status yang Diterima",
|
"Accepted Status Codes": "Kode Status yang Diterima",
|
||||||
Save: "Simpan",
|
Save: "Simpan",
|
||||||
Notifications: "Notifikasi",
|
Notifications: "Notifikasi",
|
||||||
|
@ -81,25 +81,25 @@ export default {
|
||||||
"Setup Notification": "Setel Notifikasi",
|
"Setup Notification": "Setel Notifikasi",
|
||||||
Light: "Terang",
|
Light: "Terang",
|
||||||
Dark: "Gelap",
|
Dark: "Gelap",
|
||||||
Auto: "Automatis",
|
Auto: "Otomatis",
|
||||||
"Theme - Heartbeat Bar": "Theme - Heartbeat Bar",
|
"Theme - Heartbeat Bar": "Tema - Heartbeat Bar",
|
||||||
Normal: "Normal",
|
Normal: "Normal",
|
||||||
Bottom: "Bawah",
|
Bottom: "Bawah",
|
||||||
None: "Tidak ada",
|
None: "Tidak ada",
|
||||||
Timezone: "Zona Waktu",
|
Timezone: "Zona Waktu",
|
||||||
"Search Engine Visibility": "Visibilitas Mesin Pencari",
|
"Search Engine Visibility": "Visibilitas Mesin Pencari",
|
||||||
"Allow indexing": "Mengizinkan untuk diindex",
|
"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",
|
"Change Password": "Ganti Sandi",
|
||||||
"Current Password": "Sandi Lama",
|
"Current Password": "Sandi Lama",
|
||||||
"New Password": "Sandi Baru",
|
"New Password": "Sandi Baru",
|
||||||
"Repeat New Password": "Ulangi Sandi Baru",
|
"Repeat New Password": "Ulangi Sandi Baru",
|
||||||
"Update Password": "Perbarui Kata Sandi",
|
"Update Password": "Perbarui Kata Sandi",
|
||||||
"Disable Auth": "Nonaktifkan auth",
|
"Disable Auth": "Nonaktifkan Autentikasi",
|
||||||
"Enable Auth": "Aktifkan Auth",
|
"Enable Auth": "Aktifkan Autentikasi",
|
||||||
Logout: "Keluar",
|
Logout: "Keluar",
|
||||||
Leave: "Pergi",
|
Leave: "Pergi",
|
||||||
"I understand, please disable": "Saya mengerti, silahkan dinonaktifkan",
|
"I understand, please disable": "Saya mengerti, silakan dinonaktifkan",
|
||||||
Confirm: "Konfirmasi",
|
Confirm: "Konfirmasi",
|
||||||
Yes: "Ya",
|
Yes: "Ya",
|
||||||
No: "Tidak",
|
No: "Tidak",
|
||||||
|
@ -107,35 +107,35 @@ export default {
|
||||||
Password: "Sandi",
|
Password: "Sandi",
|
||||||
"Remember me": "Ingat saya",
|
"Remember me": "Ingat saya",
|
||||||
Login: "Masuk",
|
Login: "Masuk",
|
||||||
"No Monitors, please": "Tidak ada monitor, silahkan",
|
"No Monitors, please": "Tidak ada monitor, silakan",
|
||||||
"add one": "tambah baru",
|
"add one": "tambahkan satu",
|
||||||
"Notification Type": "Tipe Notifikasi",
|
"Notification Type": "Tipe Notifikasi",
|
||||||
Email: "Email",
|
Email: "Surel",
|
||||||
Test: "Test",
|
Test: "Tes",
|
||||||
"Certificate Info": "Info Sertifikasi ",
|
"Certificate Info": "Info Sertifikasi",
|
||||||
"Resolver Server": "Resolver Server",
|
"Resolver Server": "Resolver Server",
|
||||||
"Resource Record Type": "Resource Record Type",
|
"Resource Record Type": "Resource Record Type",
|
||||||
"Last Result": "Hasil Terakhir",
|
"Last Result": "Hasil Terakhir",
|
||||||
"Create your admin account": "Buat admin akun anda",
|
"Create your admin account": "Buat admin akun Anda",
|
||||||
"Repeat Password": "Ulangi Sandi",
|
"Repeat Password": "Ulangi Sandi",
|
||||||
"Import Backup": "Impor Backup",
|
"Import Backup": "Impor Cadangan",
|
||||||
"Export Backup": "Expor Backup",
|
"Export Backup": "Expor Cadangan",
|
||||||
Export: "Expor",
|
Export: "Expor",
|
||||||
Import: "Impor",
|
Import: "Impor",
|
||||||
respTime: "Tanggapan. Waktu (milidetik)",
|
respTime: "Tanggapan. Waktu (milidetik)",
|
||||||
notAvailableShort: "N/A",
|
notAvailableShort: "N/A",
|
||||||
"Default enabled": "Default diaktifkan",
|
"Default enabled": "Bawaan diaktifkan",
|
||||||
"Apply on all existing monitors": "Terapkan pada semua monitor yang ada",
|
"Apply on all existing monitors": "Terapkan pada semua monitor yang ada",
|
||||||
Create: "Buat",
|
Create: "Buat",
|
||||||
"Clear Data": "Bersihkan Data",
|
"Clear Data": "Bersihkan Data",
|
||||||
Events: "Event",
|
Events: "Peristiwa",
|
||||||
Heartbeats: "Heartbeats",
|
Heartbeats: "Heartbeats",
|
||||||
"Auto Get": "Auto Get",
|
"Auto Get": "Ambil Otomatis",
|
||||||
backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam file JSON.",
|
backupDescription: "Anda dapat mencadangkan semua monitor dan semua notifikasi ke dalam berkas JSON.",
|
||||||
backupDescription2: "Catatan: Data sejarah dan event tidak disertakan.",
|
backupDescription2: "Catatan: Data sejarah dan peristiwa tidak disertakan.",
|
||||||
backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam file ekspor, harap simpan dengan hati-hati.",
|
backupDescription3: "Data sensitif seperti notifikasi token disertakan dalam berkas ekspor, harap simpan dengan hati-hati.",
|
||||||
alertNoFile: "Silakan pilih file untuk diimpor.",
|
alertNoFile: "Silakan pilih berkas untuk diimpor.",
|
||||||
alertWrongFileType: "Silakan pilih file JSON .",
|
alertWrongFileType: "Silakan pilih berkas JSON.",
|
||||||
"Clear all statistics": "Hapus semua statistik",
|
"Clear all statistics": "Hapus semua statistik",
|
||||||
"Skip existing": "Lewati yang ada",
|
"Skip existing": "Lewati yang ada",
|
||||||
Overwrite: "Timpa",
|
Overwrite: "Timpa",
|
||||||
|
@ -145,29 +145,29 @@ export default {
|
||||||
"Setup 2FA": "Pengaturan 2FA",
|
"Setup 2FA": "Pengaturan 2FA",
|
||||||
"Enable 2FA": "Aktifkan 2FA",
|
"Enable 2FA": "Aktifkan 2FA",
|
||||||
"Disable 2FA": "Nonaktifkan 2FA",
|
"Disable 2FA": "Nonaktifkan 2FA",
|
||||||
"2FA Settings": "Settings 2FA",
|
"2FA Settings": "Pengaturan 2FA",
|
||||||
"Two Factor Authentication": "Otentikasi Dua Faktor",
|
"Two Factor Authentication": "Autentikasi Dua Faktor",
|
||||||
Active: "Aktif",
|
Active: "Aktif",
|
||||||
Inactive: "Tidak Aktif",
|
Inactive: "Tidak Aktif",
|
||||||
Token: "Token",
|
Token: "Token",
|
||||||
"Show URI": "Lihat URI",
|
"Show URI": "Lihat URI",
|
||||||
Tags: "Tag",
|
Tags: "Tanda",
|
||||||
"Add New below or Select...": "Tambahkan Baru di bawah atau Pilih...",
|
"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 name already exist.": "Tanda dengan nama ini sudah ada.",
|
||||||
"Tag with this value already exist.": "Tag dengan nilai ini sudah ada.",
|
"Tag with this value already exist.": "Tanda dengan nilai ini sudah ada.",
|
||||||
color: "warna",
|
color: "warna",
|
||||||
"value (optional)": "nilai (harus diisi)",
|
"value (optional)": "nilai (harus diisi)",
|
||||||
Gray: "Abu Abu",
|
Gray: "Abu-abu",
|
||||||
Red: "Merah",
|
Red: "Merah",
|
||||||
Orange: "Oranye",
|
Orange: "Jingga",
|
||||||
Green: "Hijau",
|
Green: "Hijau",
|
||||||
Blue: "Biru",
|
Blue: "Biru",
|
||||||
Indigo: "Indigo",
|
Indigo: "Biru Tua",
|
||||||
Purple: "Ungu",
|
Purple: "Ungu",
|
||||||
Pink: "Merah Muda",
|
Pink: "Merah Muda",
|
||||||
"Search...": "Cari...",
|
"Search...": "Cari...",
|
||||||
"Avg. Ping": "Rata-rata. Ping",
|
"Avg. Ping": "Rata-rata Ping",
|
||||||
"Avg. Response": "Rata-rata. Respon",
|
"Avg. Response": "Rata-rata Tanggapan",
|
||||||
"Entry Page": "Halaman Masuk",
|
"Entry Page": "Halaman Masuk",
|
||||||
statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.",
|
statusPageNothing: "Tidak ada di sini, silakan tambahkan grup atau monitor.",
|
||||||
"No Services": "Tidak ada Layanan",
|
"No Services": "Tidak ada Layanan",
|
||||||
|
@ -177,7 +177,7 @@ export default {
|
||||||
"Add Group": "Tambah Grup",
|
"Add Group": "Tambah Grup",
|
||||||
"Add a monitor": "Tambah monitor",
|
"Add a monitor": "Tambah monitor",
|
||||||
"Edit Status Page": "Edit Halaman Status",
|
"Edit Status Page": "Edit Halaman Status",
|
||||||
"Go to Dashboard": "Lihat Dashboard",
|
"Go to Dashboard": "Pergi ke Dasbor",
|
||||||
"Status Page": "Halaman Status",
|
"Status Page": "Halaman Status",
|
||||||
// Start notification form
|
// Start notification form
|
||||||
defaultNotificationName: "{notification} saya Peringatan ({number})",
|
defaultNotificationName: "{notification} saya Peringatan ({number})",
|
||||||
|
@ -194,22 +194,22 @@ export default {
|
||||||
"webhook": "Webhook",
|
"webhook": "Webhook",
|
||||||
"Post URL": "Post URL",
|
"Post URL": "Post URL",
|
||||||
"Content Type": "Tipe konten",
|
"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}",
|
webhookFormDataDesc: "{multipart} bagus untuk PHP, Anda hanya perlu mengurai json dengan {decodeFunction}",
|
||||||
"smtp": "Email (SMTP)",
|
"smtp": "Surel (SMTP)",
|
||||||
secureOptionNone: "None / STARTTLS (25, 587)",
|
secureOptionNone: "None / STARTTLS (25, 587)",
|
||||||
secureOptionTLS: "TLS (465)",
|
secureOptionTLS: "TLS (465)",
|
||||||
"Ignore TLS Error": "Ignore TLS Error",
|
"Ignore TLS Error": "Abaikan Kesalahan TLS",
|
||||||
"From Email": "From Email",
|
"From Email": "Dari Surel",
|
||||||
"To Email": "To Email",
|
"To Email": "Ke Surel",
|
||||||
smtpCC: "CC",
|
smtpCC: "CC",
|
||||||
smtpBCC: "BCC",
|
smtpBCC: "BCC",
|
||||||
"discord": "Discord",
|
"discord": "Discord",
|
||||||
"Discord Webhook URL": "Discord Webhook URL",
|
"Discord Webhook URL": "Discord Webhook URL",
|
||||||
wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook",
|
wayToGetDiscordURL: "Anda bisa mendapatkan ini dengan pergi ke Server Settings -> Integrations -> Create Webhook",
|
||||||
"Bot Display Name": "Nama Bot",
|
"Bot Display Name": "Nama Bot",
|
||||||
"Prefix Custom Message": "Prefix Pesan",
|
"Prefix Custom Message": "Awalan Pesan",
|
||||||
"Hello @everyone is...": "Hallo {'@'}everyone is...",
|
"Hello @everyone is...": "Halo {'@'}everyone is...",
|
||||||
"teams": "Microsoft Teams",
|
"teams": "Microsoft Teams",
|
||||||
"Webhook URL": "Webhook URL",
|
"Webhook URL": "Webhook URL",
|
||||||
wayToGetTeamsURL: "Anda dapat mempelajari cara membuat url webhook {0}.",
|
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!",
|
signalImportant: "PENTING: Anda tidak dapat mencampur grup dan nomor di penerima!",
|
||||||
"gotify": "Gotify",
|
"gotify": "Gotify",
|
||||||
"Application Token": "Token Aplikasi",
|
"Application Token": "Token Aplikasi",
|
||||||
"Server URL": "Server URL",
|
"Server URL": "URL Peladen",
|
||||||
"Priority": "Prioritas",
|
"Priority": "Prioritas",
|
||||||
"slack": "Slack",
|
"slack": "Slack",
|
||||||
"Icon Emoji": "Icon Emoji",
|
"Icon Emoji": "Ikon Emoji",
|
||||||
"Channel Name": "Nama Channel",
|
"Channel Name": "Nama Saluran",
|
||||||
"Uptime Kuma URL": "Uptime Kuma URL",
|
"Uptime Kuma URL": "Uptime Kuma URL",
|
||||||
aboutWebhooks: "Info lain tentang webhook: {0}",
|
aboutWebhooks: "Info lain tentang webhook: {0}",
|
||||||
aboutChannelName: "Masukan nama channel di {0} Kolom Nama Channel jika Anda ingin melewati channel webhook. Contoh: #other-channel",
|
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 default ke halaman Project Github.",
|
aboutKumaURL: "Jika Anda membiarkan bidang URL Uptime Kuma kosong, itu akan menjadi bawaan ke halaman Proyek Github.",
|
||||||
emojiCheatSheet: "Emoji cheat sheet: {0}",
|
emojiCheatSheet: "Lembar contekan emoji: {0}",
|
||||||
"rocket.chat": "Rocket.chat",
|
"rocket.chat": "Rocket.chat",
|
||||||
pushover: "Pushover",
|
pushover: "Pushover",
|
||||||
pushy: "Pushy",
|
pushy: "Pushy",
|
||||||
|
@ -246,7 +246,7 @@ export default {
|
||||||
"Message Title": "Judul Pesan",
|
"Message Title": "Judul Pesan",
|
||||||
"Notification Sound": "Suara Nofifikasi",
|
"Notification Sound": "Suara Nofifikasi",
|
||||||
"More info on:": "Info lebih lanjut tentang: {0}",
|
"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.",
|
pushoverDesc2: "Jika Anda ingin mengirim pemberitahuan ke perangkat yang berbeda, isi kolom Perangkat.",
|
||||||
"SMS Type": "Tipe SMS",
|
"SMS Type": "Tipe SMS",
|
||||||
octopushTypePremium: "Premium (Cepat - direkomendasikan untuk mengingatkan)",
|
octopushTypePremium: "Premium (Cepat - direkomendasikan untuk mengingatkan)",
|
||||||
|
@ -262,24 +262,24 @@ export default {
|
||||||
"Read more": "Baca lebih lajut",
|
"Read more": "Baca lebih lajut",
|
||||||
appriseInstalled: "Apprise diinstall.",
|
appriseInstalled: "Apprise diinstall.",
|
||||||
appriseNotInstalled: "Apprise tidak diinstall. {0}",
|
appriseNotInstalled: "Apprise tidak diinstall. {0}",
|
||||||
"Access Token": "Access Token",
|
"Access Token": "Token Akses",
|
||||||
"Channel access token": "Channel access token",
|
"Channel access token": "Token akses saluran",
|
||||||
"Line Developers Console": "Line Developers Console",
|
"Line Developers Console": "Konsol Pengembang Line",
|
||||||
lineDevConsoleTo: "Line Developers Console - {0}",
|
lineDevConsoleTo: "Konsol Pengembang Line - {0}",
|
||||||
"Basic Settings": "Pengaturan dasar",
|
"Basic Settings": "Pengaturan Dasar",
|
||||||
"User ID": "User ID",
|
"User ID": "ID User",
|
||||||
"Messaging API": "Messaging API",
|
"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.",
|
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",
|
"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.",
|
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 default 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",
|
"matrix": "Matrix",
|
||||||
promosmsTypeEco: "SMS ECO - murah tapi lambat dan sering kelebihan beban. Terbatas hanya untuk penerima Polandia.",
|
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.",
|
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.",
|
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).",
|
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)",
|
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",
|
"Feishu WebHookUrl": "Feishu WebHookUrl",
|
||||||
// End notification form
|
// End notification form
|
||||||
};
|
};
|
||||||
|
|
|
@ -198,4 +198,12 @@ export default {
|
||||||
pushbullet: "Pushbullet",
|
pushbullet: "Pushbullet",
|
||||||
line: "Line Messenger",
|
line: "Line Messenger",
|
||||||
mattermost: "Mattermost",
|
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 -->
|
<!-- Push URL -->
|
||||||
<div v-if="monitor.type === 'push' " class="my-3">
|
<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" />
|
<CopyableInput id="push-url" v-model="pushURL" type="url" disabled="disabled" />
|
||||||
<div class="form-text">
|
<div class="form-text">
|
||||||
You should call this url every {{ monitor.interval }} seconds.<br />
|
You should call this url every {{ monitor.interval }} seconds.<br />
|
||||||
|
@ -196,6 +196,7 @@
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<div v-if="$root.isMobile" class="mt-3" />
|
<div v-if="$root.isMobile" class="mt-3" />
|
||||||
|
|
||||||
|
<!-- Notifications -->
|
||||||
<h2 class="mb-2">{{ $t("Notifications") }}</h2>
|
<h2 class="mb-2">{{ $t("Notifications") }}</h2>
|
||||||
<p v-if="$root.notificationList.length === 0">
|
<p v-if="$root.notificationList.length === 0">
|
||||||
{{ $t("Not available, please setup.") }}
|
{{ $t("Not available, please setup.") }}
|
||||||
|
@ -215,6 +216,51 @@
|
||||||
<button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
|
<button class="btn btn-primary me-2" type="button" @click="$refs.notificationDialog.show()">
|
||||||
{{ $t("Setup Notification") }}
|
{{ $t("Setup Notification") }}
|
||||||
</button>
|
</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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -286,6 +332,14 @@ export default {
|
||||||
|
|
||||||
pushURL() {
|
pushURL() {
|
||||||
return this.$root.baseURL + "/api/push/" + this.monitor.pushToken + "?msg=OK&ping=";
|
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) {
|
"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) {
|
if (this.monitor.retryInterval === oldValue) {
|
||||||
this.monitor.retryInterval = value;
|
this.monitor.retryInterval = value;
|
||||||
}
|
}
|
||||||
|
@ -350,6 +404,7 @@ export default {
|
||||||
type: "http",
|
type: "http",
|
||||||
name: "",
|
name: "",
|
||||||
url: "https://",
|
url: "https://",
|
||||||
|
method: "GET",
|
||||||
interval: 60,
|
interval: 60,
|
||||||
retryInterval: this.interval,
|
retryInterval: this.interval,
|
||||||
maxretries: 0,
|
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() {
|
async submit() {
|
||||||
this.processing = true;
|
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) {
|
if (this.isAdd) {
|
||||||
this.$root.add(this.monitor, async (res) => {
|
this.$root.add(this.monitor, async (res) => {
|
||||||
|
|
||||||
|
@ -419,12 +508,22 @@ export default {
|
||||||
addedNotification(id) {
|
addedNotification(id) {
|
||||||
this.monitor.notificationIDList[id] = true;
|
this.monitor.notificationIDList[id] = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
decodeHtml(html) {
|
||||||
|
const txt = document.createElement("textarea");
|
||||||
|
txt.innerHTML = html;
|
||||||
|
return txt.value;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.shadow-box {
|
.shadow-box {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -334,9 +334,9 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="$i18n.locale === 'id-ID' ">
|
<template v-else-if="$i18n.locale === 'id-ID' ">
|
||||||
<p> Apakah Anda yakin ingin <strong>menonaktifkan autentikasi</strong>? </p>
|
<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>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>
|
<p>Gunakan dengan hati-hati.</p>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-else-if="$i18n.locale === 'ru-RU' ">
|
<template v-else-if="$i18n.locale === 'ru-RU' ">
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
const { genSecret } = require("../src/util");
|
const { genSecret, sleep } = require("../src/util");
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Test genSecret", () => {
|
describe("Test genSecret", () => {
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
it("should be correct length", () => {
|
it("should be correct length", () => {
|
||||||
let secret = genSecret(-1);
|
let secret = genSecret(-1);
|
||||||
expect(secret).toEqual("");
|
expect(secret).toEqual("");
|
||||||
|
@ -34,4 +34,11 @@ describe("Test genSecret", () => {
|
||||||
expect(secret).toContain("A");
|
expect(secret).toContain("A");
|
||||||
expect(secret).toContain("9");
|
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