diff --git a/.github/workflows/stale-bot b/.github/workflows/stale-bot new file mode 100644 index 0000000..5dc5013 --- /dev/null +++ b/.github/workflows/stale-bot @@ -0,0 +1,22 @@ +name: 'Automatically close stale issues and PRs' +on: + schedule: + - cron: '0 0 * * *' +#Run once a day at midnight + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + stale-issue-message: 'We are clearing up our old issues and your ticket has been open for 6 months with no activity. Remove stale label or comment or this will be closed in 7 days.' + stale-pr-message: 'We are clearing up our old Pull Requests and yours has been open for 6 months with no activity. Remove stale label or comment or this will be closed in 7 days.' + close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.' + close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.' + days-before-stale: 180 + days-before-close: 7 + exempt-issue-labels: 'News,Medium,High,discussion,bug,doc,' + exempt-pr-labels: 'awaiting-approval,work-in-progress,enhancement,' + exempt-issue-assignees: 'louislam' + exempt-pr-assignees: 'louislam' diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index b618a2c..746334e 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -60,7 +60,7 @@ representative at an online or offline event. Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at -louis@uptimekuma.louislam.net. +uptime@kuma.pet. All complaints will be reviewed and investigated promptly and fairly. All community leaders are obligated to respect the privacy and security of the diff --git a/README.md b/README.md index 1dc492b..6caa1a8 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Try it! https://demo.uptime.kuma.pet -It is a 10 minutes live demo, all data will be deleted after that. The server is located at Tokyo, if you live far away from here, it may affact your experience. I suggest that you should install to try it. +It is a temporary live demo, all data will be deleted after 10 minutes. The server is located at Tokyo, so if you live far from there it may affect your experience. I suggest that you should install and try it out for the best demo experience. VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollective.com/uptime-kuma)! Thank you so much! @@ -25,7 +25,7 @@ VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollec * Monitoring uptime for HTTP(s) / TCP / Ping / DNS Record / Push. * Fancy, Reactive, Fast UI/UX. * Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [70+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications). -* 20 seconds interval. +* 20 second intervals. * [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages) * Simple Status Page * Ping Chart @@ -40,7 +40,7 @@ docker volume create uptime-kuma docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1 ``` -Browse to http://localhost:3001 after started. +Browse to http://localhost:3001 after starting. ### 💪🏻 Without Docker @@ -58,11 +58,11 @@ npm run setup node server/server.js # (Recommended) Option 2. Run in background using PM2 -# Install PM2 if you don't have: npm install pm2 -g +# Install PM2 if you don't have it: npm install pm2 -g pm2 start server/server.js --name uptime-kuma ``` -Browse to http://localhost:3001 after started. +Browse to http://localhost:3001 after starting. ### Advanced Installation @@ -124,7 +124,7 @@ You can discuss or ask for help in [Issues](https://github.com/louislam/uptime-k ### Subreddit My Reddit account: louislamlam -You can mention me if you ask question on Reddit. +You can mention me if you ask a question on Reddit. https://www.reddit.com/r/UptimeKuma/ ## Contribute diff --git a/docker/dockerfile b/docker/dockerfile index 9765574..e2a3725 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -31,14 +31,15 @@ WORKDIR / RUN apt update && \ apt --yes install curl file +COPY --from=build /app /app + +ARG VERSION=1.9.1 ARG GITHUB_TOKEN ARG TARGETARCH ARG PLATFORM=debian -ARG VERSION ARG FILE=$PLATFORM-$TARGETARCH-$VERSION.tar.gz ARG DIST=dist.tar.gz -COPY --from=build /app /app RUN chmod +x /app/extra/upload-github-release-asset.sh # Full Build diff --git a/kubernetes/README.md b/kubernetes/README.md deleted file mode 100644 index e85b0c4..0000000 --- a/kubernetes/README.md +++ /dev/null @@ -1,32 +0,0 @@ -# Uptime-Kuma K8s Deployment - -⚠ Warning: K8s deployment is provided by contributors. I have no experience with K8s and I can't fix error in the future. I only test Docker and Node.js. Use at your own risk. - -## How does it work? - -Kustomize is a tool which builds a complete deployment file for all config elements. -You can edit the files in the ```uptime-kuma``` folder except the ```kustomization.yml``` until you know what you're doing. -If you want to choose another namespace you can edit the ```kustomization.yml``` in the ```kubernetes```-Folder and change the ```namespace: uptime-kuma``` to something you like. - -It creates a certificate with the specified Issuer and creates the Ingress for the Uptime-Kuma ClusterIP-Service. - -## What do I have to edit? - -You have to edit the ```ingressroute.yml``` to your needs. -This ingressroute.yml is for the [nginx-ingress-controller](https://kubernetes.github.io/ingress-nginx/) in combination with the [cert-manager](https://cert-manager.io/). - -- Host -- Secrets and secret names -- (Cluster)Issuer (optional) -- The Version in the Deployment-File - - Update: - - Change to newer version and run the above commands, it will update the pods one after another - -## How To use - -- Install [kustomize](https://kubectl.docs.kubernetes.io/installation/kustomize/) -- Edit files mentioned above to your needs -- Run ```kustomize build > apply.yml``` -- Run ```kubectl apply -f apply.yml``` - -Now you should see some k8s magic and Uptime-Kuma should be available at the specified address. diff --git a/kubernetes/kustomization.yml b/kubernetes/kustomization.yml deleted file mode 100644 index 0daf10f..0000000 --- a/kubernetes/kustomization.yml +++ /dev/null @@ -1,10 +0,0 @@ -namespace: uptime-kuma -namePrefix: uptime-kuma- - -commonLabels: - app: uptime-kuma - -bases: - - uptime-kuma - - diff --git a/kubernetes/uptime-kuma/deployment.yml b/kubernetes/uptime-kuma/deployment.yml deleted file mode 100644 index b97ece2..0000000 --- a/kubernetes/uptime-kuma/deployment.yml +++ /dev/null @@ -1,45 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - labels: - component: uptime-kuma - name: deployment -spec: - selector: - matchLabels: - component: uptime-kuma - replicas: 1 - strategy: - type: Recreate - - template: - metadata: - labels: - component: uptime-kuma - spec: - containers: - - name: app - image: louislam/uptime-kuma:1 - ports: - - containerPort: 3001 - volumeMounts: - - mountPath: /app/data - name: storage - livenessProbe: - exec: - command: - - node - - extra/healthcheck.js - initialDelaySeconds: 180 - periodSeconds: 60 - timeoutSeconds: 30 - readinessProbe: - httpGet: - path: / - port: 3001 - scheme: HTTP - - volumes: - - name: storage - persistentVolumeClaim: - claimName: pvc diff --git a/kubernetes/uptime-kuma/ingressroute.yml b/kubernetes/uptime-kuma/ingressroute.yml deleted file mode 100644 index 71f7027..0000000 --- a/kubernetes/uptime-kuma/ingressroute.yml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - annotations: - kubernetes.io/ingress.class: nginx - cert-manager.io/cluster-issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/proxy-read-timeout: "3600" - nginx.ingress.kubernetes.io/proxy-send-timeout: "3600" - nginx.ingress.kubernetes.io/server-snippets: | - location / { - proxy_set_header Upgrade $http_upgrade; - proxy_http_version 1.1; - proxy_set_header X-Forwarded-Host $http_host; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-For $remote_addr; - proxy_set_header Host $host; - proxy_set_header Connection "upgrade"; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Upgrade $http_upgrade; - proxy_cache_bypass $http_upgrade; - } - name: ingress -spec: - tls: - - hosts: - - example.com - secretName: example-com-tls - rules: - - host: example.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: service - port: - number: 3001 diff --git a/kubernetes/uptime-kuma/kustomization.yml b/kubernetes/uptime-kuma/kustomization.yml deleted file mode 100644 index 638a2ab..0000000 --- a/kubernetes/uptime-kuma/kustomization.yml +++ /dev/null @@ -1,5 +0,0 @@ -resources: - - deployment.yml - - service.yml - - ingressroute.yml - - pvc.yml \ No newline at end of file diff --git a/kubernetes/uptime-kuma/pvc.yml b/kubernetes/uptime-kuma/pvc.yml deleted file mode 100644 index eda3b8b..0000000 --- a/kubernetes/uptime-kuma/pvc.yml +++ /dev/null @@ -1,10 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 4Gi diff --git a/kubernetes/uptime-kuma/service.yml b/kubernetes/uptime-kuma/service.yml deleted file mode 100644 index 5fa812e..0000000 --- a/kubernetes/uptime-kuma/service.yml +++ /dev/null @@ -1,13 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: service -spec: - selector: - component: uptime-kuma - type: ClusterIP - ports: - - name: http - port: 3001 - targetPort: 3001 - protocol: TCP diff --git a/package.json b/package.json index 7353cf1..4c79982 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.8.0", + "version": "1.9.1", "license": "MIT", "repository": { "type": "git", @@ -30,13 +30,13 @@ "build-docker": "npm run build-docker-debian && npm run build-docker-alpine", "build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push", "build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push", - "build-docker-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:1.8.0-alpine --target release . --push", - "build-docker-debian": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.8.0 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.8.0-debian --target release . --push", + "build-docker-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:1.9.1-alpine --target release . --push", + "build-docker-debian": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.9.1 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.9.1-debian --target release . --push", "build-docker-nightly": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push", - "build-docker-nightly-alpine": "docker buildx build -f dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push", + "build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push", "build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain", - "upload-artifacts": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain", - "setup": "git checkout 1.8.0 && npm ci --production && npm run download-dist", + "upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain", + "setup": "git checkout 1.9.1 && npm ci --production && npm run download-dist", "download-dist": "node extra/download-dist.js", "update-version": "node extra/update-version.js", "mark-as-nightly": "node extra/mark-as-nightly.js", diff --git a/server/database.js b/server/database.js index 297df65..aa36384 100644 --- a/server/database.js +++ b/server/database.js @@ -53,7 +53,7 @@ class Database { } /** - * The finally version should be 10 after merged tag feature + * The final version should be 10 after merged tag feature * @deprecated Use patchList for any new feature */ static latestVersion = 10; @@ -131,7 +131,7 @@ class Database { console.info("Latest database version: " + this.latestVersion); if (version === this.latestVersion) { - console.info("Database no need to patch"); + console.info("Database patch not needed"); } else if (version > this.latestVersion) { console.info("Warning: Database version is newer than expected"); } else { @@ -152,8 +152,8 @@ class Database { await Database.close(); console.error(ex); - console.error("Start Uptime-Kuma failed due to patch db failed"); - console.error("Please submit the bug report if you still encounter the problem after restart: https://github.com/louislam/uptime-kuma/issues"); + console.error("Start Uptime-Kuma failed due to issue patching the database"); + console.error("Please submit a bug report if you still encounter the problem after restart: https://github.com/louislam/uptime-kuma/issues"); this.restore(); process.exit(1); @@ -191,7 +191,7 @@ class Database { await Database.close(); console.error(ex); - console.error("Start Uptime-Kuma failed due to patch db failed"); + console.error("Start Uptime-Kuma failed due to issue patching the database"); console.error("Please submit the bug report if you still encounter the problem after restart: https://github.com/louislam/uptime-kuma/issues"); this.restore(); @@ -232,7 +232,7 @@ class Database { this.patched = true; await this.importSQLFile("./db/" + sqlFilename); databasePatchedFiles[sqlFilename] = true; - console.log(sqlFilename + " is patched successfully"); + console.log(sqlFilename + " was patched successfully"); } else { debug(sqlFilename + " is already patched, skip"); @@ -287,7 +287,7 @@ class Database { }; process.addListener("unhandledRejection", listener); - console.log("Closing DB"); + console.log("Closing the database"); while (true) { Database.noReject = true; @@ -297,7 +297,7 @@ class Database { if (Database.noReject) { break; } else { - console.log("Waiting to close the db"); + console.log("Waiting to close the database"); } } console.log("SQLite closed"); @@ -312,7 +312,7 @@ class Database { */ static backup(version) { if (! this.backupPath) { - console.info("Backup the db"); + console.info("Backing up the database"); this.backupPath = this.dataDir + "kuma.db.bak" + version; fs.copyFileSync(Database.path, this.backupPath); @@ -335,7 +335,7 @@ class Database { */ static restore() { if (this.backupPath) { - console.error("Patch db failed!!! Restoring the backup"); + console.error("Patching the database failed!!! Restoring the backup"); const shmPath = Database.path + "-shm"; const walPath = Database.path + "-wal"; @@ -354,7 +354,7 @@ class Database { fs.unlinkSync(walPath); } } catch (e) { - console.log("Restore failed, you may need to restore the backup manually"); + console.log("Restore failed; you may need to restore the backup manually"); process.exit(1); } diff --git a/server/model/monitor.js b/server/model/monitor.js index 3640c73..fb73629 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -7,7 +7,7 @@ dayjs.extend(timezone); const axios = require("axios"); const { Prometheus } = require("../prometheus"); const { debug, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util"); -const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom } = require("../util-server"); +const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); const { Notification } = require("../notification"); @@ -272,6 +272,46 @@ class Monitor extends BeanModel { return; } + } else if (this.type === "steam") { + const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/"; + const steamAPIKey = await setting("steamAPIKey"); + const filter = `addr\\${this.hostname}:${this.port}`; + + if (!steamAPIKey) { + throw new Error("Steam API Key not found"); + } + + let res = await axios.get(steamApiUrl, { + timeout: this.interval * 1000 * 0.8, + headers: { + "Accept": "*/*", + "User-Agent": "Uptime-Kuma/" + version, + }, + httpsAgent: new https.Agent({ + maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) + rejectUnauthorized: ! this.getIgnoreTls(), + }), + maxRedirects: this.maxredirects, + validateStatus: (status) => { + return checkStatusCode(status, this.getAcceptedStatuscodes()); + }, + params: { + filter: filter, + key: steamAPIKey, + } + }); + + if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) { + bean.status = UP; + bean.msg = res.data.response.servers[0].name; + + try { + bean.ping = await ping(this.hostname); + } catch (_) { } + } else { + throw new Error("Server not found on Steam"); + } + } else { bean.msg = "Unknown Monitor Type"; bean.status = PENDING; diff --git a/server/server.js b/server/server.js index 6496699..d5f2d37 100644 --- a/server/server.js +++ b/server/server.js @@ -77,12 +77,13 @@ const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || args.p // SSL 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 disableFrameSameOrigin = !!process.env.UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN || args["disable-frame-sameorigin"] || false; // 2FA / notp verification defaults const twofa_verification_opts = { "window": 1, "time": 30 -} +}; /** * Run unit test after the server is ready @@ -119,6 +120,15 @@ const { statusPageSocketHandler } = require("./socket-handlers/status-page-socke app.use(express.json()); +// Global Middleware +app.use(function (req, res, next) { + if (!disableFrameSameOrigin) { + res.setHeader("X-Frame-Options", "SAMEORIGIN"); + } + res.removeHeader("X-Powered-By"); + next(); +}); + /** * Total WebSocket client connected to server currently, no actual use * @type {number} @@ -192,7 +202,7 @@ exports.entryPage = "dashboard"; const apiRouter = require("./routers/api-router"); app.use(apiRouter); - // Universal Route Handler, must be at the end of all express route. + // Universal Route Handler, must be at the end of all express routes. app.get("*", async (_request, response) => { if (_request.originalUrl.startsWith("/upload/")) { response.status(404).send("File not found."); @@ -321,7 +331,7 @@ exports.entryPage = "dashboard"; ]); if (user.twofa_status == 0) { - let newSecret = await genSecret(); + let newSecret = genSecret(); let encodedSecret = base32.encode(newSecret); // Google authenticator doesn't like equal signs @@ -449,7 +459,7 @@ exports.entryPage = "dashboard"; socket.on("setup", async (username, password, callback) => { try { if ((await R.count("user")) !== 0) { - throw new Error("Uptime Kuma has been setup. If you want to setup again, please delete the database."); + throw new Error("Uptime Kuma has been initialized. If you want to run setup again, please delete the database."); } let user = R.dispense("user"); @@ -1339,7 +1349,7 @@ async function initDatabase() { fs.copyFileSync(Database.templatePath, Database.path); } - console.log("Connecting to Database"); + console.log("Connecting to the Database"); await Database.connect(); console.log("Connected"); @@ -1439,7 +1449,7 @@ async function shutdownFunction(signal) { } function finalFunction() { - console.log("Graceful shutdown successfully!"); + console.log("Graceful shutdown successful!"); } gracefulShutdown(server, { diff --git a/src/components/notifications/PromoSMS.vue b/src/components/notifications/PromoSMS.vue index 06dea0b..61e61a9 100644 --- a/src/components/notifications/PromoSMS.vue +++ b/src/components/notifications/PromoSMS.vue @@ -10,8 +10,8 @@