mirror of
https://github.com/louislam/uptime-kuma.git
synced 2025-06-07 13:32:35 +02:00
Merge remote-tracking branch 'bertyhell/feature/monitor-checks' into feature/monitor-checks
This commit is contained in:
commit
5943c76dfb
9 changed files with 387 additions and 102 deletions
|
@ -8,7 +8,7 @@ create table monitor_checks
|
||||||
constraint monitor_checks_pk
|
constraint monitor_checks_pk
|
||||||
primary key autoincrement,
|
primary key autoincrement,
|
||||||
type VARCHAR(50) not null,
|
type VARCHAR(50) not null,
|
||||||
value TEXTt,
|
value TEXT,
|
||||||
monitor_id INTEGER not null
|
monitor_id INTEGER not null
|
||||||
constraint monitor_checks_monitor_id_fk
|
constraint monitor_checks_monitor_id_fk
|
||||||
references monitor
|
references monitor
|
||||||
|
|
114
package-lock.json
generated
114
package-lock.json
generated
|
@ -1,8 +1,10 @@
|
||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
|
<<<<<<< HEAD
|
||||||
|
=======
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
|
@ -7946,6 +7948,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
>>>>>>> master
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@babel/code-frame": {
|
"@babel/code-frame": {
|
||||||
"version": "7.12.11",
|
"version": "7.12.11",
|
||||||
|
@ -8991,7 +8994,6 @@
|
||||||
"version": "6.12.6",
|
"version": "6.12.6",
|
||||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||||
"devOptional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"fast-deep-equal": "^3.1.1",
|
"fast-deep-equal": "^3.1.1",
|
||||||
"fast-json-stable-stringify": "^2.0.0",
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
@ -10294,8 +10296,7 @@
|
||||||
"extend": {
|
"extend": {
|
||||||
"version": "3.0.2",
|
"version": "3.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"extsprintf": {
|
"extsprintf": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
|
@ -10306,8 +10307,7 @@
|
||||||
"fast-deep-equal": {
|
"fast-deep-equal": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"fast-glob": {
|
"fast-glob": {
|
||||||
"version": "3.2.7",
|
"version": "3.2.7",
|
||||||
|
@ -10325,8 +10325,7 @@
|
||||||
"fast-json-stable-stringify": {
|
"fast-json-stable-stringify": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
|
||||||
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
|
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"fast-levenshtein": {
|
"fast-levenshtein": {
|
||||||
"version": "2.0.6",
|
"version": "2.0.6",
|
||||||
|
@ -10973,8 +10972,7 @@
|
||||||
"is-typedarray": {
|
"is-typedarray": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||||
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=",
|
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"is-unicode-supported": {
|
"is-unicode-supported": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
|
@ -10990,8 +10988,7 @@
|
||||||
"isexe": {
|
"isexe": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=",
|
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"isstream": {
|
"isstream": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -11042,8 +11039,7 @@
|
||||||
"json-schema-traverse": {
|
"json-schema-traverse": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"json-stable-stringify-without-jsonify": {
|
"json-stable-stringify-without-jsonify": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -11489,7 +11485,8 @@
|
||||||
"nanoid": {
|
"nanoid": {
|
||||||
"version": "3.1.25",
|
"version": "3.1.25",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
|
||||||
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q=="
|
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"natural-compare": {
|
"natural-compare": {
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
|
@ -12314,8 +12311,7 @@
|
||||||
"punycode": {
|
"punycode": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||||
"devOptional": true
|
|
||||||
},
|
},
|
||||||
"qrcode": {
|
"qrcode": {
|
||||||
"version": "1.4.4",
|
"version": "1.4.4",
|
||||||
|
@ -12917,6 +12913,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||||
},
|
},
|
||||||
|
<<<<<<< HEAD
|
||||||
"string_decoder": {
|
"string_decoder": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
@ -12924,6 +12921,13 @@
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "~5.1.0"
|
"safe-buffer": "~5.1.0"
|
||||||
}
|
}
|
||||||
|
=======
|
||||||
|
"string-hash": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz",
|
||||||
|
"integrity": "sha1-6Kr8CsGFW0Zmkp7X3RJ1311sgRs=",
|
||||||
|
"dev": true
|
||||||
|
>>>>>>> monitor-checks
|
||||||
},
|
},
|
||||||
"string-width": {
|
"string-width": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -12950,6 +12954,14 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"strip-ansi": {
|
"strip-ansi": {
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||||
|
@ -13556,7 +13568,6 @@
|
||||||
"version": "4.4.1",
|
"version": "4.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
|
||||||
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
|
||||||
"devOptional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"punycode": "^2.1.0"
|
"punycode": "^2.1.0"
|
||||||
}
|
}
|
||||||
|
@ -13677,12 +13688,68 @@
|
||||||
"resolved": "https://registry.npmjs.org/vue-chart-3/-/vue-chart-3-0.5.8.tgz",
|
"resolved": "https://registry.npmjs.org/vue-chart-3/-/vue-chart-3-0.5.8.tgz",
|
||||||
"integrity": "sha512-VJEBTdMgWOaYqekXtz4LVBIeYyIx3qDlQnFyY4Ao1GwizokYZBycCeRN3oKDcYbbZi5yxYqTy6+Tm+m+SOPUPA==",
|
"integrity": "sha512-VJEBTdMgWOaYqekXtz4LVBIeYyIx3qDlQnFyY4Ao1GwizokYZBycCeRN3oKDcYbbZi5yxYqTy6+Tm+m+SOPUPA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@vue/runtime-core": "latest",
|
"@vue/runtime-core": "^3.2.11",
|
||||||
"@vue/runtime-dom": "latest",
|
"@vue/runtime-dom": "^3.2.11",
|
||||||
"csstype": "latest",
|
"csstype": "^3.0.9",
|
||||||
"lodash": "latest",
|
"lodash": "^4.17.21",
|
||||||
"nanoid": "latest",
|
"nanoid": "^3.1.25",
|
||||||
"vue-demi": "^0.10.1"
|
"vue-demi": "^0.10.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/reactivity": {
|
||||||
|
"version": "3.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.2.11.tgz",
|
||||||
|
"integrity": "sha512-hEQstxPQbgGZq5qApzrvbDmRdK1KP96O/j4XrwT8fVkT1ytkFs4fH2xNEh9QKwXfybbQkLs77W7OfXCv5o6qbA==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/shared": "3.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@vue/runtime-core": {
|
||||||
|
"version": "3.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.2.11.tgz",
|
||||||
|
"integrity": "sha512-horlxjWwSvModC87WdsWswzzHE5IexmKkQA65S5vFgP5hLUBW+HRyScDeuB/RRcFmqnf+ozacNCfap0kqcpODw==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/reactivity": "3.2.11",
|
||||||
|
"@vue/shared": "3.2.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@vue/runtime-dom": {
|
||||||
|
"version": "3.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.2.11.tgz",
|
||||||
|
"integrity": "sha512-cOK1g0INdiCbds2xrrJKrrN+pDHuLz6esUs/crdEiupDuX7IeiMbdqrAQCkYHp5P1KLWcbGlkmwfVD7HQGii0Q==",
|
||||||
|
"requires": {
|
||||||
|
"@vue/runtime-core": "3.2.11",
|
||||||
|
"@vue/shared": "3.2.11",
|
||||||
|
"csstype": "^2.6.8"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"csstype": {
|
||||||
|
"version": "2.6.18",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.18.tgz",
|
||||||
|
"integrity": "sha512-RSU6Hyeg14am3Ah4VZEmeX8H7kLwEEirXe6aU2IPfKNvhXwTflK5HQRDNI0ypQXoqmm+QPyG2IaPuQE5zMwSIQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@vue/shared": {
|
||||||
|
"version": "3.2.11",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.2.11.tgz",
|
||||||
|
"integrity": "sha512-ovfXAsSsCvV9JVceWjkqC/7OF5HbgLOtCWjCIosmPGG8lxbPuavhIxRH1dTx4Dg9xLgRTNLvI3pVxG4ItQZekg=="
|
||||||
|
},
|
||||||
|
"csstype": {
|
||||||
|
"version": "3.0.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.9.tgz",
|
||||||
|
"integrity": "sha512-rpw6JPxK6Rfg1zLOYCSwle2GFOOsnjmDYDaBwEcwoOg4qlsIVCN789VkBZDJAGi4T07gI4YSutR43t9Zz4Lzuw=="
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.21",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||||
|
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||||
|
},
|
||||||
|
"nanoid": {
|
||||||
|
"version": "3.1.25",
|
||||||
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz",
|
||||||
|
"integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q=="
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"vue-confirm-dialog": {
|
"vue-confirm-dialog": {
|
||||||
|
@ -13804,7 +13871,6 @@
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
|
||||||
"devOptional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
"form-data": "^4.0.0",
|
"form-data": "^4.0.0",
|
||||||
"http-graceful-shutdown": "^3.1.4",
|
"http-graceful-shutdown": "^3.1.4",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
|
"lodash.get": "^4.4.2",
|
||||||
"nodemailer": "^6.6.5",
|
"nodemailer": "^6.6.5",
|
||||||
"notp": "^2.0.3",
|
"notp": "^2.0.3",
|
||||||
"password-hash": "^1.2.2",
|
"password-hash": "^1.2.2",
|
||||||
|
|
|
@ -7,10 +7,11 @@ dayjs.extend(timezone);
|
||||||
const axios = require("axios");
|
const axios = require("axios");
|
||||||
const { Prometheus } = require("../prometheus");
|
const { Prometheus } = require("../prometheus");
|
||||||
const { debug, UP, DOWN, PENDING, flipStatus, TimeLogger } = require("../../src/util");
|
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, getTotalClientInRoom } = require("../util-server");
|
||||||
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 validateMonitorChecks = require("./validate-monitor-checks");
|
||||||
const version = require("../../package.json").version;
|
const version = require("../../package.json").version;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,15 +62,14 @@ class Monitor extends BeanModel {
|
||||||
type: this.type,
|
type: this.type,
|
||||||
interval: this.interval,
|
interval: this.interval,
|
||||||
retryInterval: this.retryInterval,
|
retryInterval: this.retryInterval,
|
||||||
keyword: this.keyword,
|
|
||||||
ignoreTls: this.getIgnoreTls(),
|
ignoreTls: this.getIgnoreTls(),
|
||||||
upsideDown: this.isUpsideDown(),
|
upsideDown: this.isUpsideDown(),
|
||||||
maxredirects: this.maxredirects,
|
maxredirects: this.maxredirects,
|
||||||
accepted_statuscodes: this.getAcceptedStatuscodes(),
|
|
||||||
dns_resolve_type: this.dns_resolve_type,
|
dns_resolve_type: this.dns_resolve_type,
|
||||||
dns_resolve_server: this.dns_resolve_server,
|
dns_resolve_server: this.dns_resolve_server,
|
||||||
dns_last_result: this.dns_last_result,
|
dns_last_result: this.dns_last_result,
|
||||||
notificationIDList,
|
notificationIDList,
|
||||||
|
checks: this.checks,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -90,10 +90,6 @@ class Monitor extends BeanModel {
|
||||||
return Boolean(this.upsideDown);
|
return Boolean(this.upsideDown);
|
||||||
}
|
}
|
||||||
|
|
||||||
getAcceptedStatuscodes() {
|
|
||||||
return JSON.parse(this.accepted_statuscodes_json);
|
|
||||||
}
|
|
||||||
|
|
||||||
start(io) {
|
start(io) {
|
||||||
let previousBeat = null;
|
let previousBeat = null;
|
||||||
let retries = 0;
|
let retries = 0;
|
||||||
|
@ -131,7 +127,7 @@ class Monitor extends BeanModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.type === "http" || this.type === "keyword") {
|
if (this.type === "http") {
|
||||||
// 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();
|
||||||
|
|
||||||
|
@ -146,9 +142,6 @@ class Monitor extends BeanModel {
|
||||||
rejectUnauthorized: ! this.getIgnoreTls(),
|
rejectUnauthorized: ! this.getIgnoreTls(),
|
||||||
}),
|
}),
|
||||||
maxRedirects: this.maxredirects,
|
maxRedirects: this.maxredirects,
|
||||||
validateStatus: (status) => {
|
|
||||||
return checkStatusCode(status, this.getAcceptedStatuscodes());
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
bean.msg = `${res.status} - ${res.statusText}`;
|
bean.msg = `${res.status} - ${res.statusText}`;
|
||||||
bean.ping = dayjs().valueOf() - startTime;
|
bean.ping = dayjs().valueOf() - startTime;
|
||||||
|
@ -167,6 +160,8 @@ class Monitor extends BeanModel {
|
||||||
|
|
||||||
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
|
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
|
||||||
|
|
||||||
|
|
||||||
|
validateMonitorChecks(res, this.checks, bean);
|
||||||
if (this.type === "http") {
|
if (this.type === "http") {
|
||||||
bean.status = UP;
|
bean.status = UP;
|
||||||
} else {
|
} else {
|
||||||
|
|
102
server/model/validate-monitor-checks.js
Normal file
102
server/model/validate-monitor-checks.js
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
const { checkStatusCode } = require("../util-server");
|
||||||
|
const { UP } = require("../../src/util");
|
||||||
|
const get = require("lodash.get");
|
||||||
|
|
||||||
|
function validateMonitorChecks(res, checks, bean) {
|
||||||
|
const responseText = typeof data === "string" ? res.data : JSON.stringify(res.data);
|
||||||
|
let checkObj;
|
||||||
|
|
||||||
|
this.checks.forEach(check => {
|
||||||
|
switch (check.type) {
|
||||||
|
case "HTTP_STATUS_CODE_SHOULD_EQUAL":
|
||||||
|
if (checkStatusCode(res.status, check.value)) {
|
||||||
|
bean.msg += `, status matches '${check.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(bean.msg + ", but status code dit not match " + check.value)
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SHOULD_CONTAIN_TEXT":
|
||||||
|
if (responseText.includes(check.value)) {
|
||||||
|
bean.msg += `, response contains '${check.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(bean.msg + ", but response does not contain '" + check.value + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SHOULD_NOT_CONTAIN_TEXT":
|
||||||
|
if (!responseText.includes(check.value)) {
|
||||||
|
bean.msg += `, response does not contain '${check.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(bean.msg + ", but response does contain '" + check.value + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SHOULD_MATCH_REGEX":
|
||||||
|
if (responseText.test(new RegExp(check.value))) {
|
||||||
|
bean.msg += `, regex '${check.value}' matches`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(bean.msg + ", but response does not match regex: '" + check.value + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SHOULD_NOT_MATCH_REGEX":
|
||||||
|
if (!responseText.test(new RegExp(check.value))) {
|
||||||
|
bean.msg += `, regex '${check.value}' does not matches`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(bean.msg + ", but response does match regex: '" + check.value + "'");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SELECTOR_SHOULD_EQUAL":
|
||||||
|
checkObj = JSON.parse(check.value);
|
||||||
|
if (get(res, checkObj.selector) === checkObj.value) {
|
||||||
|
bean.msg += `, response selector equals '${checkObj.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(`${bean.msg}, but response selector '${checkObj.selector}' does not equal '${checkObj.value}'`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SELECTOR_SHOULD_NOT_EQUAL":
|
||||||
|
checkObj = JSON.parse(check.value);
|
||||||
|
if (get(res, checkObj.selector) !== checkObj.value) {
|
||||||
|
bean.msg += `, response selector does not equal '${checkObj.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(`${bean.msg}, but response selector '${checkObj.selector}' does equal '${checkObj.value}'`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SELECTOR_SHOULD_MATCH_REGEX":
|
||||||
|
checkObj = JSON.parse(check.value);
|
||||||
|
if (get(res, checkObj.selector).test(new RegExp(checkObj.value))) {
|
||||||
|
bean.msg += `, response selector matches regex '${checkObj.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(`${bean.msg}, but response selector '${checkObj.selector}' does not match regex '${checkObj.value}'`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "RESPONSE_SELECTOR_SHOULD_NOT_MATCH_REGEX":
|
||||||
|
checkObj = JSON.parse(check.value);
|
||||||
|
if (!get(res, checkObj.selector).test(new RegExp(checkObj.value))) {
|
||||||
|
bean.msg += `, response selector does not match regex '${checkObj.value}'`
|
||||||
|
bean.status = UP;
|
||||||
|
} else {
|
||||||
|
throw new Error(`${bean.msg}, but response selector '${checkObj.selector}' does match regex '${checkObj.value}'`);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new Error(`${bean.msg}, encountered unknown monitor_check.type`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = validateMonitorChecks;
|
|
@ -6,7 +6,7 @@ if (! process.env.NODE_ENV) {
|
||||||
|
|
||||||
console.log("Node Env: " + process.env.NODE_ENV);
|
console.log("Node Env: " + process.env.NODE_ENV);
|
||||||
|
|
||||||
const { sleep, debug, TimeLogger, getRandomInt } = require("../src/util");
|
const { sleep, debug, getRandomInt } = require("../src/util");
|
||||||
|
|
||||||
console.log("Importing Node libraries");
|
console.log("Importing Node libraries");
|
||||||
const fs = require("fs");
|
const fs = require("fs");
|
||||||
|
@ -459,8 +459,8 @@ exports.entryPage = "dashboard";
|
||||||
let notificationIDList = monitor.notificationIDList;
|
let notificationIDList = monitor.notificationIDList;
|
||||||
delete monitor.notificationIDList;
|
delete monitor.notificationIDList;
|
||||||
|
|
||||||
monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
|
monitor.checks_json = JSON.stringify(monitor.checks);
|
||||||
delete monitor.accepted_statuscodes;
|
delete monitor.checks;
|
||||||
|
|
||||||
bean.import(monitor);
|
bean.import(monitor);
|
||||||
bean.user_id = socket.userID;
|
bean.user_id = socket.userID;
|
||||||
|
@ -504,13 +504,12 @@ exports.entryPage = "dashboard";
|
||||||
bean.hostname = monitor.hostname;
|
bean.hostname = monitor.hostname;
|
||||||
bean.maxretries = monitor.maxretries;
|
bean.maxretries = monitor.maxretries;
|
||||||
bean.port = monitor.port;
|
bean.port = monitor.port;
|
||||||
bean.keyword = monitor.keyword;
|
|
||||||
bean.ignoreTls = monitor.ignoreTls;
|
bean.ignoreTls = monitor.ignoreTls;
|
||||||
bean.upsideDown = monitor.upsideDown;
|
bean.upsideDown = monitor.upsideDown;
|
||||||
bean.maxredirects = monitor.maxredirects;
|
bean.maxredirects = monitor.maxredirects;
|
||||||
bean.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
|
|
||||||
bean.dns_resolve_type = monitor.dns_resolve_type;
|
bean.dns_resolve_type = monitor.dns_resolve_type;
|
||||||
bean.dns_resolve_server = monitor.dns_resolve_server;
|
bean.dns_resolve_server = monitor.dns_resolve_server;
|
||||||
|
bean.checks_json = JSON.stringify(monitor.checks);
|
||||||
|
|
||||||
await R.store(bean);
|
await R.store(bean);
|
||||||
|
|
||||||
|
@ -1015,22 +1014,19 @@ exports.entryPage = "dashboard";
|
||||||
// --- End ---
|
// --- End ---
|
||||||
|
|
||||||
let monitor = {
|
let monitor = {
|
||||||
// Define the new variable from earlier here
|
name: monitorList[i].name,
|
||||||
name: monitorListData[i].name,
|
type: monitorList[i].type,
|
||||||
type: monitorListData[i].type,
|
url: monitorList[i].url,
|
||||||
url: monitorListData[i].url,
|
interval: monitorList[i].interval,
|
||||||
interval: monitorListData[i].interval,
|
hostname: monitorList[i].hostname,
|
||||||
retryInterval: retryInterval,
|
maxretries: monitorList[i].maxretries,
|
||||||
hostname: monitorListData[i].hostname,
|
port: monitorList[i].port,
|
||||||
maxretries: monitorListData[i].maxretries,
|
ignoreTls: monitorList[i].ignoreTls,
|
||||||
port: monitorListData[i].port,
|
upsideDown: monitorList[i].upsideDown,
|
||||||
keyword: monitorListData[i].keyword,
|
maxredirects: monitorList[i].maxredirects,
|
||||||
ignoreTls: monitorListData[i].ignoreTls,
|
checks: monitorList[i].checks,
|
||||||
upsideDown: monitorListData[i].upsideDown,
|
dns_resolve_type: monitorList[i].dns_resolve_type,
|
||||||
maxredirects: monitorListData[i].maxredirects,
|
dns_resolve_server: monitorList[i].dns_resolve_server,
|
||||||
accepted_statuscodes: monitorListData[i].accepted_statuscodes,
|
|
||||||
dns_resolve_type: monitorListData[i].dns_resolve_type,
|
|
||||||
dns_resolve_server: monitorListData[i].dns_resolve_server,
|
|
||||||
notificationIDList: {},
|
notificationIDList: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1038,8 +1034,8 @@ exports.entryPage = "dashboard";
|
||||||
|
|
||||||
let notificationIDList = monitor.notificationIDList;
|
let notificationIDList = monitor.notificationIDList;
|
||||||
delete monitor.notificationIDList;
|
delete monitor.notificationIDList;
|
||||||
|
|
||||||
monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes);
|
monitor.checks_json = JSON.stringify(monitor.checks);
|
||||||
delete monitor.accepted_statuscodes;
|
delete monitor.accepted_statuscodes;
|
||||||
|
|
||||||
bean.import(monitor);
|
bean.import(monitor);
|
||||||
|
|
141
src/components/MonitorCheckEditor.vue
Normal file
141
src/components/MonitorCheckEditor.vue
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
<template>
|
||||||
|
<div class="monitor-check mb-4">
|
||||||
|
<div>
|
||||||
|
<select id="type" v-model="monitorCheck.type" :class="{'form-select': true, 'mb-1': !!monitorCheck.type}">
|
||||||
|
<option value="HTTP_STATUS_CODE_SHOULD_EQUAL">
|
||||||
|
{{ $t("HTTP status code should equal") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SHOULD_CONTAIN_TEXT">
|
||||||
|
{{ $t("Response should contain text") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SHOULD_NOT_CONTAIN_TEXT">
|
||||||
|
{{ $t("Response should not contain text") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SHOULD_MATCH_REGEX">
|
||||||
|
{{ $t("Response should match regex") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SHOULD_NOT_MATCH_REGEX">
|
||||||
|
{{ $t("Response should not match regex") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SELECTOR_SHOULD_EQUAL">
|
||||||
|
{{ $t("Response selector should equal") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SELECTOR_SHOULD_NOT_EQUAL">
|
||||||
|
{{ $t("Response selector should not equal") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SELECTOR_SHOULD_MATCH_REGEX">
|
||||||
|
{{ $t("Response selector should match regex") }}
|
||||||
|
</option>
|
||||||
|
<option value="RESPONSE_SELECTOR_SHOULD_NOT_MATCH_REGEX">
|
||||||
|
{{ $t("Response selector should not match regex") }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<div v-if="monitorCheck.type === 'HTTP_STATUS_CODE_SHOULD_EQUAL'">
|
||||||
|
<VueMultiselect
|
||||||
|
id="acceptedStatusCodes"
|
||||||
|
v-model="monitorCheck.value"
|
||||||
|
:options="acceptedStatusCodeOptions"
|
||||||
|
:multiple="true"
|
||||||
|
:close-on-select="false"
|
||||||
|
:clear-on-select="false"
|
||||||
|
:preserve-search="true"
|
||||||
|
placeholder="Pick Accepted Status Codes..."
|
||||||
|
:preselect-first="false"
|
||||||
|
:max-height="600"
|
||||||
|
:taggable="true"
|
||||||
|
></VueMultiselect>
|
||||||
|
</div>
|
||||||
|
<div v-if="monitorCheck.type === 'RESPONSE_SHOULD_CONTAIN_TEXT' || monitorCheck.type === 'RESPONSE_SHOULD_NOT_CONTAIN_TEXT'">
|
||||||
|
<input v-model="monitorCheck.value" type="text" class="form-control" required :placeholder="$t('Value')">
|
||||||
|
</div>
|
||||||
|
<div v-if="monitorCheck.type === 'RESPONSE_SHOULD_MATCH_REGEX' || monitorCheck.type === 'RESPONSE_SHOULD_NOT_MATCH_REGEX'">
|
||||||
|
<input v-model="monitorCheck.value" type="text" class="form-control" required
|
||||||
|
:placeholder="$t('Regexp, Example: [a-z0-9.]+@gmail\.com')">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="monitorCheck.type === 'RESPONSE_SELECTOR_SHOULD_EQUAL' || monitorCheck.type === 'RESPONSE_SELECTOR_SHOULD_NOT_EQUAL'">
|
||||||
|
<input v-model="monitorCheck.value.selector" type="text" class="form-control mb-1" required
|
||||||
|
:placeholder="$t('Selector, Example: customer.address.street')">
|
||||||
|
<input v-model="monitorCheck.value.value" type="text" class="form-control" required :placeholder="$t('Value, Example: First street')">
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="monitorCheck.type === 'RESPONSE_SELECTOR_SHOULD_MATCH_REGEX' || monitorCheck.type === 'RESPONSE_SELECTOR_SHOULD_NOT_MATCH_REGEX'">
|
||||||
|
<input v-model="monitorCheck.value.selector" type="text" class="form-control mb-1" required
|
||||||
|
:placeholder="$t('Selector, Example: customer.contactInfo.email')">
|
||||||
|
<input v-model="monitorCheck.value.value" type="text" class="form-control" required
|
||||||
|
:placeholder="$t('Regexp, Example: [a-z0-9.]+@gmail\.com')">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="btn btn-outline-danger" type="button" @click="deleteMonitorCheck">
|
||||||
|
<font-awesome-icon icon="times" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import VueMultiselect from "vue-multiselect";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
VueMultiselect,
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
monitorCheck: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
acceptedStatusCodeOptions: [],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
let acceptedStatusCodeOptions = [
|
||||||
|
"100-199",
|
||||||
|
"200-299",
|
||||||
|
"300-399",
|
||||||
|
"400-499",
|
||||||
|
"500-599",
|
||||||
|
];
|
||||||
|
|
||||||
|
for (let i = 100; i <= 999; i++) {
|
||||||
|
acceptedStatusCodeOptions.push(i.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
this.acceptedStatusCodeOptions = acceptedStatusCodeOptions;
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
deleteMonitorCheck() {
|
||||||
|
this.$emit('delete');
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../assets/vars.scss";
|
||||||
|
|
||||||
|
.monitor-check {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
input,
|
||||||
|
select {
|
||||||
|
border-radius: 19px 0 0 19px;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
margin-left: 0.25rem;
|
||||||
|
padding-left: 15px;
|
||||||
|
padding-right: 15px;
|
||||||
|
border-radius: 0 19px 19px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.monitor-check {
|
||||||
|
.multiselect__tags {
|
||||||
|
border-radius: 19px 0 0 19px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -6,13 +6,9 @@
|
||||||
<Tag v-for="tag in monitor.tags" :key="tag.id" :item="tag" :size="'sm'" />
|
<Tag v-for="tag in monitor.tags" :key="tag.id" :item="tag" :size="'sm'" />
|
||||||
</div>
|
</div>
|
||||||
<p class="url">
|
<p class="url">
|
||||||
<a v-if="monitor.type === 'http' || monitor.type === 'keyword' " :href="monitor.url" target="_blank">{{ monitor.url }}</a>
|
<a v-if="monitor.type === 'http'" :href="monitor.url" target="_blank">{{ monitor.url }}</a>
|
||||||
<span v-if="monitor.type === 'port'">TCP Ping {{ monitor.hostname }}:{{ monitor.port }}</span>
|
<span v-if="monitor.type === 'port'">TCP Ping {{ monitor.hostname }}:{{ monitor.port }}</span>
|
||||||
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
|
<span v-if="monitor.type === 'ping'">Ping: {{ monitor.hostname }}</span>
|
||||||
<span v-if="monitor.type === 'keyword'">
|
|
||||||
<br>
|
|
||||||
<span>{{ $t("Keyword") }}:</span> <span class="keyword">{{ monitor.keyword }}</span>
|
|
||||||
</span>
|
|
||||||
<span v-if="monitor.type === 'dns'">[{{ monitor.dns_resolve_type }}] {{ monitor.hostname }}
|
<span v-if="monitor.type === 'dns'">[{{ monitor.dns_resolve_type }}] {{ monitor.hostname }}
|
||||||
<br>
|
<br>
|
||||||
<span>{{ $t("Last Result") }}:</span> <span class="keyword">{{ monitor.dns_last_result }}</span>
|
<span>{{ $t("Last Result") }}:</span> <span class="keyword">{{ monitor.dns_last_result }}</span>
|
||||||
|
|
|
@ -12,19 +12,16 @@
|
||||||
<label for="type" class="form-label">{{ $t("Monitor Type") }}</label>
|
<label for="type" class="form-label">{{ $t("Monitor Type") }}</label>
|
||||||
<select id="type" v-model="monitor.type" class="form-select">
|
<select id="type" v-model="monitor.type" class="form-select">
|
||||||
<option value="http">
|
<option value="http">
|
||||||
HTTP(s)
|
{{ $t("HTTP(s)") }}
|
||||||
</option>
|
</option>
|
||||||
<option value="port">
|
<option value="port">
|
||||||
TCP Port
|
{{ $t("TCP Port") }}
|
||||||
</option>
|
</option>
|
||||||
<option value="ping">
|
<option value="ping">
|
||||||
Ping
|
{{ $t("Ping") }}
|
||||||
</option>
|
|
||||||
<option value="keyword">
|
|
||||||
HTTP(s) - {{ $t("Keyword") }}
|
|
||||||
</option>
|
</option>
|
||||||
<option value="dns">
|
<option value="dns">
|
||||||
DNS
|
{{ $t("DNS") }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
@ -34,19 +31,11 @@
|
||||||
<input id="name" v-model="monitor.name" type="text" class="form-control" required>
|
<input id="name" v-model="monitor.name" type="text" class="form-control" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3">
|
<div v-if="monitor.type === 'http'" class="my-3">
|
||||||
<label for="url" class="form-label">{{ $t("URL") }}</label>
|
<label for="url" class="form-label">{{ $t("URL") }}</label>
|
||||||
<input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required>
|
<input id="url" v-model="monitor.url" type="url" class="form-control" pattern="https?://.+" required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="monitor.type === 'keyword' " class="my-3">
|
|
||||||
<label for="keyword" class="form-label">{{ $t("Keyword") }}</label>
|
|
||||||
<input id="keyword" v-model="monitor.keyword" type="text" class="form-control" required>
|
|
||||||
<div class="form-text">
|
|
||||||
{{ $t("keywordDescription") }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- TCP Port / Ping / DNS only -->
|
<!-- TCP Port / Ping / DNS only -->
|
||||||
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' " class="my-3">
|
<div v-if="monitor.type === 'port' || monitor.type === 'ping' || monitor.type === 'dns' " class="my-3">
|
||||||
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
<label for="hostname" class="form-label">{{ $t("Hostname") }}</label>
|
||||||
|
@ -116,7 +105,7 @@
|
||||||
|
|
||||||
<h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
<h2 class="mt-5 mb-2">{{ $t("Advanced") }}</h2>
|
||||||
|
|
||||||
<div v-if="monitor.type === 'http' || monitor.type === 'keyword' " class="my-3 form-check">
|
<div v-if="monitor.type === 'http'" class="my-3 form-check">
|
||||||
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
|
<input id="ignore-tls" v-model="monitor.ignoreTls" class="form-check-input" type="checkbox" value="">
|
||||||
<label class="form-check-label" for="ignore-tls">
|
<label class="form-check-label" for="ignore-tls">
|
||||||
{{ $t("ignoreTLSError") }}
|
{{ $t("ignoreTLSError") }}
|
||||||
|
@ -133,8 +122,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- HTTP / Keyword only -->
|
<!-- HTTP only -->
|
||||||
<template v-if="monitor.type === 'http' || monitor.type === 'keyword' ">
|
<template v-if="monitor.type === 'http'">
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<label for="maxRedirects" class="form-label">{{ $t("Max. Redirects") }}</label>
|
<label for="maxRedirects" class="form-label">{{ $t("Max. Redirects") }}</label>
|
||||||
<input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1">
|
<input id="maxRedirects" v-model="monitor.maxredirects" type="number" class="form-control" required min="0" step="1">
|
||||||
|
@ -143,26 +132,13 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<h2 class="mt-5 mb-2">{{ $t("Checks") }}</h2>
|
||||||
|
|
||||||
<div class="my-3">
|
<div class="my-3">
|
||||||
<label for="acceptedStatusCodes" class="form-label">{{ $t("Accepted Status Codes") }}</label>
|
<div v-for="(monitorCheck, index) in monitor.checks" :key="index" class="mb-3">
|
||||||
|
<MonitorCheckEditor :monitorCheck="monitorCheck" :index="index" @delete="deleteMonitorCheck(index)"></MonitorCheckEditor>
|
||||||
<VueMultiselect
|
|
||||||
id="acceptedStatusCodes"
|
|
||||||
v-model="monitor.accepted_statuscodes"
|
|
||||||
:options="acceptedStatusCodeOptions"
|
|
||||||
:multiple="true"
|
|
||||||
:close-on-select="false"
|
|
||||||
:clear-on-select="false"
|
|
||||||
:preserve-search="true"
|
|
||||||
placeholder="Pick Accepted Status Codes..."
|
|
||||||
:preselect-first="false"
|
|
||||||
:max-height="600"
|
|
||||||
:taggable="true"
|
|
||||||
></VueMultiselect>
|
|
||||||
|
|
||||||
<div class="form-text">
|
|
||||||
{{ $t("acceptedStatusCodesDescription") }}
|
|
||||||
</div>
|
</div>
|
||||||
|
<button class="btn btn-light" type="button" @click="addMonitorCheck()">{{ $t("Add check") }}</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -210,6 +186,7 @@
|
||||||
<script>
|
<script>
|
||||||
import NotificationDialog from "../components/NotificationDialog.vue";
|
import NotificationDialog from "../components/NotificationDialog.vue";
|
||||||
import TagsManager from "../components/TagsManager.vue";
|
import TagsManager from "../components/TagsManager.vue";
|
||||||
|
import MonitorCheckEditor from "../components/MonitorCheckEditor.vue";
|
||||||
import { useToast } from "vue-toastification"
|
import { useToast } from "vue-toastification"
|
||||||
import VueMultiselect from "vue-multiselect"
|
import VueMultiselect from "vue-multiselect"
|
||||||
import { isDev } from "../util.ts";
|
import { isDev } from "../util.ts";
|
||||||
|
@ -219,6 +196,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
NotificationDialog,
|
NotificationDialog,
|
||||||
TagsManager,
|
TagsManager,
|
||||||
|
MonitorCheckEditor,
|
||||||
VueMultiselect,
|
VueMultiselect,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -341,7 +319,17 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
addMonitorCheck() {
|
||||||
|
this.monitor.checks = [...(this.monitor.checks || []), {
|
||||||
|
type: null,
|
||||||
|
value: '',
|
||||||
|
}];
|
||||||
|
},
|
||||||
|
|
||||||
|
deleteMonitorCheck(index) {
|
||||||
|
this.monitor.checks = this.monitor.checks.splice(index, 1);
|
||||||
},
|
},
|
||||||
|
|
||||||
async submit() {
|
async submit() {
|
||||||
|
|
Loading…
Add table
Reference in a new issue