From 8f7885e58a5edca69e4ff2e3715232474dc5bcb3 Mon Sep 17 00:00:00 2001 From: Nelson Chan Date: Thu, 5 Aug 2021 19:04:38 +0800 Subject: [PATCH] Feat: Implement MaxRedirects & StatusCodes --- db/patch6.sql | 74 +++++++++++++++++++++++++++++++++++++++ package-lock.json | 7 +++- package.json | 1 + server/database.js | 2 +- server/model/monitor.js | 12 ++++++- server/server.js | 1 + server/util-server.js | 35 ++++++++++++++++-- src/pages/EditMonitor.vue | 71 ++++++++++++++++++++++++++++++------- 8 files changed, 184 insertions(+), 19 deletions(-) create mode 100644 db/patch6.sql diff --git a/db/patch6.sql b/db/patch6.sql new file mode 100644 index 000000000..4f539a271 --- /dev/null +++ b/db/patch6.sql @@ -0,0 +1,74 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +PRAGMA foreign_keys = off; + +BEGIN TRANSACTION; + +create table monitor_dg_tmp ( + id INTEGER not null primary key autoincrement, + name VARCHAR(150), + active BOOLEAN default 1 not null, + user_id INTEGER references user on update cascade on delete + set + null, + interval INTEGER default 20 not null, + url TEXT, + type VARCHAR(20), + weight INTEGER default 2000, + hostname VARCHAR(255), + port INTEGER, + created_date DATETIME default (DATETIME('now')) not null, + keyword VARCHAR(255), + maxretries INTEGER NOT NULL DEFAULT 0, + ignore_tls BOOLEAN default 0 not null, + upside_down BOOLEAN default 0 not null, + maxredirects INTEGER default 10 not null, + accepted_statuscodes_json TEXT default '["200-299"]' not null +); + +insert into + monitor_dg_tmp( + id, + name, + active, + user_id, + interval, + url, + type, + weight, + hostname, + port, + created_date, + keyword, + maxretries, + ignore_tls, + upside_down + ) +select + id, + name, + active, + user_id, + interval, + url, + type, + weight, + hostname, + port, + created_date, + keyword, + maxretries, + ignore_tls, + upside_down +from + monitor; + +drop table monitor; + +alter table + monitor_dg_tmp rename to monitor; + +create index user_id on monitor (user_id); + +COMMIT; + +PRAGMA foreign_keys = on; diff --git a/package-lock.json b/package-lock.json index c62dc8eed..3053e0337 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "uptime-kuma", - "version": "1.0.7", + "version": "1.0.10", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -7021,6 +7021,11 @@ } } }, + "vue-multiselect": { + "version": "3.0.0-alpha.2", + "resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-3.0.0-alpha.2.tgz", + "integrity": "sha512-Xp9fGJECns45v+v8jXbCIsAkCybYkEg0lNwr7Z6HDUSMyx2TEIK2giipPE+qXiShEc1Ipn+ZtttH2iq9hwXP4Q==" + }, "vue-router": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.10.tgz", diff --git a/package.json b/package.json index def27f798..2faac07c3 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "v-pagination-3": "^0.1.6", "vue": "^3.0.5", "vue-confirm-dialog": "^1.0.2", + "vue-multiselect": "^3.0.0-alpha.2", "vue-router": "^4.0.10", "vue-toastification": "^2.0.0-rc.1" }, diff --git a/server/database.js b/server/database.js index 4accbc32e..233d54f7c 100644 --- a/server/database.js +++ b/server/database.js @@ -9,7 +9,7 @@ class Database { static templatePath = "./db/kuma.db" static path = "./data/kuma.db"; - static latestVersion = 5; + static latestVersion = 6; static noReject = true; static async patch() { diff --git a/server/model/monitor.js b/server/model/monitor.js index 49fcfb303..e452e686b 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 } = require("../../src/util"); -const { tcping, ping, checkCertificate } = require("../util-server"); +const { tcping, ping, checkCertificate, checkStatusCode } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); const { Notification } = require("../notification") @@ -45,6 +45,8 @@ class Monitor extends BeanModel { keyword: this.keyword, ignoreTls: this.getIgnoreTls(), upsideDown: this.isUpsideDown(), + maxredirects: this.maxredirects, + accepted_statuscodes: this.getAcceptedStatuscodes(), notificationIDList, }; } @@ -65,6 +67,10 @@ class Monitor extends BeanModel { return Boolean(this.upsideDown); } + getAcceptedStatuscodes() { + return JSON.parse(this.accepted_statuscodes_json); + } + start(io) { let previousBeat = null; let retries = 0; @@ -111,6 +117,10 @@ class Monitor extends BeanModel { maxCachedSessions: 0, rejectUnauthorized: ! this.getIgnoreTls(), }), + maxRedirects: this.maxredirects, + validateStatus: (status) => { + return checkStatusCode(status, this.getAcceptedStatuscodes()); + }, }); bean.msg = `${res.status} - ${res.statusText}` bean.ping = dayjs().valueOf() - startTime; diff --git a/server/server.js b/server/server.js index daaf9555a..688966c96 100644 --- a/server/server.js +++ b/server/server.js @@ -274,6 +274,7 @@ let indexHTML = fs.readFileSync("./dist/index.html").toString(); bean.keyword = monitor.keyword; bean.ignoreTls = monitor.ignoreTls; bean.upsideDown = monitor.upsideDown; + bean.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes); await R.store(bean) diff --git a/server/util-server.js b/server/util-server.js index 1411a3f69..d9bd54102 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -9,7 +9,7 @@ exports.tcping = function (hostname, port) { address: hostname, port: port, attempts: 1, - }, function(err, data) { + }, function (err, data) { if (err) { reject(err); @@ -28,7 +28,7 @@ exports.ping = function (hostname) { return new Promise((resolve, reject) => { const ping = new Ping(hostname); - ping.send(function(err, ms) { + ping.send(function (err, ms) { if (err) { reject(err) } else if (ms === null) { @@ -58,7 +58,7 @@ exports.setSetting = async function (key, value) { let bean = await R.findOne("setting", " `key` = ? ", [ key, ]) - if (! bean) { + if (!bean) { bean = R.dispense("setting") bean.key = key; } @@ -158,3 +158,32 @@ exports.checkCertificate = function (res) { fingerprint, }; } + +// Check if the provided status code is within the accepted ranges +// Param: status - the status code to check +// Param: accepted_codes - an array of accepted status codes +// Return: true if the status code is within the accepted ranges, false otherwise +// Will throw an error if the provided status code is not a valid range string or code string + +exports.checkStatusCode = function (status, accepted_codes) { + if (accepted_codes == null || accepted_codes.length === 0) { + return false; + } + + for (const code_range of accepted_codes) { + const code_range_split = code_range.split("-").map(string => parseInt(string)); + if (code_range_split.length === 1) { + if (status === code_range_split[0]) { + return true; + } + } else if (code_range_split.length === 2) { + if (status >= code_range_split[0] && status <= code_range_split[1]) { + return true; + } + } else { + throw new Error("Invalid status code range"); + } + } + + return false; +} diff --git a/src/pages/EditMonitor.vue b/src/pages/EditMonitor.vue index 6754173a0..a54016b41 100644 --- a/src/pages/EditMonitor.vue +++ b/src/pages/EditMonitor.vue @@ -1,5 +1,5 @@