mirror of
https://github.com/louislam/uptime-kuma.git
synced 2024-12-15 02:34:38 -05:00
Merge pull request #1513 from louislam/status-page-inject-html
[Status Page] Render title, meta tag or favicon etc. in server side
This commit is contained in:
commit
80094ec4e1
197
package-lock.json
generated
197
package-lock.json
generated
@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.15.1",
|
"version": "1.16.1",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "uptime-kuma",
|
"name": "uptime-kuma",
|
||||||
"version": "1.15.1",
|
"version": "1.16.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
"@fortawesome/fontawesome-svg-core": "~1.2.36",
|
||||||
@ -25,6 +25,7 @@
|
|||||||
"chart.js": "~3.6.2",
|
"chart.js": "~3.6.2",
|
||||||
"chartjs-adapter-dayjs": "~1.0.0",
|
"chartjs-adapter-dayjs": "~1.0.0",
|
||||||
"check-password-strength": "^2.0.5",
|
"check-password-strength": "^2.0.5",
|
||||||
|
"cheerio": "^1.0.0-rc.10",
|
||||||
"chroma-js": "^2.1.2",
|
"chroma-js": "^2.1.2",
|
||||||
"command-exists": "~1.2.9",
|
"command-exists": "~1.2.9",
|
||||||
"compare-versions": "~3.6.0",
|
"compare-versions": "~3.6.0",
|
||||||
@ -4536,8 +4537,7 @@
|
|||||||
"node_modules/boolbase": {
|
"node_modules/boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"node_modules/boolean": {
|
"node_modules/boolean": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
@ -5008,6 +5008,67 @@
|
|||||||
"resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.5.tgz",
|
||||||
"integrity": "sha512-b61T/+4OIGWSMRxJUsYOY44Cf9w7orIt2OQmF/WgH16qbJKIT1jG3XHx3jP+o090eH7rq13DRleKgXCiROBzMQ=="
|
"integrity": "sha512-b61T/+4OIGWSMRxJUsYOY44Cf9w7orIt2OQmF/WgH16qbJKIT1jG3XHx3jP+o090eH7rq13DRleKgXCiROBzMQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/cheerio": {
|
||||||
|
"version": "1.0.0-rc.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
||||||
|
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
|
||||||
|
"dependencies": {
|
||||||
|
"cheerio-select": "^1.5.0",
|
||||||
|
"dom-serializer": "^1.3.2",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"htmlparser2": "^6.1.0",
|
||||||
|
"parse5": "^6.0.1",
|
||||||
|
"parse5-htmlparser2-tree-adapter": "^6.0.1",
|
||||||
|
"tslib": "^2.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio-select": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==",
|
||||||
|
"dependencies": {
|
||||||
|
"css-select": "^4.3.0",
|
||||||
|
"css-what": "^6.0.1",
|
||||||
|
"domelementtype": "^2.2.0",
|
||||||
|
"domhandler": "^4.3.1",
|
||||||
|
"domutils": "^2.8.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio/node_modules/entities": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cheerio/node_modules/htmlparser2": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||||
|
"funding": [
|
||||||
|
"https://github.com/fb55/htmlparser2?sponsor=1",
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.0.0",
|
||||||
|
"domutils": "^2.5.2",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/chokidar": {
|
"node_modules/chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
@ -5664,11 +5725,37 @@
|
|||||||
"node": ">=12.22"
|
"node": ">=12.22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/css-select": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^6.0.1",
|
||||||
|
"domhandler": "^4.3.1",
|
||||||
|
"domutils": "^2.8.0",
|
||||||
|
"nth-check": "^2.0.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/css-unit-converter": {
|
"node_modules/css-unit-converter": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
|
||||||
"integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
|
"integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
|
||||||
},
|
},
|
||||||
|
"node_modules/css-what": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/fb55"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cssesc": {
|
"node_modules/cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
@ -5992,7 +6079,6 @@
|
|||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domelementtype": "^2.0.1",
|
"domelementtype": "^2.0.1",
|
||||||
"domhandler": "^4.2.0",
|
"domhandler": "^4.2.0",
|
||||||
@ -6006,7 +6092,6 @@
|
|||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
||||||
"dev": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/fb55/entities?sponsor=1"
|
"url": "https://github.com/fb55/entities?sponsor=1"
|
||||||
}
|
}
|
||||||
@ -6015,7 +6100,6 @@
|
|||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
||||||
"dev": true,
|
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
"type": "github",
|
"type": "github",
|
||||||
@ -6048,7 +6132,6 @@
|
|||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domelementtype": "^2.2.0"
|
"domelementtype": "^2.2.0"
|
||||||
},
|
},
|
||||||
@ -6063,7 +6146,6 @@
|
|||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dom-serializer": "^1.0.1",
|
"dom-serializer": "^1.0.1",
|
||||||
"domelementtype": "^2.2.0",
|
"domelementtype": "^2.2.0",
|
||||||
@ -12763,7 +12845,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
|
||||||
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
|
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
|
||||||
"dev": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"boolbase": "^1.0.0"
|
"boolbase": "^1.0.0"
|
||||||
},
|
},
|
||||||
@ -13176,8 +13257,15 @@
|
|||||||
"node_modules/parse5": {
|
"node_modules/parse5": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||||
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
|
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
|
||||||
"dev": true
|
},
|
||||||
|
"node_modules/parse5-htmlparser2-tree-adapter": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
|
||||||
|
"dependencies": {
|
||||||
|
"parse5": "^6.0.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"node_modules/parseqs": {
|
"node_modules/parseqs": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
@ -20304,8 +20392,7 @@
|
|||||||
"boolbase": {
|
"boolbase": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"boolean": {
|
"boolean": {
|
||||||
"version": "3.2.0",
|
"version": "3.2.0",
|
||||||
@ -20641,6 +20728,50 @@
|
|||||||
"resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.5.tgz",
|
||||||
"integrity": "sha512-b61T/+4OIGWSMRxJUsYOY44Cf9w7orIt2OQmF/WgH16qbJKIT1jG3XHx3jP+o090eH7rq13DRleKgXCiROBzMQ=="
|
"integrity": "sha512-b61T/+4OIGWSMRxJUsYOY44Cf9w7orIt2OQmF/WgH16qbJKIT1jG3XHx3jP+o090eH7rq13DRleKgXCiROBzMQ=="
|
||||||
},
|
},
|
||||||
|
"cheerio": {
|
||||||
|
"version": "1.0.0-rc.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz",
|
||||||
|
"integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==",
|
||||||
|
"requires": {
|
||||||
|
"cheerio-select": "^1.5.0",
|
||||||
|
"dom-serializer": "^1.3.2",
|
||||||
|
"domhandler": "^4.2.0",
|
||||||
|
"htmlparser2": "^6.1.0",
|
||||||
|
"parse5": "^6.0.1",
|
||||||
|
"parse5-htmlparser2-tree-adapter": "^6.0.1",
|
||||||
|
"tslib": "^2.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"entities": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||||
|
},
|
||||||
|
"htmlparser2": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
|
||||||
|
"requires": {
|
||||||
|
"domelementtype": "^2.0.1",
|
||||||
|
"domhandler": "^4.0.0",
|
||||||
|
"domutils": "^2.5.2",
|
||||||
|
"entities": "^2.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cheerio-select": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==",
|
||||||
|
"requires": {
|
||||||
|
"css-select": "^4.3.0",
|
||||||
|
"css-what": "^6.0.1",
|
||||||
|
"domelementtype": "^2.2.0",
|
||||||
|
"domhandler": "^4.3.1",
|
||||||
|
"domutils": "^2.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"chokidar": {
|
"chokidar": {
|
||||||
"version": "3.5.3",
|
"version": "3.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
|
||||||
@ -21162,11 +21293,28 @@
|
|||||||
"integrity": "sha512-PriDuifDt4u4rkDgnqRCLnjfMatufLmWNfQnGCq34xZwpY3oabwhB9SqRBmuvWUgndbemCFlKqg+nO7C2q0SBw==",
|
"integrity": "sha512-PriDuifDt4u4rkDgnqRCLnjfMatufLmWNfQnGCq34xZwpY3oabwhB9SqRBmuvWUgndbemCFlKqg+nO7C2q0SBw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"css-select": {
|
||||||
|
"version": "4.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
|
||||||
|
"integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
|
||||||
|
"requires": {
|
||||||
|
"boolbase": "^1.0.0",
|
||||||
|
"css-what": "^6.0.1",
|
||||||
|
"domhandler": "^4.3.1",
|
||||||
|
"domutils": "^2.8.0",
|
||||||
|
"nth-check": "^2.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"css-unit-converter": {
|
"css-unit-converter": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
|
||||||
"integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
|
"integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA=="
|
||||||
},
|
},
|
||||||
|
"css-what": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw=="
|
||||||
|
},
|
||||||
"cssesc": {
|
"cssesc": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
@ -21421,7 +21569,6 @@
|
|||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
|
||||||
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "^2.0.1",
|
"domelementtype": "^2.0.1",
|
||||||
"domhandler": "^4.2.0",
|
"domhandler": "^4.2.0",
|
||||||
@ -21431,16 +21578,14 @@
|
|||||||
"entities": {
|
"entities": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
|
||||||
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
|
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"domelementtype": {
|
"domelementtype": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
|
||||||
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
|
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"domexception": {
|
"domexception": {
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
@ -21463,7 +21608,6 @@
|
|||||||
"version": "4.3.1",
|
"version": "4.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
|
||||||
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"domelementtype": "^2.2.0"
|
"domelementtype": "^2.2.0"
|
||||||
}
|
}
|
||||||
@ -21472,7 +21616,6 @@
|
|||||||
"version": "2.8.0",
|
"version": "2.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
|
||||||
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"dom-serializer": "^1.0.1",
|
"dom-serializer": "^1.0.1",
|
||||||
"domelementtype": "^2.2.0",
|
"domelementtype": "^2.2.0",
|
||||||
@ -26547,7 +26690,6 @@
|
|||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
|
||||||
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
|
"integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"boolbase": "^1.0.0"
|
"boolbase": "^1.0.0"
|
||||||
}
|
}
|
||||||
@ -26850,8 +26992,15 @@
|
|||||||
"parse5": {
|
"parse5": {
|
||||||
"version": "6.0.1",
|
"version": "6.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||||
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
|
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw=="
|
||||||
"dev": true
|
},
|
||||||
|
"parse5-htmlparser2-tree-adapter": {
|
||||||
|
"version": "6.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
|
||||||
|
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
|
||||||
|
"requires": {
|
||||||
|
"parse5": "^6.0.1"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"parseqs": {
|
"parseqs": {
|
||||||
"version": "0.0.6",
|
"version": "0.0.6",
|
||||||
|
@ -76,6 +76,7 @@
|
|||||||
"chart.js": "~3.6.2",
|
"chart.js": "~3.6.2",
|
||||||
"chartjs-adapter-dayjs": "~1.0.0",
|
"chartjs-adapter-dayjs": "~1.0.0",
|
||||||
"check-password-strength": "^2.0.5",
|
"check-password-strength": "^2.0.5",
|
||||||
|
"cheerio": "^1.0.0-rc.10",
|
||||||
"chroma-js": "^2.1.2",
|
"chroma-js": "^2.1.2",
|
||||||
"command-exists": "~1.2.9",
|
"command-exists": "~1.2.9",
|
||||||
"compare-versions": "~3.6.0",
|
"compare-versions": "~3.6.0",
|
||||||
|
@ -1,10 +1,104 @@
|
|||||||
const { BeanModel } = require("redbean-node/dist/bean-model");
|
const { BeanModel } = require("redbean-node/dist/bean-model");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
|
const cheerio = require("cheerio");
|
||||||
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||||
|
|
||||||
class StatusPage extends BeanModel {
|
class StatusPage extends BeanModel {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like this: { "test-uptime.kuma.pet": "default" }
|
||||||
|
* @type {{}}
|
||||||
|
*/
|
||||||
static domainMappingList = { };
|
static domainMappingList = { };
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Response} response
|
||||||
|
* @param {string} indexHTML
|
||||||
|
* @param {string} slug
|
||||||
|
*/
|
||||||
|
static async handleStatusPageResponse(response, indexHTML, slug) {
|
||||||
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
|
slug
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (statusPage) {
|
||||||
|
response.send(await StatusPage.renderHTML(indexHTML, statusPage));
|
||||||
|
} else {
|
||||||
|
response.status(404).send(UptimeKumaServer.getInstance().indexHTML);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SSR for status pages
|
||||||
|
* @param {string} indexHTML
|
||||||
|
* @param {StatusPage} statusPage
|
||||||
|
*/
|
||||||
|
static async renderHTML(indexHTML, statusPage) {
|
||||||
|
const $ = cheerio.load(indexHTML);
|
||||||
|
const description155 = statusPage.description.substring(0, 155);
|
||||||
|
|
||||||
|
$("title").text(statusPage.title);
|
||||||
|
$("meta[name=description]").attr("content", description155);
|
||||||
|
|
||||||
|
if (statusPage.icon) {
|
||||||
|
$("link[rel=icon]")
|
||||||
|
.attr("href", statusPage.icon)
|
||||||
|
.removeAttr("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
const head = $("head");
|
||||||
|
|
||||||
|
// OG Meta Tags
|
||||||
|
head.append(`<meta property="og:title" content="${statusPage.title}" />`);
|
||||||
|
head.append(`<meta property="og:description" content="${description155}" />`);
|
||||||
|
|
||||||
|
// Preload data
|
||||||
|
const json = JSON.stringify(await StatusPage.getStatusPageData(statusPage));
|
||||||
|
head.append(`
|
||||||
|
<script>
|
||||||
|
window.preloadData = ${json}
|
||||||
|
</script>
|
||||||
|
`);
|
||||||
|
|
||||||
|
return $.root().html();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all status page data in one call
|
||||||
|
* @param {StatusPage} statusPage
|
||||||
|
*/
|
||||||
|
static async getStatusPageData(statusPage) {
|
||||||
|
// Incident
|
||||||
|
let incident = await R.findOne("incident", " pin = 1 AND active = 1 AND status_page_id = ? ", [
|
||||||
|
statusPage.id,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (incident) {
|
||||||
|
incident = incident.toPublicJSON();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Group List
|
||||||
|
const publicGroupList = [];
|
||||||
|
const showTags = !!statusPage.show_tags;
|
||||||
|
|
||||||
|
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
||||||
|
statusPage.id
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (let groupBean of list) {
|
||||||
|
let monitorGroup = await groupBean.toPublicJSON(showTags);
|
||||||
|
publicGroupList.push(monitorGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
return {
|
||||||
|
config: await statusPage.toPublicJSON(),
|
||||||
|
incident,
|
||||||
|
publicGroupList
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads domain mapping from DB
|
* Loads domain mapping from DB
|
||||||
* Return object like this: { "test-uptime.kuma.pet": "default" }
|
* Return object like this: { "test-uptime.kuma.pet": "default" }
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
let express = require("express");
|
let express = require("express");
|
||||||
const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin } = require("../util-server");
|
const { allowDevAllOrigin, allowAllOrigin, percentageToColor, filterAndJoin, send403 } = require("../util-server");
|
||||||
const { R } = require("redbean-node");
|
const { R } = require("redbean-node");
|
||||||
const apicache = require("../modules/apicache");
|
const apicache = require("../modules/apicache");
|
||||||
const Monitor = require("../model/monitor");
|
const Monitor = require("../model/monitor");
|
||||||
@ -99,108 +99,6 @@ router.get("/api/push/:pushToken", async (request, response) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Status page config, incident, monitor list
|
|
||||||
router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
|
|
||||||
allowDevAllOrigin(response);
|
|
||||||
let slug = request.params.slug;
|
|
||||||
|
|
||||||
// Get Status Page
|
|
||||||
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
|
||||||
slug
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (!statusPage) {
|
|
||||||
response.statusCode = 404;
|
|
||||||
response.json({
|
|
||||||
msg: "Not Found"
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Incident
|
|
||||||
let incident = await R.findOne("incident", " pin = 1 AND active = 1 AND status_page_id = ? ", [
|
|
||||||
statusPage.id,
|
|
||||||
]);
|
|
||||||
|
|
||||||
if (incident) {
|
|
||||||
incident = incident.toPublicJSON();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Public Group List
|
|
||||||
const publicGroupList = [];
|
|
||||||
const showTags = !!statusPage.show_tags;
|
|
||||||
|
|
||||||
const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [
|
|
||||||
statusPage.id
|
|
||||||
]);
|
|
||||||
|
|
||||||
for (let groupBean of list) {
|
|
||||||
let monitorGroup = await groupBean.toPublicJSON(showTags);
|
|
||||||
publicGroupList.push(monitorGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Response
|
|
||||||
response.json({
|
|
||||||
config: await statusPage.toPublicJSON(),
|
|
||||||
incident,
|
|
||||||
publicGroupList
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
send403(response, error.message);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// Status Page Polling Data
|
|
||||||
// Can fetch only if published
|
|
||||||
router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (request, response) => {
|
|
||||||
allowDevAllOrigin(response);
|
|
||||||
|
|
||||||
try {
|
|
||||||
let heartbeatList = {};
|
|
||||||
let uptimeList = {};
|
|
||||||
|
|
||||||
let slug = request.params.slug;
|
|
||||||
let statusPageID = await StatusPage.slugToID(slug);
|
|
||||||
|
|
||||||
let monitorIDList = await R.getCol(`
|
|
||||||
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
|
||||||
WHERE monitor_group.group_id = \`group\`.id
|
|
||||||
AND public = 1
|
|
||||||
AND \`group\`.status_page_id = ?
|
|
||||||
`, [
|
|
||||||
statusPageID
|
|
||||||
]);
|
|
||||||
|
|
||||||
for (let monitorID of monitorIDList) {
|
|
||||||
let list = await R.getAll(`
|
|
||||||
SELECT * FROM heartbeat
|
|
||||||
WHERE monitor_id = ?
|
|
||||||
ORDER BY time DESC
|
|
||||||
LIMIT 50
|
|
||||||
`, [
|
|
||||||
monitorID,
|
|
||||||
]);
|
|
||||||
|
|
||||||
list = R.convertToBeans("heartbeat", list);
|
|
||||||
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
|
|
||||||
|
|
||||||
const type = 24;
|
|
||||||
uptimeList[`${monitorID}_${type}`] = await Monitor.calcUptime(type, monitorID);
|
|
||||||
}
|
|
||||||
|
|
||||||
response.json({
|
|
||||||
heartbeatList,
|
|
||||||
uptimeList
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
send403(response, error.message);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response) => {
|
router.get("/api/badge/:id/status", cache("5 minutes"), async (request, response) => {
|
||||||
allowAllOrigin(response);
|
allowAllOrigin(response);
|
||||||
|
|
||||||
@ -377,16 +275,4 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request,
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
|
||||||
* Send a 403 response
|
|
||||||
* @param {Object} res Express response object
|
|
||||||
* @param {string} [msg=""] Message to send
|
|
||||||
*/
|
|
||||||
function send403(res, msg = "") {
|
|
||||||
res.status(403).json({
|
|
||||||
"status": "fail",
|
|
||||||
"msg": msg,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
110
server/routers/status-page-router.js
Normal file
110
server/routers/status-page-router.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
let express = require("express");
|
||||||
|
const apicache = require("../modules/apicache");
|
||||||
|
const { UptimeKumaServer } = require("../uptime-kuma-server");
|
||||||
|
const StatusPage = require("../model/status_page");
|
||||||
|
const { allowDevAllOrigin, send403 } = require("../util-server");
|
||||||
|
const { R } = require("redbean-node");
|
||||||
|
const Monitor = require("../model/monitor");
|
||||||
|
|
||||||
|
let router = express.Router();
|
||||||
|
|
||||||
|
let cache = apicache.middleware;
|
||||||
|
const server = UptimeKumaServer.getInstance();
|
||||||
|
|
||||||
|
router.get("/status/:slug", cache("5 minutes"), async (request, response) => {
|
||||||
|
let slug = request.params.slug;
|
||||||
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/status", cache("5 minutes"), async (request, response) => {
|
||||||
|
let slug = "default";
|
||||||
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/status-page", cache("5 minutes"), async (request, response) => {
|
||||||
|
let slug = "default";
|
||||||
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Status page config, incident, monitor list
|
||||||
|
router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => {
|
||||||
|
allowDevAllOrigin(response);
|
||||||
|
let slug = request.params.slug;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get Status Page
|
||||||
|
let statusPage = await R.findOne("status_page", " slug = ? ", [
|
||||||
|
slug
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!statusPage) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
let statusPageData = await StatusPage.getStatusPageData(statusPage);
|
||||||
|
|
||||||
|
if (!statusPageData) {
|
||||||
|
response.statusCode = 404;
|
||||||
|
response.json({
|
||||||
|
msg: "Not Found"
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Response
|
||||||
|
response.json(statusPageData);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
send403(response, error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Status Page Polling Data
|
||||||
|
// Can fetch only if published
|
||||||
|
router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (request, response) => {
|
||||||
|
allowDevAllOrigin(response);
|
||||||
|
|
||||||
|
try {
|
||||||
|
let heartbeatList = {};
|
||||||
|
let uptimeList = {};
|
||||||
|
|
||||||
|
let slug = request.params.slug;
|
||||||
|
let statusPageID = await StatusPage.slugToID(slug);
|
||||||
|
|
||||||
|
let monitorIDList = await R.getCol(`
|
||||||
|
SELECT monitor_group.monitor_id FROM monitor_group, \`group\`
|
||||||
|
WHERE monitor_group.group_id = \`group\`.id
|
||||||
|
AND public = 1
|
||||||
|
AND \`group\`.status_page_id = ?
|
||||||
|
`, [
|
||||||
|
statusPageID
|
||||||
|
]);
|
||||||
|
|
||||||
|
for (let monitorID of monitorIDList) {
|
||||||
|
let list = await R.getAll(`
|
||||||
|
SELECT * FROM heartbeat
|
||||||
|
WHERE monitor_id = ?
|
||||||
|
ORDER BY time DESC
|
||||||
|
LIMIT 50
|
||||||
|
`, [
|
||||||
|
monitorID,
|
||||||
|
]);
|
||||||
|
|
||||||
|
list = R.convertToBeans("heartbeat", list);
|
||||||
|
heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON());
|
||||||
|
|
||||||
|
const type = 24;
|
||||||
|
uptimeList[`${monitorID}_${type}`] = await Monitor.calcUptime(type, monitorID);
|
||||||
|
}
|
||||||
|
|
||||||
|
response.json({
|
||||||
|
heartbeatList,
|
||||||
|
uptimeList
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
send403(response, error.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
@ -16,7 +16,7 @@ if (nodeVersion < requiredVersion) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const args = require("args-parser")(process.argv);
|
const args = require("args-parser")(process.argv);
|
||||||
const { sleep, log, getRandomInt, genSecret, debug, isDev } = require("../src/util");
|
const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util");
|
||||||
const config = require("./config");
|
const config = require("./config");
|
||||||
|
|
||||||
log.info("server", "Welcome to Uptime Kuma");
|
log.info("server", "Welcome to Uptime Kuma");
|
||||||
@ -148,22 +148,6 @@ let jwtSecret = null;
|
|||||||
*/
|
*/
|
||||||
let needSetup = false;
|
let needSetup = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache Index HTML
|
|
||||||
* @type {string}
|
|
||||||
*/
|
|
||||||
let indexHTML = "";
|
|
||||||
|
|
||||||
try {
|
|
||||||
indexHTML = fs.readFileSync("./dist/index.html").toString();
|
|
||||||
} catch (e) {
|
|
||||||
// "dist/index.html" is not necessary for development
|
|
||||||
if (process.env.NODE_ENV !== "development") {
|
|
||||||
log.error("server", "Error: Cannot find 'dist/index.html', did you install correctly?");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
Database.init(args);
|
Database.init(args);
|
||||||
await initDatabase(testMode);
|
await initDatabase(testMode);
|
||||||
@ -179,13 +163,17 @@ try {
|
|||||||
|
|
||||||
// Entry Page
|
// Entry Page
|
||||||
app.get("/", async (request, response) => {
|
app.get("/", async (request, response) => {
|
||||||
debug(`Request Domain: ${request.hostname}`);
|
log.debug("entry", `Request Domain: ${request.hostname}`);
|
||||||
|
|
||||||
if (request.hostname in StatusPage.domainMappingList) {
|
if (request.hostname in StatusPage.domainMappingList) {
|
||||||
debug("This is a status page domain");
|
log.debug("entry", "This is a status page domain");
|
||||||
response.send(indexHTML);
|
|
||||||
|
let slug = StatusPage.domainMappingList[request.hostname];
|
||||||
|
await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug);
|
||||||
|
|
||||||
} else if (exports.entryPage && exports.entryPage.startsWith("statusPage-")) {
|
} else if (exports.entryPage && exports.entryPage.startsWith("statusPage-")) {
|
||||||
response.redirect("/status/" + exports.entryPage.replace("statusPage-", ""));
|
response.redirect("/status/" + exports.entryPage.replace("statusPage-", ""));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
response.redirect("/dashboard");
|
response.redirect("/dashboard");
|
||||||
}
|
}
|
||||||
@ -227,12 +215,16 @@ try {
|
|||||||
const apiRouter = require("./routers/api-router");
|
const apiRouter = require("./routers/api-router");
|
||||||
app.use(apiRouter);
|
app.use(apiRouter);
|
||||||
|
|
||||||
|
// Status Page Router
|
||||||
|
const statusPageRouter = require("./routers/status-page-router");
|
||||||
|
app.use(statusPageRouter);
|
||||||
|
|
||||||
// Universal Route Handler, must be at the end of all express routes.
|
// Universal Route Handler, must be at the end of all express routes.
|
||||||
app.get("*", async (_request, response) => {
|
app.get("*", async (_request, response) => {
|
||||||
if (_request.originalUrl.startsWith("/upload/")) {
|
if (_request.originalUrl.startsWith("/upload/")) {
|
||||||
response.status(404).send("File not found.");
|
response.status(404).send("File not found.");
|
||||||
} else {
|
} else {
|
||||||
response.send(indexHTML);
|
response.send(server.indexHTML);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,6 +29,12 @@ class UptimeKumaServer {
|
|||||||
httpServer = undefined;
|
httpServer = undefined;
|
||||||
io = undefined;
|
io = undefined;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cache Index HTML
|
||||||
|
* @type {string}
|
||||||
|
*/
|
||||||
|
indexHTML = "";
|
||||||
|
|
||||||
static getInstance(args) {
|
static getInstance(args) {
|
||||||
if (UptimeKumaServer.instance == null) {
|
if (UptimeKumaServer.instance == null) {
|
||||||
UptimeKumaServer.instance = new UptimeKumaServer(args);
|
UptimeKumaServer.instance = new UptimeKumaServer(args);
|
||||||
@ -55,6 +61,16 @@ class UptimeKumaServer {
|
|||||||
this.httpServer = http.createServer(this.app);
|
this.httpServer = http.createServer(this.app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.indexHTML = fs.readFileSync("./dist/index.html").toString();
|
||||||
|
} catch (e) {
|
||||||
|
// "dist/index.html" is not necessary for development
|
||||||
|
if (process.env.NODE_ENV !== "development") {
|
||||||
|
log.error("server", "Error: Cannot find 'dist/index.html', did you install correctly?");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.io = new Server(this.httpServer);
|
this.io = new Server(this.httpServer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,3 +558,15 @@ exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => {
|
|||||||
exports.filterAndJoin = (parts, connector = "") => {
|
exports.filterAndJoin = (parts, connector = "") => {
|
||||||
return parts.filter((part) => !!part && part !== "").join(connector);
|
return parts.filter((part) => !!part && part !== "").join(connector);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a 403 response
|
||||||
|
* @param {Object} res Express response object
|
||||||
|
* @param {string} [msg=""] Message to send
|
||||||
|
*/
|
||||||
|
module.exports.send403 = (res, msg = "") => {
|
||||||
|
res.status(403).json({
|
||||||
|
"status": "fail",
|
||||||
|
"msg": msg,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
@ -98,7 +98,7 @@
|
|||||||
<h1 class="mb-4 title-flex">
|
<h1 class="mb-4 title-flex">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<span class="logo-wrapper" @click="showImageCropUploadMethod">
|
<span class="logo-wrapper" @click="showImageCropUploadMethod">
|
||||||
<img :src="logoURL" alt class="logo me-2" :class="logoClass" @load="statusPageLogoLoaded" />
|
<img :src="logoURL" alt class="logo me-2" :class="logoClass" />
|
||||||
<font-awesome-icon v-if="enableEditMode" class="icon-upload" icon="upload" />
|
<font-awesome-icon v-if="enableEditMode" class="icon-upload" icon="upload" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
@ -538,7 +538,7 @@ export default {
|
|||||||
this.slug = "default";
|
this.slug = "default";
|
||||||
}
|
}
|
||||||
|
|
||||||
axios.get("/api/status-page/" + this.slug).then((res) => {
|
this.getData().then((res) => {
|
||||||
this.config = res.data.config;
|
this.config = res.data.config;
|
||||||
|
|
||||||
if (!this.config.domainNameList) {
|
if (!this.config.domainNameList) {
|
||||||
@ -567,6 +567,21 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get status page data
|
||||||
|
* It should be preloaded in window.preloadData
|
||||||
|
* @returns {Promise<any>}
|
||||||
|
*/
|
||||||
|
getData: function () {
|
||||||
|
if (window.preloadData) {
|
||||||
|
return new Promise(resolve => resolve({
|
||||||
|
data: window.preloadData
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return axios.get("/api/status-page/" + this.slug);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
highlighter(code) {
|
highlighter(code) {
|
||||||
return highlight(code, languages.css);
|
return highlight(code, languages.css);
|
||||||
},
|
},
|
||||||
@ -687,11 +702,6 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
statusPageLogoLoaded(eventPayload) {
|
|
||||||
// Remark: may not work in dev, due to CORS
|
|
||||||
favicon.image(eventPayload.target);
|
|
||||||
},
|
|
||||||
|
|
||||||
createIncident() {
|
createIncident() {
|
||||||
this.enableEditIncidentMode = true;
|
this.enableEditIncidentMode = true;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user