Compare commits

...

30 Commits

Author SHA1 Message Date
Frank Elsinga
4b0e7de3e4 fixed linting issues 2024-06-04 01:23:51 +02:00
Frank Elsinga
2a556e714f implemented additional changes 2024-06-04 01:11:13 +02:00
mueller-ma
7f0d3a3043 Add custom html code to head
With this PR a new text field will be added that allows setting custom
html code to the `<head>` of a status page.
The implementation will be similar to
https://github.com/louislam/uptime-kuma/pull/2567/files, but with a
multi-line text field and without escaping any special chars.

For security reasons the env var `UPTIME_KUMA_ALLOW_CUSTOM_HTML` must be set to `1` to enable this feature.

This will allow tracking with most analytic platforms and has been
requested several times.

Closes #2818
2024-06-04 00:31:47 +02:00
Frank Elsinga
10ebdcacaa Fix: Use retryInterval when a monitor is DOWN (#4476) 2024-06-03 21:47:43 +02:00
Frank Elsinga
a00b4ed285 Feat: Add background color change on hover to nav links (#4494) 2024-06-03 21:06:23 +02:00
Frank Elsinga
a26d93ac52 Merge branch 'master' into nav-link-hover 2024-06-03 21:04:50 +02:00
DevMirza
c919d2c990 fix(ci): Prevent ARM runner from running in Forks (#4803) 2024-05-30 14:46:04 +08:00
Frank Elsinga
40d24e7837 feat: update feishu notification template (#4800) 2024-05-29 18:19:53 +02:00
nino
30bf7a5e23 fix: update Feishu notification provider configuration 2024-05-29 22:22:05 +08:00
nino
4e63d00007 feat: update feishu notification template 2024-05-29 18:20:33 +08:00
Frank Elsinga
9f35290c68 made sure that the Set up a Docker Builder section in the contribution guide is layouted like the rest 2024-05-29 11:03:37 +02:00
Frank Elsinga
11007823e7 feat: added HTTP method option for push monitor (#1991) 2024-05-24 10:26:58 +02:00
Stefan Ottosson
9ce0911e34 Merge branch 'master' into feature/http-method-push-monitor 2024-05-24 09:05:11 +02:00
Stefan Ottosson
df663a81cd Update src/pages/EditMonitor.vue
Co-authored-by: Frank Elsinga <frank@elsinga.de>
2024-05-24 09:04:12 +02:00
Stefan Ottosson
8b648a3ed1 Revert "fix: hide body options for monitor type push"
This reverts commit e670b5f4cf.
2024-05-24 08:29:22 +02:00
Stefan Ottosson
9c7aa13190 fix: remove check that method is correct 2024-05-24 08:29:09 +02:00
Stefan Ottosson
823aeda9fe Revert "fix: update some examples"
This reverts commit b2ede38269.
2024-05-24 08:26:28 +02:00
Frank Elsinga
1590ca6c02 made sure that json-query for the mqtt monitor is translated properly (#4791) 2024-05-23 20:37:02 +02:00
Stefan Ottosson
e670b5f4cf fix: hide body options for monitor type push 2024-05-23 17:49:18 +02:00
Stefan Ottosson
b2ede38269 fix: update some examples 2024-05-23 17:42:36 +02:00
Stefan Ottosson
1ac5696463 Merge branch 'master' into feature/http-method-push-monitor
# Conflicts:
#	src/pages/EditMonitor.vue
2024-05-23 17:34:45 +02:00
Frank Elsinga
63b8c52a65 made sure that json-query for the mqtt monitor is translated properly 2024-05-23 14:48:12 +02:00
NihadBadalov
17dfdacd93 Fix: Correct colors 2024-02-20 17:52:59 +01:00
NihadBadalov
94154c49aa Feat: Change hover colors to shades of gray 2024-02-15 08:21:54 +01:00
NihadBadalov
4d6ea433e6 Feat: Add background color change on hover to nav links 2024-02-14 22:51:06 +01:00
Frank Elsinga
81e465f418 Removed debug statement 2024-02-11 20:02:09 +01:00
Neel Bhanushali
a5d0f7a7db console added with double quotes and semicolons. console added with username so i can remove later 2024-02-11 21:42:20 +05:30
Neel Bhanushali
a16b42f98c poc done 2024-02-11 21:33:58 +05:30
Neel Bhanushali
65ff08b38e lower heartbeat interval when monitor is down #4025 2024-02-11 20:19:56 +05:30
Stefan Ottosson
f89ed0a3a4 feat: added HTTP method option for push monitor 2022-08-12 18:52:23 +02:00
13 changed files with 150 additions and 71 deletions

View File

@@ -45,7 +45,7 @@ jobs:
needs: [ check-linters ]
runs-on: ${{ matrix.os }}
timeout-minutes: 15
if: ${{ github.repository == 'louislam/uptime-kuma' }}
strategy:
matrix:
os: [ ARMv7 ]

View File

@@ -427,7 +427,33 @@ Currently, there are 3 maintainers:
### Procedures
We have a few procedures we follow. These are documented here:
- <details><summary>Set up a Docker Builder</summary>
<p>
- amd64, armv7 using local.
- arm64 using remote arm64 cpu, as the emulator is too slow and can no longer pass the `npm ci` command.
1. Add the public key to the remote server.
2. Add the remote context. The remote machine must be arm64 and installed Docker CE.
```
docker context create oracle-arm64-jp --docker "host=ssh://root@100.107.174.88"
```
3. Create a new builder.
```
docker buildx create --name kuma-builder --platform linux/amd64,linux/arm/v7
docker buildx use kuma-builder
docker buildx inspect --bootstrap
```
4. Append the remote context to the builder.
```
docker buildx create --append --name kuma-builder --platform linux/arm64 oracle-arm64-jp
```
5. Verify the builder and check if the builder is using `kuma-builder`.
```
docker buildx inspect kuma-builder
docker buildx ls
```
</p>
</details>
- <details><summary>Release</summary>
<p>
@@ -490,28 +516,3 @@ We have a few procedures we follow. These are documented here:
</p>
</details>
### Set up a Docker Builder
- amd64, armv7 using local.
- arm64 using remote arm64 cpu, as the emulator is too slow and can no longer pass the `npm ci` command.
1. Add the public key to the remote server.
2. Add the remote context. The remote machine must be arm64 and installed Docker CE.
```
docker context create oracle-arm64-jp --docker "host=ssh://root@100.107.174.88"
```
3. Create a new builder.
```
docker buildx create --name kuma-builder --platform linux/amd64,linux/arm/v7
docker buildx use kuma-builder
docker buildx inspect --bootstrap
```
4. Append the remote context to the builder.
```
docker buildx create --append --name kuma-builder --platform linux/arm64 oracle-arm64-jp
```
5. Verify the builder and check if the builder is using `kuma-builder`.
```
docker buildx inspect kuma-builder
docker buildx ls
```

View File

@@ -0,0 +1,14 @@
exports.up = function (knex) {
// Insert column for custom HTML code
return knex.schema
.alterTable("status_page", function (table) {
table.text("custom_html").nullable().defaultTo(null);
});
};
exports.down = function (knex) {
return knex.schema
.alterTable("status_page", function (table) {
table.dropColumn("custom_html");
});
};

2
package-lock.json generated
View File

@@ -74,7 +74,7 @@
"socket.io": "~4.6.1",
"socket.io-client": "~4.6.1",
"socks-proxy-agent": "6.1.1",
"sqlite3": "^5.1.7",
"sqlite3": "~5.1.7",
"tar": "~6.2.1",
"tcp-ping": "~0.1.1",
"thirty-two": "~1.0.2",

View File

@@ -897,7 +897,6 @@ class Monitor extends BeanModel {
retries = 0;
} catch (error) {
if (error?.name === "CanceledError") {
bean.msg = `timeout by AbortSignal (${this.timeout}s)`;
} else {
@@ -970,6 +969,7 @@ class Monitor extends BeanModel {
} else if (bean.status === MAINTENANCE) {
log.warn("monitor", `Monitor #${this.id} '${this.name}': Under Maintenance | Type: ${this.type}`);
} else {
beatInterval = this.retryInterval;
log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type} | Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`);
}

View File

@@ -66,6 +66,10 @@ class StatusPage extends BeanModel {
head.append($(escapedGoogleAnalyticsScript));
}
if (process.env.UPTIME_KUMA_ALLOW_CUSTOM_HTML === "1") {
head.append(statusPage.customHtml);
}
// OG Meta Tags
let ogTitle = $("<meta property=\"og:title\" content=\"\" />").attr("content", statusPage.title);
head.append(ogTitle);
@@ -247,6 +251,7 @@ class StatusPage extends BeanModel {
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
customHtml: this.custom_html
};
}
@@ -270,6 +275,7 @@ class StatusPage extends BeanModel {
showPoweredBy: !!this.show_powered_by,
googleAnalyticsId: this.google_analytics_tag_id,
showCertificateExpiry: !!this.show_certificate_expiry,
customHtml: this.custom_html
};
}

View File

@@ -25,25 +25,29 @@ class Feishu extends NotificationProvider {
if (heartbeatJSON["status"] === DOWN) {
let downdata = {
msg_type: "post",
content: {
post: {
zh_cn: {
title: "UptimeKuma Alert: [Down] " + monitorJSON["name"],
content: [
[
{
tag: "text",
text:
"[Down] " +
heartbeatJSON["msg"] +
`\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`
},
],
],
},
msg_type: "interactive",
card: {
config: {
update_multi: false,
wide_screen_mode: true,
},
},
header: {
title: {
tag: "plain_text",
content: "UptimeKuma Alert: [Down] " + monitorJSON["name"],
},
template: "red",
},
elements: [
{
tag: "div",
text: {
tag: "lark_md",
content: getContent(heartbeatJSON),
},
}
]
}
};
await axios.post(notification.feishuWebHookUrl, downdata);
return okMsg;
@@ -51,25 +55,29 @@ class Feishu extends NotificationProvider {
if (heartbeatJSON["status"] === UP) {
let updata = {
msg_type: "post",
content: {
post: {
zh_cn: {
title: "UptimeKuma Alert: [Up] " + monitorJSON["name"],
content: [
[
{
tag: "text",
text:
"[Up] " +
heartbeatJSON["msg"] +
`\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`,
},
],
],
},
msg_type: "interactive",
card: {
config: {
update_multi: false,
wide_screen_mode: true,
},
},
header: {
title: {
tag: "plain_text",
content: "UptimeKuma Alert: [UP] " + monitorJSON["name"],
},
template: "green",
},
elements: [
{
tag: "div",
text: {
tag: "lark_md",
content: getContent(heartbeatJSON),
},
},
]
}
};
await axios.post(notification.feishuWebHookUrl, updata);
return okMsg;
@@ -80,4 +88,17 @@ class Feishu extends NotificationProvider {
}
}
/**
* Get content
* @param {?object} heartbeatJSON Heartbeat details (For Up/Down only)
* @returns {string} Return Successful Message
*/
function getContent(heartbeatJSON) {
return [
"**Message**: " + heartbeatJSON["msg"],
"**Ping**: " + (heartbeatJSON["ping"] == null ? "N/A" : heartbeatJSON["ping"] + " ms"),
`**Time (${heartbeatJSON["timezone"]})**: ${heartbeatJSON["localDateTime"]}`
].join("\n");
}
module.exports = Feishu;

View File

@@ -44,9 +44,8 @@ router.get("/api/entry-page", async (request, response) => {
response.json(result);
});
router.get("/api/push/:pushToken", async (request, response) => {
router.all("/api/push/:pushToken", async (request, response) => {
try {
let pushToken = request.params.pushToken;
let msg = request.query.msg || "OK";
let ping = parseFloat(request.query.ping) || null;

View File

@@ -101,10 +101,11 @@ module.exports.statusPageSocketHandler = (socket) => {
if (!statusPage) {
throw new Error("No slug?");
}
const config = await statusPage.toJSON();
config.allowEditingCustomHtml = import.meta.env.UPTIME_KUMA_ALLOW_CUSTOM_HTML === "1";
callback({
ok: true,
config: await statusPage.toJSON(),
config,
});
} catch (error) {
callback({
@@ -167,6 +168,9 @@ module.exports.statusPageSocketHandler = (socket) => {
statusPage.show_certificate_expiry = config.showCertificateExpiry;
statusPage.modified_date = R.isoDateTime();
statusPage.google_analytics_tag_id = config.googleAnalyticsId;
if (process.env.UPTIME_KUMA_ALLOW_CUSTOM_HTML === "1") {
statusPage.custom_html = config.customHtml;
}
await R.store(statusPage);

View File

@@ -776,6 +776,9 @@
"wayToGetClickSendSMSToken": "You can get API Username and API Key from {0} .",
"Custom Monitor Type": "Custom Monitor Type",
"Google Analytics ID": "Google Analytics ID",
"Custom HTML": "Custom HTML",
"customHtmlEnvVarDisabled": "environment variable {allow_custom_html} must be set to inject html to the head",
"customHtmlEnvVarEnabled": "Because the environment variable {allow_custom_html} is set, arbitrary html can be injected into the head. Make sure to remove the environment variable after use",
"Edit Tag": "Edit Tag",
"Server Address": "Server Address",
"Learn More": "Learn More",

View File

@@ -211,6 +211,20 @@ export default {
@import "../assets/vars.scss";
.nav-link {
&:hover {
background-color: $primary;
color: #fff;
.dark & {
background-color: $primary;
color: #000;
}
&.active {
background-color: $highlight;
}
}
&.status-page {
background-color: rgba(255, 255, 255, 0.1);
}

View File

@@ -370,9 +370,10 @@
<label for="jsonPath" class="form-label">{{ $t("Json Query") }}</label>
<input id="jsonPath" v-model="monitor.jsonPath" type="text" class="form-control" required>
<!-- eslint-disable-next-line vue/no-v-html -->
<div class="form-text" v-html="$t('jsonQueryDescription')">
</div>
<i18n-t tag="div" class="form-text" keypath="jsonQueryDescription">
<a href="https://jsonata.org/">jsonata.org</a>
<a href="https://try.jsonata.org/">{{ $t('here') }}</a>
</i18n-t>
<br>
<label for="expectedValue" class="form-label">{{ $t("Expected Value") }}</label>

View File

@@ -104,6 +104,22 @@
<prism-editor v-model="config.customCSS" class="css-editor" :highlight="highlighter" line-numbers></prism-editor>
</div>
<!-- Custom HTML -->
<div class="my-3">
<div class="mb-1">{{ $t("Custom HTML") }}</div>
<prism-editor v-model="config.customHtml" class="css-editor" :highlight="highlighter" line-numbers :readonly="!config.allowEditingCustomHtml"></prism-editor>
<i18n-t v-if="config.allowEditingCustomHtml" tag="div" class="form-text" keypath="customHtmlEnvVarEnabled">
<template #allow_custom_html>
<code>UPTIME_KUMA_ALLOW_CUSTOM_HTML</code>
</template>
</i18n-t>
<i18n-t v-else tag="div" class="form-text" keypath="customHtmlEnvVarDisabled">
<template #allow_custom_html>
<code>UPTIME_KUMA_ALLOW_CUSTOM_HTML=1</code>
</template>
</i18n-t>
</div>
<div class="danger-zone">
<button class="btn btn-danger me-2" @click="deleteDialog">
<font-awesome-icon icon="trash" />