- Subject: |
+ {{ $t("Subject:") }} |
{{ formatSubject(cert.subject) }} |
- Valid To: |
+ {{ $t("Valid To:") }} |
|
- Days Remaining: |
+ {{ $t("Days Remaining:") }} |
{{ cert.daysRemaining }} |
- Issuer: |
+ {{ $t("Issuer:") }} |
{{ formatSubject(cert.issuer) }} |
- Fingerprint: |
+ {{ $t("Fingerprint:") }} |
{{ cert.fingerprint }} |
diff --git a/src/components/Confirm.vue b/src/components/Confirm.vue
index 391155f4..1bfe7fe4 100644
--- a/src/components/Confirm.vue
+++ b/src/components/Confirm.vue
@@ -25,7 +25,7 @@
diff --git a/src/components/CopyableInput.vue b/src/components/CopyableInput.vue
index 1fe89802..1bccfa2c 100644
--- a/src/components/CopyableInput.vue
+++ b/src/components/CopyableInput.vue
@@ -57,6 +57,7 @@ export default {
default: undefined,
},
},
+ emits: [ "update:modelValue" ],
data() {
return {
visibility: "password",
diff --git a/src/components/CountUp.vue b/src/components/CountUp.vue
index b321fde1..41edc4a0 100644
--- a/src/components/CountUp.vue
+++ b/src/components/CountUp.vue
@@ -5,12 +5,12 @@
diff --git a/src/components/Datetime.vue b/src/components/Datetime.vue
index 1df982cb..8662e6d8 100644
--- a/src/components/Datetime.vue
+++ b/src/components/Datetime.vue
@@ -4,12 +4,12 @@
diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue
index be0b122e..245a8512 100644
--- a/src/components/HeartbeatBar.vue
+++ b/src/components/HeartbeatBar.vue
@@ -38,7 +38,7 @@ export default {
beatMargin: 4,
move: false,
maxBeat: -1,
- }
+ };
},
computed: {
@@ -69,12 +69,12 @@ export default {
if (start < 0) {
// Add empty placeholder
for (let i = start; i < 0; i++) {
- placeholders.push(0)
+ placeholders.push(0);
}
start = 0;
}
- return placeholders.concat(this.beatList.slice(start))
+ return placeholders.concat(this.beatList.slice(start));
},
wrapStyle() {
@@ -84,7 +84,7 @@ export default {
return {
padding: `${topBottom}px ${leftRight}px`,
width: "100%",
- }
+ };
},
barStyle() {
@@ -94,12 +94,12 @@ export default {
return {
transition: "all ease-in-out 0.25s",
transform: `translateX(${width}px)`,
- }
+ };
}
return {
transform: "translateX(0)",
- }
+ };
},
@@ -109,7 +109,7 @@ export default {
height: this.beatHeight + "px",
margin: this.beatMargin + "px",
"--hover-scale": this.hoverScale,
- }
+ };
},
},
@@ -120,7 +120,7 @@ export default {
setTimeout(() => {
this.move = false;
- }, 300)
+ }, 300);
},
deep: true,
},
@@ -162,15 +162,15 @@ export default {
methods: {
resize() {
if (this.$refs.wrap) {
- this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2))
+ this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2));
}
},
getBeatTitle(beat) {
- return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ``);
+ return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : "");
}
},
-}
+};
diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue
index 8c03dbbd..7a1f1a10 100644
--- a/src/components/NotificationDialog.vue
+++ b/src/components/NotificationDialog.vue
@@ -69,7 +69,6 @@
@@ -278,7 +286,7 @@ export default {
.dropdown-item {
border-radius: 0.3rem;
- padding: 2px 16px 4px 16px;
+ padding: 2px 16px 4px;
.dark & {
background: $dark-bg;
@@ -286,6 +294,7 @@ export default {
.dark &:hover {
background: $dark-font-color;
+ color: $dark-font-color2;
}
}
diff --git a/src/components/ProxyDialog.vue b/src/components/ProxyDialog.vue
new file mode 100644
index 00000000..3070925c
--- /dev/null
+++ b/src/components/ProxyDialog.vue
@@ -0,0 +1,206 @@
+
+
+
+
+ {{ $t("deleteProxyMsg") }}
+
+
+
+
+
+
diff --git a/src/components/PublicGroupList.vue b/src/components/PublicGroupList.vue
index 37440e31..df94eec9 100644
--- a/src/components/PublicGroupList.vue
+++ b/src/components/PublicGroupList.vue
@@ -145,7 +145,7 @@ export default {
.mobile {
.item {
- padding: 13px 0 10px 0;
+ padding: 13px 0 10px;
}
}
diff --git a/src/components/Tag.vue b/src/components/Tag.vue
index 434358aa..364a05c6 100644
--- a/src/components/Tag.vue
+++ b/src/components/Tag.vue
@@ -41,7 +41,7 @@ export default {
}
}
}
-}
+};
diff --git a/src/components/settings/MonitorHistory.vue b/src/components/settings/MonitorHistory.vue
index 9b5b8bd7..0092727f 100644
--- a/src/components/settings/MonitorHistory.vue
+++ b/src/components/settings/MonitorHistory.vue
@@ -52,7 +52,7 @@
-
-
diff --git a/src/components/settings/Proxies.vue b/src/components/settings/Proxies.vue
new file mode 100644
index 00000000..4608f3aa
--- /dev/null
+++ b/src/components/settings/Proxies.vue
@@ -0,0 +1,48 @@
+
+
+
+
+
+ {{ $t("Not available, please setup.") }}
+
+
+ {{ $t("proxyDescription") }}
+
+
+
+ -
+ {{ proxy.host }}:{{ proxy.port }} ({{ proxy.protocol }})
+ {{ $t("Default") }}
+ {{ $t("Edit") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/settings/ReverseProxy.vue b/src/components/settings/ReverseProxy.vue
new file mode 100644
index 00000000..97db4d59
--- /dev/null
+++ b/src/components/settings/ReverseProxy.vue
@@ -0,0 +1,144 @@
+
+
+
Cloudflare Tunnel
+
+
+
+ cloudflared:
+ {{ $t("Installed") }}
+ {{ $t("Not installed") }}
+
+
+
+ {{ $t("Status") }}:
+ {{ $t("Running") }}
+ {{ $t("Not running") }}
+
+
+
+ {{ message }}
+
+
+
+ {{ $t("Message:") }}
+
+
+
+
+ {{ $t("cloudflareWebsite") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $t("The current connection may be lost if you are currently connecting via Cloudflare Tunnel. Are you sure want to stop it? Type your current password to confirm it.") }}
+
+
+
+
+
+
+
+
+
+
{{ $t("Other Software") }}
+
+
+
+
+
+
+
diff --git a/src/components/settings/Security.vue b/src/components/settings/Security.vue
index ede0d90c..e5960004 100644
--- a/src/components/settings/Security.vue
+++ b/src/components/settings/Security.vue
@@ -192,6 +192,12 @@
Пожалуйста, используйте с осторожностью.
+
+ Ви впевнені, що бажаєте вимкнути авторизацію?
+ Це підходить для тих, у кого встановлена інша авторизація пееред відкриттям Uptime Kuma, наприклад Cloudflare Access.
+ Будь ласка, використовуйте з обережністю.
+
+
آیا مطمئن هستید که میخواهید احراز هویت را غیر فعال کنید?
این ویژگی برای کسانی است که لایه امنیتی شخص ثالث دیگر بر روی این آدرس فعال کردهاند، مانند Cloudflare Access.
@@ -215,14 +221,14 @@
Dette er for de som har tredjepartsautorisering foran Uptime Kuma, for eksempel Cloudflare Access.
Vennligst vær forsiktig.
-
+
Opravdu chcete deaktivovat autentifikaci?
Tato možnost je určena pro případy, kdy máte autentifikaci zajištěnou třetí stranou ještě před přístupem do Uptime Kuma, například prostřednictvím Cloudflare Access.
Používejte ji prosím s rozmyslem.
-
+
Bạn có muốn TẮT XÁC THỰC không?
Điều này rất nguy hiểmBẤT KỲ AI cũng có thể truy cập và cướp quyền điều khiển.
Vui lòng cẩn thận.
@@ -234,6 +240,19 @@
It is designed for scenarios where you intend to implement third-party authentication in front of Uptime Kuma such as Cloudflare Access, Authelia or other authentication mechanisms.
Please use this option carefully!
+
+
+
+
+
@@ -310,7 +329,12 @@ export default {
disableAuth() {
this.settings.disableAuth = true;
- this.saveSettings();
+
+ // Need current password to disable auth
+ // Set it to empty if done
+ this.saveSettings(() => {
+ this.password.currentPassword = "";
+ }, this.password.currentPassword);
},
enableAuth() {
@@ -331,7 +355,7 @@ export default {
diff --git a/src/router.js b/src/router.js
index f59192d3..c07f68c9 100644
--- a/src/router.js
+++ b/src/router.js
@@ -14,8 +14,10 @@ import Entry from "./pages/Entry.vue";
import Appearance from "./components/settings/Appearance.vue";
import General from "./components/settings/General.vue";
import Notifications from "./components/settings/Notifications.vue";
+import ReverseProxy from "./components/settings/ReverseProxy.vue";
import MonitorHistory from "./components/settings/MonitorHistory.vue";
import Security from "./components/settings/Security.vue";
+import Proxies from "./components/settings/Proxies.vue";
import Backup from "./components/settings/Backup.vue";
import About from "./components/settings/About.vue";
import ManageStatusPage from "./pages/ManageStatusPage.vue";
@@ -83,6 +85,10 @@ const routes = [
path: "notifications",
component: Notifications,
},
+ {
+ path: "reverse-proxy",
+ component: ReverseProxy,
+ },
{
path: "monitor-history",
component: MonitorHistory,
@@ -91,6 +97,10 @@ const routes = [
path: "security",
component: Security,
},
+ {
+ path: "proxies",
+ component: Proxies,
+ },
{
path: "backup",
component: Backup,
diff --git a/src/util-frontend.js b/src/util-frontend.js
index bf53eaf5..565b053c 100644
--- a/src/util-frontend.js
+++ b/src/util-frontend.js
@@ -7,6 +7,12 @@ import { localeDirection, currentLocale } from "./i18n";
dayjs.extend(utc);
dayjs.extend(timezone);
+/**
+ * Returns the offset from UTC in hours for the current locale.
+ * @returns {number} The offset from UTC in hours.
+ *
+ * Generated by Trelent
+ */
function getTimezoneOffset(timeZone) {
const now = new Date();
const tzString = now.toLocaleString("en-US", {
@@ -18,6 +24,13 @@ function getTimezoneOffset(timeZone) {
return -offset;
}
+/**
+* Returns a list of timezones sorted by their offset from UTC.
+* @param {Array} timezones - An array of timezone objects.
+* @returns {Array} A list of the given timezones sorted by their offset from UTC.
+*
+* Generated by Trelent
+*/
export function timezoneList() {
let result = [];
diff --git a/src/util.js b/src/util.js
index b2df7ac7..b1f55201 100644
--- a/src/util.js
+++ b/src/util.js
@@ -7,7 +7,7 @@
// Backend uses the compiled file util.js
// Frontend uses util.ts
Object.defineProperty(exports, "__esModule", { value: true });
-exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
+exports.getMonitorRelativeURL = exports.genSecret = exports.getCryptoRandomInt = exports.getRandomInt = exports.getRandomArbitrary = exports.TimeLogger = exports.polyfill = exports.log = exports.debug = exports.ucfirst = exports.sleep = exports.flipStatus = exports.STATUS_PAGE_PARTIAL_DOWN = exports.STATUS_PAGE_ALL_UP = exports.STATUS_PAGE_ALL_DOWN = exports.PENDING = exports.UP = exports.DOWN = exports.appName = exports.isDev = void 0;
const _dayjs = require("dayjs");
const dayjs = _dayjs;
exports.isDev = process.env.NODE_ENV === "development";
@@ -44,12 +44,92 @@ function ucfirst(str) {
return firstLetter.toUpperCase() + str.substr(1);
}
exports.ucfirst = ucfirst;
+/**
+ * @deprecated Use log.debug
+ * @since https://github.com/louislam/uptime-kuma/pull/910
+ * @param msg
+ */
function debug(msg) {
- if (exports.isDev) {
- console.log(msg);
- }
+ exports.log.log("", msg, "debug");
}
exports.debug = debug;
+class Logger {
+ constructor() {
+ /**
+ * UPTIME_KUMA_HIDE_LOG=debug_monitor,info_monitor
+ *
+ * Example:
+ * [
+ * "debug_monitor", // Hide all logs that level is debug and the module is monitor
+ * "info_monitor",
+ * ]
+ */
+ this.hideLog = {
+ info: [],
+ warn: [],
+ error: [],
+ debug: [],
+ };
+ if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) {
+ let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
+ for (let pair of list) {
+ // split first "_" only
+ let values = pair.split(/_(.*)/s);
+ if (values.length >= 2) {
+ this.hideLog[values[0]].push(values[1]);
+ }
+ }
+ this.debug("server", "UPTIME_KUMA_HIDE_LOG is set");
+ this.debug("server", this.hideLog);
+ }
+ }
+ log(module, msg, level) {
+ if (this.hideLog[level] && this.hideLog[level].includes(module)) {
+ return;
+ }
+ module = module.toUpperCase();
+ level = level.toUpperCase();
+ const now = new Date().toISOString();
+ const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
+ if (level === "INFO") {
+ console.info(formattedMessage);
+ }
+ else if (level === "WARN") {
+ console.warn(formattedMessage);
+ }
+ else if (level === "ERROR") {
+ console.error(formattedMessage);
+ }
+ else if (level === "DEBUG") {
+ if (exports.isDev) {
+ console.debug(formattedMessage);
+ }
+ }
+ else {
+ console.log(formattedMessage);
+ }
+ }
+ info(module, msg) {
+ this.log(module, msg, "info");
+ }
+ warn(module, msg) {
+ this.log(module, msg, "warn");
+ }
+ error(module, msg) {
+ this.log(module, msg, "error");
+ }
+ debug(module, msg) {
+ this.log(module, msg, "debug");
+ }
+ exception(module, exception, msg) {
+ let finalMessage = exception;
+ if (msg) {
+ finalMessage = `${msg}: ${exception}`;
+ }
+ this.log(module, finalMessage, "error");
+ }
+}
+exports.log = new Logger();
function polyfill() {
/**
* String.prototype.replaceAll() polyfill
diff --git a/src/util.ts b/src/util.ts
index 633d933e..75abd662 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -49,12 +49,105 @@ export function ucfirst(str: string) {
return firstLetter.toUpperCase() + str.substr(1);
}
+/**
+ * @deprecated Use log.debug
+ * @since https://github.com/louislam/uptime-kuma/pull/910
+ * @param msg
+ */
export function debug(msg: any) {
- if (isDev) {
- console.log(msg);
+ log.log("", msg, "debug");
+}
+
+class Logger {
+
+ /**
+ * UPTIME_KUMA_HIDE_LOG=debug_monitor,info_monitor
+ *
+ * Example:
+ * [
+ * "debug_monitor", // Hide all logs that level is debug and the module is monitor
+ * "info_monitor",
+ * ]
+ */
+ hideLog : any = {
+ info: [],
+ warn: [],
+ error: [],
+ debug: [],
+ };
+
+ constructor() {
+ if (typeof process !== "undefined" && process.env.UPTIME_KUMA_HIDE_LOG) {
+ let list = process.env.UPTIME_KUMA_HIDE_LOG.split(",").map(v => v.toLowerCase());
+
+ for (let pair of list) {
+ // split first "_" only
+ let values = pair.split(/_(.*)/s);
+
+ if (values.length >= 2) {
+ this.hideLog[values[0]].push(values[1]);
+ }
+ }
+
+ this.debug("server", "UPTIME_KUMA_HIDE_LOG is set");
+ this.debug("server", this.hideLog);
+ }
+ }
+
+ log(module: string, msg: any, level: string) {
+ if (this.hideLog[level] && this.hideLog[level].includes(module)) {
+ return;
+ }
+
+ module = module.toUpperCase();
+ level = level.toUpperCase();
+
+ const now = new Date().toISOString();
+ const formattedMessage = (typeof msg === "string") ? `${now} [${module}] ${level}: ${msg}` : msg;
+
+ if (level === "INFO") {
+ console.info(formattedMessage);
+ } else if (level === "WARN") {
+ console.warn(formattedMessage);
+ } else if (level === "ERROR") {
+ console.error(formattedMessage);
+ } else if (level === "DEBUG") {
+ if (isDev) {
+ console.debug(formattedMessage);
+ }
+ } else {
+ console.log(formattedMessage);
+ }
+ }
+
+ info(module: string, msg: any) {
+ this.log(module, msg, "info");
+ }
+
+ warn(module: string, msg: any) {
+ this.log(module, msg, "warn");
+ }
+
+ error(module: string, msg: any) {
+ this.log(module, msg, "error");
+ }
+
+ debug(module: string, msg: any) {
+ this.log(module, msg, "debug");
+ }
+
+ exception(module: string, exception: any, msg: any) {
+ let finalMessage = exception
+
+ if (msg) {
+ finalMessage = `${msg}: ${exception}`
+ }
+
+ this.log(module, finalMessage , "error");
}
}
+export const log = new Logger();
declare global { interface String { replaceAll(str: string, newStr: string): string; } }
diff --git a/test/backend.spec.js b/test/backend.spec.js
index bbfc6897..86b83fa5 100644
--- a/test/backend.spec.js
+++ b/test/backend.spec.js
@@ -1,4 +1,4 @@
-const { genSecret, sleep } = require("../src/util");
+const { genSecret } = require("../src/util");
const utilServerRewire = require("../server/util-server");
describe("Test parseCertificateInfo", () => {
diff --git a/test/e2e.spec.js b/test/e2e.spec.js
index d4835d1c..5535f57d 100644
--- a/test/e2e.spec.js
+++ b/test/e2e.spec.js
@@ -1,7 +1,6 @@
// eslint-disable-next-line no-unused-vars
const { Page, Browser } = require("puppeteer");
const { sleep } = require("../src/util");
-const axios = require("axios");
/**
* Set back the correct data type for page object
diff --git a/test/prepare-jest.js b/test/prepare-jest.js
index 9dfaba7d..3fd89d10 100644
--- a/test/prepare-jest.js
+++ b/test/prepare-jest.js
@@ -1,9 +1,10 @@
const fs = require("fs");
+const rmSync = require("../extra/fs-rmSync.js");
const path = "./data/test-chrome-profile";
if (fs.existsSync(path)) {
- fs.rmdirSync(path, {
+ rmSync(path, {
recursive: true,
});
}
diff --git a/test/prepare-test-server.js b/test/prepare-test-server.js
index 0e49c7fb..1a9b04df 100644
--- a/test/prepare-test-server.js
+++ b/test/prepare-test-server.js
@@ -1,9 +1,10 @@
const fs = require("fs");
+const rmSync = require("../extra/fs-rmSync.js");
const path = "./data/test";
if (fs.existsSync(path)) {
- fs.rmdirSync(path, {
+ rmSync(path, {
recursive: true,
});
}