Compare commits

..

1168 Commits
1.0.0 ... 1.7.3

Author SHA1 Message Date
LouisLam
8d8d5987e7 update to 1.7.3 2021-09-30 14:44:37 +08:00
LouisLam
1fa90bffaa freeze vite version to 2.5.* (2.6.* is broken when build the project) 2021-09-30 14:43:29 +08:00
LouisLam
67f221d3c7 update to 1.7.2 2021-09-30 13:04:49 +08:00
LouisLam
6eceb4c744 Merge remote-tracking branch 'origin/master' 2021-09-29 17:20:58 +08:00
LouisLam
3e4154dfb5 Fix retry interval affected bug 2021-09-29 17:20:35 +08:00
Louis Lam
fbc8828ddc Merge pull request #464 from chakflying/fix-delete-monitor
Fix: clear important beats after deleteMonitor
2021-09-29 15:39:57 +08:00
LouisLam
3677aa639f update to 1.7.1 2021-09-29 14:26:30 +08:00
LouisLam
aaddfa1786 update package-lock.json 2021-09-29 13:30:28 +08:00
LouisLam
6d65d248f4 Merge branch 'bulgarian'
# Conflicts:
#	src/languages/da-DK.js
#	src/languages/fr-FR.js
#	src/languages/it-IT.js
#	src/languages/pl.js
#	src/languages/ru-RU.js
#	src/languages/zh-CN.js
2021-09-29 13:28:43 +08:00
LouisLam
87a4748b40 check back to root user for Debian, until problem has been found (#488) 2021-09-29 12:40:28 +08:00
Louis Lam
182bdf13a7 Merge pull request #500 from Saibamen/remove_timezone_console_log
Remove "Skip Timezone" console log from frontend
2021-09-29 12:16:51 +08:00
MrEddX
0f66e5cfc5 Added Bulgarian Language 2021-09-28 23:21:59 +03:00
Louis Lam
fe5ae46013 Merge pull request #480 from gaby/init-support
Add dumb-init to avoid zombie processes
2021-09-28 21:58:26 +08:00
Adam Stachowicz
756f317f82 Remove "Skip Timezone" console log from frontend 2021-09-28 07:29:32 +02:00
Louis Lam
cc9fe26584 Merge pull request #498 from kry008/patch-2
Update pl.js
2021-09-28 11:59:25 +08:00
kry008
99818aa370 Update pl.js
Aby było że to serwer sprawdza, a nie użytkownik ma.
Dokończenie tłumaczenia
2021-09-27 21:58:18 +02:00
Louis Lam
682265fe9c Merge pull request #481 from DX37/translation-ru
fix some ru-RU lines and add new ones
2021-09-28 00:13:37 +08:00
Louis Lam
4406e51ab6 Merge pull request #496 from bertyhell/bugfix/remove-zero-width-spaces
fix(nl-NL): remove ZWSP from translation
2021-09-28 00:13:16 +08:00
Louis Lam
c3d5be5a5e Merge pull request #493 from iomataani/master
updated translation
2021-09-28 00:08:12 +08:00
Louis Lam
dfe12c99c1 Merge pull request #490 from Minvinea/master
Update fr-FR.js
2021-09-28 00:07:58 +08:00
Louis Lam
bb69851160 Merge pull request #485 from Lrss/patch-1
Update Danish translation
2021-09-28 00:07:44 +08:00
Louis Lam
6c9323351d Merge pull request #484 from xinac721/master
Update Simplified Chinese Language(更新简体中文语言)
2021-09-28 00:06:57 +08:00
Bert Verhelst
8e9fa20e57 fix(nl-NL): remove ZWSP from translation 2021-09-27 17:51:48 +02:00
Ioma Taani
da7c29f4b9 updated translation 2021-09-27 13:23:53 +02:00
Minvinea
e545d48583 Update fr-FR.js
Update line 112 to 181
2021-09-26 21:39:38 +02:00
Lars Sørensen
8d84d8f891 Update da-DK.js with new strings 2021-09-26 15:28:46 +02:00
新逸Cary
74acc2cea7 Update Simplified Chinese Language(更新简体中文语言) 2021-09-26 14:31:16 +08:00
新逸Cary
ba4a4089eb Merge pull request #3 from louislam/master
update-21.09.26
2021-09-26 13:17:48 +08:00
DX37
122631c91b fix some ru-RU lines and add new ones 2021-09-26 01:44:00 +07:00
Juan Calderon-Perez
1e12f25c4b Add support for using init to start service 2021-09-25 12:26:30 -04:00
LouisLam
9e10296290 Merge remote-tracking branch 'origin/master' 2021-09-25 22:44:47 +08:00
LouisLam
87e213085f add /status, alias of /status-page (#471) 2021-09-25 22:44:29 +08:00
Louis Lam
d9038f1da2 Merge pull request #473 from Ponkhy/german-language
Added german translation for the status page
2021-09-24 23:26:30 +08:00
Louis Lam
3fb2d0ce68 Update README.md 2021-09-24 22:38:54 +08:00
Ponkhy
50a33e3b45 Added german translation for the status page 2021-09-24 15:56:35 +02:00
LouisLam
ce9a97a107 update to 1.7.0 2021-09-24 19:17:29 +08:00
LouisLam
0afa3a2c21 Merge branch '1.6.X'
# Conflicts:
#	server/database.js
#	server/server.js
2021-09-24 19:12:57 +08:00
LouisLam
51512b6f5f update dependencies 2021-09-24 19:00:06 +08:00
Louis Lam
3d79e841c9 Merge pull request #466 from chakflying/public-dashboard
[status-page] hide select if no monitors to add
2021-09-24 18:33:00 +08:00
Nelson Chan
d2af42e579 Fix: Add placeholder if no monitors to add 2021-09-24 16:51:53 +08:00
LouisLam
d6e3bd2282 Merge remote-tracking branch 'origin/master' 2021-09-24 16:01:18 +08:00
LouisLam
70fbe9a2d9 fix alpine nightly build 2021-09-24 16:00:08 +08:00
Louis Lam
c669e7eaba Merge pull request #469 from chakflying/patch-1
Fix: Fix importing tag if tag doesn't exist
2021-09-24 15:41:13 +08:00
LouisLam
9a9fd41f62 Merge branch 'master' into patch-1 2021-09-24 15:33:13 +08:00
LouisLam
50b868e751 fix #465 2021-09-24 15:26:48 +08:00
LouisLam
a856780066 fix the active link problem 2021-09-24 15:00:52 +08:00
LouisLam
266b03fbf7 language key from "Status Page Nothing" to "statusPageNothing" 2021-09-24 14:42:54 +08:00
Nelson Chan
662c97dcde Fix: Fix importing tag if tag doesn't exist 2021-09-24 14:34:53 +08:00
Louis Lam
1ebf752f1a Merge pull request #415 from Ponkhy/import-export
Added import/export compatibility for version 1.7
2021-09-24 14:00:28 +08:00
Mawoka
69bb6ef290 Removed empty selector if no monitor available 2021-09-24 00:19:09 +08:00
Ponkhy
720ea850e1 Added space between Dashboard and settings button 2021-09-23 17:33:23 +02:00
Ponkhy
7fb55b8875 Fixed issues 2021-09-23 17:31:01 +02:00
Ponkhy
4786514e9f Merge branch 'louislam:master' into import-export 2021-09-23 17:24:53 +02:00
Nelson Chan
32c9dfbb31 Fix: clear important beats after deleteMonitor 2021-09-23 23:21:08 +08:00
Ponkhy
d3d4363031 Used compare-version instead of replace 2021-09-23 17:15:11 +02:00
Louis Lam
6f352a6e3c [guide] update how to start dev server 2021-09-23 22:48:19 +08:00
Louis Lam
3fb06a8ba4 Merge pull request #463 from CosmoAbdon/ptBR-Translation
add: BR Portuguese Language and new words
2021-09-23 21:04:39 +08:00
Louis Lam
b3a5a5b0ba Merge pull request #462 from Saibamen/development_server
`start-server-dev` command. Fixes #460
2021-09-23 21:04:23 +08:00
Cosmo Abdon
a4cad3db65 add: BR Portuguese Language and new words 2021-09-23 09:42:33 -03:00
Adam Stachowicz
5fa9b33c79 Install cross-env as dev dependency for now 2021-09-23 12:49:15 +02:00
Adam Stachowicz
f6a984b671 start-server-dev. Fixes #460 2021-09-23 12:45:30 +02:00
LouisLam
23a63213aa Merge branch 'master' into import-export
# Conflicts:
#	server/server.js
2021-09-23 17:20:13 +08:00
Louis Lam
a9bb8ae6a1 Merge pull request #124 from chakflying/public-dashboard
Implement Public Dashboard
2021-09-23 16:54:07 +08:00
LouisLam
27d4c3c194 [status page] improve mobile layout 2021-09-23 16:31:45 +08:00
LouisLam
439f45d91e [status page] improve the entry 2021-09-23 13:57:24 +08:00
Louis Lam
66598a81cc Merge pull request #452 from chakflying/patch-8
Fix: Fix TCP Ping hostname Regex
2021-09-23 12:49:56 +08:00
Nelson Chan
45a6f364e1 Chore: Fix backslash in IP regex 2021-09-22 23:05:46 +08:00
Nelson Chan
95391be2ab Revert Regex update 2021-09-22 22:36:27 +08:00
LouisLam
5f533b9091 [status page] fix wrong foreign key 2021-09-22 18:50:20 +08:00
LouisLam
29920f6b60 [status page] use normal link to status-page, due to data reset problem 2021-09-22 18:05:40 +08:00
LouisLam
ad1bb93730 [status page] fix logo url 2021-09-22 15:31:15 +08:00
LouisLam
0a5a6e6a4b [status page] fix monitor order 2021-09-22 15:23:58 +08:00
LouisLam
fe0fc63843 [status page] send uptime 2021-09-22 15:10:08 +08:00
Nelson Chan
5b2e1f6086 Fix: Allow number ending TLD 2021-09-22 05:29:56 +08:00
LouisLam
8c7ee94769 add modified apicache library with disabling client cache 2021-09-22 00:58:22 +08:00
LouisLam
0834770509 [status page] also apply the title to <title> 2021-09-21 23:59:46 +08:00
LouisLam
a71814c80b add util.ts comments 2021-09-21 21:28:45 +08:00
LouisLam
17073fd786 Merge branch 'master' into public-dashboard 2021-09-21 21:25:16 +08:00
LouisLam
15c00d9158 upload logo and expose ./data/upload to url 2021-09-21 21:22:35 +08:00
Nelson Chan
d2b34f9285 Chore: make eslint happy 2021-09-21 18:53:45 +08:00
Nelson Chan
a96a515087 Fix: Fix hostname with dash 2021-09-21 18:44:32 +08:00
Nelson Chan
2eab919ae0 Fix: Fix typo 2021-09-21 18:41:19 +08:00
Nelson Chan
c09b67b94d Fix: Fix TCP Ping hostname Regex 2021-09-21 18:27:40 +08:00
LouisLam
61c737c53c fix alert text color in dark mode 2021-09-21 17:24:46 +08:00
Louis Lam
2820118eba Merge pull request #446 from Saibamen/util
Add comments from `util.ts` to `util.js`
2021-09-21 17:23:12 +08:00
LouisLam
469e8f6fd6 Merge branch 'master' into public-dashboard
# Conflicts:
#	package-lock.json
2021-09-21 17:05:13 +08:00
LouisLam
780cb0a145 install-legacy-peer-deps to install-legacy 2021-09-21 17:03:37 +08:00
LouisLam
1c8b3ce451 no need to build sqlite and add nightly for alpine 2021-09-21 10:47:55 +08:00
Adam Stachowicz
e8ef63e0a3 removeComments to false 2021-09-21 00:48:26 +02:00
LouisLam
4591adc05e second attempt: prebuilt node-sqlite3 and update SQLite to 3.36 2021-09-21 01:15:20 +08:00
LouisLam
5f6aa32844 fix store/fetch status page config 2021-09-20 20:44:07 +08:00
LouisLam
a8e170f6a8 Merge branch 'master' into public-dashboard
# Conflicts:
#	server/server.js
2021-09-20 18:48:44 +08:00
LouisLam
6aaf984f29 fix retryInterval = 0 if it is an old monitor. (#380 https://github.com/louislam/uptime-kuma/pull/380#issuecomment-922618356) 2021-09-20 18:23:53 +08:00
LouisLam
76a39f1388 update to 1.6.3 2021-09-20 16:56:03 +08:00
LouisLam
34c0fa59a8 fix reset-password (#448)
(cherry picked from commit b0e9c5bcb4)
2021-09-20 16:33:22 +08:00
LouisLam
0664217a09 Merge remote-tracking branch 'origin/master' 2021-09-20 16:29:43 +08:00
LouisLam
b0e9c5bcb4 fix reset-password (#448) 2021-09-20 16:29:18 +08:00
LouisLam
0b572df3d0 [status page] store config 2021-09-20 16:22:18 +08:00
Adam Stachowicz
bcc02c1680 Add formatting and comments from util.ts to util.js 2021-09-19 23:09:52 +02:00
Louis Lam
795d5f586f Merge pull request #444 from Saibamen/avg-ping_avg-response
Avg. Ping and Avg. Response translation keys
2021-09-20 02:23:50 +08:00
LouisLam
7ee98d989c [status page] implement rest api for heartbeat 2021-09-19 23:24:51 +08:00
Adam Stachowicz
7dc1e84e44 Avg. Ping and Avg. Response translation keys 2021-09-19 15:15:12 +02:00
LouisLam
6350c43cc3 fix newline? 2021-09-19 19:20:27 +08:00
LouisLam
fd95d41d9f [status page] many update and save group list 2021-09-19 19:04:51 +08:00
Louis Lam
7665bae927 Merge pull request #441 from iomataani/master
Italian translation updated
2021-09-19 16:32:08 +08:00
Ioma Taani
09e38269c6 Merge branch 'louislam:master' into master 2021-09-19 09:45:42 +02:00
LouisLam
6681f49a58 Merge branch 'master' into public-dashboard
# Conflicts:
#	.dockerignore
2021-09-19 15:16:13 +08:00
Louis Lam
3fc2ba3d76 Merge pull request #436 from nbvcxz/running_non-root_user
Docker entrypoint to run the application as non-root user
2021-09-19 14:33:20 +08:00
Louis Lam
78e12ab899 Merge pull request #439 from gaby/dockerignore
Add missing entries to dockerignore
2021-09-19 12:58:55 +08:00
Juan Calderon-Perez
2b8c049e7b Add missing entries to dockerignore 2021-09-18 13:53:24 -04:00
LouisLam
f0ac3c82d2 add some comments 2021-09-19 00:51:05 +08:00
Louis Lam
803029a9e4 Merge pull request #429 from Ponkhy/main
Added regex to hostname input
2021-09-19 00:38:40 +08:00
Louis Lam
c3f1cebeab Merge pull request #435 from DX37/translation-ru
fresh translations to ru-RU.js and Settings.vue
2021-09-19 00:37:37 +08:00
Louis Lam
5d9814559c Merge pull request #424 from Saibamen/fix_PL
Fix polish translation and translate new keys
2021-09-19 00:37:23 +08:00
DX37
9ef45a9c7e fresh translations to ru-RU.js and Settings.vue 2021-09-18 22:25:06 +07:00
Michal Ciania
7f78cc8d0f Substitute default values only once 2021-09-18 11:33:25 +02:00
Ioma Taani
ca84044809 Merge branch 'louislam:master' into master 2021-09-17 23:05:56 +02:00
Michal Ciania
9eaa4ab846 Docker entrypoint for running the application as non-root user 2021-09-17 22:57:27 +02:00
Marcos Sigueros Fernández
c3122a9807 Update es-ES.js (#430)
Simple but annoying language fix.
2021-09-17 22:20:45 +08:00
Ponkhy
f6498caa9a Merge branch 'main' of https://github.com/Ponkhy/uptime-kuma into main 2021-09-17 16:02:28 +02:00
Ponkhy
3a0bc80016 Added regex to hostname input 2021-09-17 16:02:20 +02:00
Ioma Taani
cbbc503f8e Merge branch 'louislam:master' into master 2021-09-17 11:31:21 +02:00
Louis
5be51abd8f Merge remote-tracking branch 'origin/master' 2021-09-17 15:19:36 +08:00
Louis
6ec219908b test nodejs 16 2021-09-17 15:19:19 +08:00
Louis
a6fdd272a6 [status page] minor 2021-09-17 14:42:19 +08:00
Ponkhy
1b5e723f60 Added descriptions to uploadBackup function 2021-09-17 03:25:18 +02:00
Ponkhy
4bdada36a9 Removed if includes version 2021-09-16 20:18:31 +02:00
Adam Stachowicz
250c2bdd6d Missing this 2021-09-16 20:17:25 +02:00
Adam Stachowicz
8e49d84050 Fix polish translation and translate new keys 2021-09-16 20:13:57 +02:00
Louis Lam
112d72da47 update discussion 2021-09-17 00:48:04 +08:00
LouisLam
9b8f01cfc6 since eslint can auto fix semicolon, standardize all end with semicolon 2021-09-16 22:57:34 +08:00
LouisLam
579e07ded4 Merge branch 'master' into public-dashboard 2021-09-16 22:52:05 +08:00
kry008
a04878fa84 Finishing the translation of PL (#422) 2021-09-16 22:49:24 +08:00
LouisLam
2955abb5d9 [status page] create incident 2021-09-16 22:48:28 +08:00
LouisLam
8230cfe13f use "next" tag to keep vue3 up-to-update 2021-09-16 20:07:26 +08:00
Ponkhy
8b463e70df Apply suggestions from @Saibamen
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-16 12:29:33 +02:00
LouisLam
392f8275b3 Merge branch 'master' into public-dashboard
# Conflicts:
#	server/database.js
2021-09-16 16:53:54 +08:00
Ioma Taani
783ec97004 updated translations 2021-09-16 09:10:13 +02:00
Siim Ots
4f4fe39c9b Simple "Add to Homescreen" manifest (PWA) (#411)
* simple "add to homescreen" manifest

* remove ?source=pwa

Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>

* run TinyPNG

Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
Co-authored-by: LouisLam <louislam@users.noreply.github.com>
2021-09-16 14:42:56 +08:00
LouisLam
611d214a32 [status page] checkpoint 2021-09-16 14:37:57 +08:00
Louis Lam
7a0cebf5bb Merge pull request #414 from Saibamen/lang_fixes
Fix languages
2021-09-16 14:33:05 +08:00
Ponkhy
54aa68ec58 Added import/export compatibility for version 1.7 2021-09-15 22:07:28 +02:00
Adam Stachowicz
217637aa1f Add de-DE translation 2021-09-15 21:19:16 +02:00
Adam Stachowicz
ab22961538 More info about update-language-files command 2021-09-15 21:16:22 +02:00
Adam Stachowicz
8ba8de07ae Missing this 2021-09-15 20:59:29 +02:00
Adam Stachowicz
a34b2623c8 Remove double spaces in console.log output with multiple parameters 2021-09-15 20:57:46 +02:00
Adam Stachowicz
79920b5f2c Fix languages after 80322cbfe7
Fix ESLint deprecated warning. Update `README.md` for  languages. Update `update-language-files` script
2021-09-15 20:52:39 +02:00
Louis Lam
72783fd94c Merge pull request #380 from No0Vad/retry-heartbeat-interval
Added support for a retry interval to monitors
2021-09-16 00:21:53 +08:00
LouisLam
80322cbfe7 Merge branch 'import-export'
# Conflicts:
#	src/languages/it-IT.js
#	src/languages/nl-NL.js
2021-09-16 00:18:07 +08:00
LouisLam
7e0272077b cleanup demo mode code 2021-09-16 00:13:28 +08:00
LouisLam
b2ff6b6098 update ignore files and delete demo db 2021-09-16 00:12:39 +08:00
LouisLam
512ff09cca set entry page 2021-09-15 20:40:26 +08:00
LouisLam
e8f4fabcd0 [status page] crop and resize logo 2021-09-15 18:28:48 +08:00
Ponkhy
f679c1cbaf Export button align left 2021-09-15 12:01:30 +02:00
LouisLam
2ab06f87b8 Merge branch 'master' into public-dashboard 2021-09-15 16:46:05 +08:00
Louis Lam
76db55b657 Merge pull request #395 from WillianRod/feat/add-microsoft-teams-notification
Add microsoft teams notification provider
2021-09-15 16:38:57 +08:00
LouisLam
1693873f4a [Teams] change handleTestNotification to GeneralNotification 2021-09-15 16:38:28 +08:00
Louis Lam
53bfdb7dad Merge pull request #409 from iomataani/master
updated
2021-09-15 14:38:17 +08:00
LouisLam
db05b506f3 [status page] checkpoint 2021-09-15 14:34:30 +08:00
Ioma Taani
0752f810f1 updated 2021-09-15 08:33:30 +02:00
Louis Lam
200d233607 Merge pull request #407 from SametKUM/master
Turkish Language added
2021-09-15 11:08:25 +08:00
samet.kum
7274913686 Turkish Language added 2021-09-15 02:55:04 +03:00
No0Vad
1300448bed Adjustments to the retry interval
The monitor logic for when to use "retryInterval" is updated. Also removed some texts when they are no longer needed.
2021-09-15 00:59:06 +02:00
Louis Lam
3f67326fce Merge pull request #404 from Ponkhy/main
Added search key
2021-09-15 01:20:51 +08:00
Louis Lam
8b48f9bd22 Merge pull request #405 from zidingz/patch-1
Update SECURITY.md
2021-09-15 01:19:29 +08:00
Louis Lam
76348cae5d Update SECURITY.md 2021-09-15 01:17:33 +08:00
Louis Lam
0b32adadb8 Update SECURITY.md 2021-09-15 01:12:59 +08:00
Ziding Zhang
3425a27a0e Update SECURITY.md
I'd like to report a security issue and felt it most prudent not to disclose it publicly, as per your Security policy instructions.

If not a hassle, might you kindly add an email, or other private contact method? GitHub [recommends](https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository) this best practice to ensure security issues are responsibly disclosed, and it would serve as a simple instruction for security researchers in the future.

Thank you for your consideration!
2021-09-14 17:54:51 +01:00
Ponkhy
fff5fd8e9e Added search key 2021-09-14 17:48:29 +02:00
LouisLam
1d6670ed9a Merge branch 'master' into public-dashboard 2021-09-14 23:29:22 +08:00
LouisLam
795411a11c Merge remote-tracking branch 'origin/master' 2021-09-14 23:28:52 +08:00
LouisLam
3234aec5b3 NODE_ENV if not set, change to production 2021-09-14 23:28:38 +08:00
LouisLam
afe91078c4 [status page] checkpoint 2021-09-14 23:27:11 +08:00
Louis Lam
2009f7097d Merge pull request #403 from Ponkhy/main
Added german translation for tags manager
2021-09-14 23:21:40 +08:00
Ponkhy
c14b71a4a7 Added german translation for tags manager 2021-09-14 17:05:17 +02:00
LouisLam
35fe9690e8 update to 1.6.2 2021-09-14 19:34:54 +08:00
LouisLam
ad2062713c fix pi4 on docker 2021-09-14 19:04:56 +08:00
Louis Lam
379656335d Merge pull request #402 from xoniq/lang-nl
Update new / updated translations to nl_NL
2021-09-14 15:49:26 +08:00
LouisLam
fc9b4617ca link interval and retryInterval 2021-09-14 15:48:25 +08:00
Jelle Posthuma
40d301457a Update new / updated translations to nl_NL 2021-09-14 09:22:50 +02:00
LouisLam
9902c181bc Merge branch 'master' into public-dashboard
# Conflicts:
#	src/components/MonitorList.vue
#	src/icon.js
2021-09-14 15:05:04 +08:00
Louis Lam
069c811af8 Merge pull request #278 from chakflying/tags
Monitor: Tags with metadata
2021-09-14 14:57:53 +08:00
LouisLam
f9311e4e7f [status page] 2021-09-14 14:55:45 +08:00
LouisLam
34abff4724 manual merge master 2021-09-14 14:19:23 +08:00
LouisLam
d7a230ac15 Merge branch 'master' into public-dashboard
# Conflicts:
#	server/server.js
#	src/main.js
2021-09-14 14:16:24 +08:00
LouisLam
9da2a01a74 [status page] checkpoint 2021-09-14 14:12:27 +08:00
Nelson Chan
74da02da2c Fix: Prevent enter in modal from submitting form 2021-09-14 12:25:31 +08:00
LouisLam
97360dab26 add /.well-known/change-password 2021-09-14 12:10:25 +08:00
Louis Lam
56dad006b5 Merge pull request #401 from NeuralMiner/patch-1
Allow SMTP that doesnt require authentication.
2021-09-14 10:05:43 +08:00
NeuralMiner
47092258f8 Allow SMTP that doesnt require authentication. 2021-09-13 16:36:37 -06:00
Willian Rodrigues Barbosa
a0838543b9 Merge branch 'feat/add-microsoft-teams-notification' of https://github.com/WillianRod/uptime-kuma into feat/add-microsoft-teams-notification 2021-09-13 14:03:14 -03:00
Willian Rodrigues Barbosa
ccb8736b3d fix: send msg if heartbeat message is not set 2021-09-13 14:02:52 -03:00
LouisLam
f351b423c5 link to the english version of microsoft link 2021-09-13 20:25:41 +08:00
LouisLam
ab6b97d77a update dependencies, fix axios security problem 2021-09-13 20:14:50 +08:00
LouisLam
0e16e88fa8 Merge remote-tracking branch 'origin/master' 2021-09-13 20:06:24 +08:00
LouisLam
c746923018 merge italian language file 2021-09-13 20:05:48 +08:00
LouisLam
df8754827d Merge branch 'italian-language-update'
# Conflicts:
#	src/languages/it-IT.js
2021-09-13 20:04:46 +08:00
Louis Lam
2c02dad1f9 Merge pull request #393 from Revyn112/master
add possibility to have a prefixMessage in discord notification before the embed
2021-09-13 20:02:55 +08:00
LouisLam
600ec6d171 Merge branch 'master' into i18n_router_own_files 2021-09-13 19:58:14 +08:00
LouisLam
728636de06 Merge branch 'feature/timezones-package' 2021-09-13 19:56:57 +08:00
LouisLam
8be7fd5c45 Merge remote-tracking branch 'bertyhell/feature/timezones-package' 2021-09-13 19:56:29 +08:00
LouisLam
59ff9fa293 update missing timezone console msg 2021-09-13 19:53:29 +08:00
LouisLam
a654e409df Merge branch 'master' into feature/timezones-package 2021-09-13 19:48:42 +08:00
LouisLam
76f1f34a0a fix #397, incorrect encode function for export file 2021-09-13 19:25:12 +08:00
LouisLam
35aca46b68 [status page] checkpoint 2021-09-13 19:21:39 +08:00
Paride Barison
6a925c7ed4 sistemato l'ordine 2021-09-13 09:19:07 +02:00
Paride Barison
8b9b86b478 updated 2021-09-13 09:10:42 +02:00
Nelson Chan
7c4b5f189b Fix: Fix hiding form when reusing draft tags 2021-09-13 14:12:17 +08:00
Nelson Chan
a6f9762c4d Feat: Split add tag to modal
Fix: Fix wrong css class

Fix: More misc. styling fixes
2021-09-13 14:12:17 +08:00
Nelson Chan
a0e4e96160 Fix: Fix tag removal, reuse and validation 2021-09-13 14:12:17 +08:00
Nelson Chan
fcbeed55bf Fix: Allow removing and re-adding the same tag
like, why would you even do this?
2021-09-13 14:12:17 +08:00
Nelson Chan
9b5abf9bb1 Fix: reset editMonitor after save 2021-09-13 14:12:17 +08:00
Nelson Chan
73f4b8e177 Fix: Improve various tags validation logic 2021-09-13 14:12:17 +08:00
Nelson Chan
e6669fbb9e Fix: Improve searchbar padding on mobile 2021-09-13 14:12:17 +08:00
Nelson Chan
e66a2d362d Feat: Add monitorList search box 2021-09-13 14:12:17 +08:00
Nelson Chan
c2148fc0f1 Fix: Slightly reduce tag opacity on light theme 2021-09-13 14:12:16 +08:00
Nelson Chan
6e3a904aaa WIP: Add tags functionality
WIP: add color column, show tags

WIP: Improve TagsManager styling & workflow

WIP: Improve styling & validation, use translation

WIP: Complete TagsManager functionality

WIP: Add tags display in monitorList & Details

Fix: update tags list after edit

Fix: slightly improve tags styling

Fix: Improve mobile UI

Fix: Fix tags not showing on create monitor

Fix: bring existingTags inside tagsManager

Fix: remove unused tags prop

Fix: Fix formatting, bump db version
2021-09-13 14:12:11 +08:00
Louis Lam
50175b733c Merge pull request #396 from Ponkhy/2fa
Hide 2FA section if disabled auth
2021-09-13 09:16:09 +08:00
No0Vad
2617e1f4d8 Update database.js 2021-09-13 00:25:18 +02:00
No0Vad
91ee39ec60 Merge branch 'master' into retry-heartbeat-interval 2021-09-13 00:19:51 +02:00
Ponkhy
4711aeb355 Merge branch 'master' into import-export 2021-09-12 23:21:33 +02:00
Ponkhy
db9e97d859 Merge pull request #2 from Saibamen/import-export
Separate import and export. Fix ESLint
2021-09-12 23:20:16 +02:00
Adam Stachowicz
7199bb5ead Remove unused i18n key 2021-09-12 23:11:07 +02:00
Ponkhy
bb87972543 Hide 2FA section if disabled auth 2021-09-12 21:58:52 +02:00
Adam Stachowicz
ea723c7595 Separate import and export. Fix ESLint 2021-09-12 21:35:37 +02:00
LouisLam
e205adfd7b [status page] developing 2021-09-13 02:26:45 +08:00
Willian Rodrigues Barbosa
063d64eec8 feat: add microsoft teams notification provider 2021-09-12 14:46:59 -03:00
Adam Stachowicz
5abf2e7597 Missing this 2021-09-12 19:44:33 +02:00
Adam Stachowicz
7c83bed273 Remove double spaces in Dockerfiles 2021-09-12 19:43:14 +02:00
Adam Stachowicz
1cc788da68 Missing this 2021-09-12 19:39:28 +02:00
Adam Stachowicz
54ffef8b7a Own files for i18n and router + fix some of markdown warnings 2021-09-12 19:23:51 +02:00
Revyn112
44aa837a9d Update NotificationDialog.vue 2021-09-12 19:17:09 +02:00
LouisLam
f47f7758f9 Merge branch 'master' into public-dashboard
# Conflicts:
#	server/database.js
#	server/server.js
#	server/util-server.js
2021-09-13 01:09:01 +08:00
Bert Verhelst
ddcd3c2a19 Merge remote-tracking branch 'origin/master' into feature/timezones-package 2021-09-12 19:03:05 +02:00
LouisLam
7df9698e5d eslint: comma-dangle for language files 2021-09-13 00:58:45 +08:00
Bert Verhelst
471333ad03 fix(util-frontend): revert typescript conversion 2021-09-12 18:56:39 +02:00
Ponkhy
d313966d80 Merge branch 'master' into import-export 2021-09-12 18:46:11 +02:00
LouisLam
8205f90f3d update language files 2021-09-13 00:45:43 +08:00
LouisLam
02247c4174 Merge remote-tracking branch 'origin/master' 2021-09-13 00:38:17 +08:00
Denis Freund
8352d9abbe add posibility to have a prefixMessage before the embed 2021-09-12 17:54:12 +02:00
Louis Lam
2d7767c905 Merge pull request #392 from bertyhell/bugfix/button-margin-settings
fix(settings): add some button bottom margin for narrow screens
2021-09-12 23:49:21 +08:00
Louis Lam
c52b9b63d5 Merge pull request #389 from Ponkhy/default-notification
Wording correction for notification modal
2021-09-12 23:49:09 +08:00
Louis Lam
e55193270d Merge pull request #377 from Lrss/master
Fix: Inconsistent white-space for the "Avg."-Ping/Response title.
2021-09-12 23:48:29 +08:00
Louis Lam
9d39071a91 Merge pull request #363 from Ponkhy/2fa
Added simple TOTP Two Factor Authentication
2021-09-12 23:47:42 +08:00
No0Vad
389d247463 Update server/database.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-12 17:05:23 +02:00
Bert Verhelst
a170694a83 fix(util-frontend): improve formatting timezoneList
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-12 15:21:40 +02:00
Bert Verhelst
5969e913b5 fix(util-frontend): improve formatting
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-12 15:19:27 +02:00
Louis Lam
0d280f5edb Merge pull request #376 from chakflying/patch-7
Fix: Fix events table width on mobile
2021-09-12 21:12:56 +08:00
Bert Verhelst
660b969178 fix(settings): switch custom styles to bootstrap class for bottom margin 2021-09-12 14:52:47 +02:00
Bert Verhelst
c26622aa39 fix(settings): add some button bottom margin for narrow screens 2021-09-12 13:40:07 +02:00
Bert Verhelst
a7674755ba Move timezones to npm package and convert util-frontend.js to typescript 2021-09-12 13:27:41 +02:00
Louis Lam
6d7cb44acc Merge pull request #387 from jtagcat/et2
i10n: update Estonian
2021-09-12 14:03:02 +08:00
LouisLam
400fc13cf2 add npm install script for npm7 2021-09-12 12:39:22 +08:00
Ponkhy
db14768229 Wording correction for notification modal 2021-09-12 01:44:05 +02:00
No0Vad
3d27561e5a Update en.js
Fixed spelling error
2021-09-12 00:24:33 +02:00
jtagcat
b80c88d9a0 i10n: update Estonian 2021-09-12 00:51:03 +03:00
Ponkhy
862672731f Minor typo fix 2021-09-11 22:06:26 +02:00
Ponkhy
7fee4a7ea7 Added import options 2021-09-11 21:53:17 +02:00
LouisLam
c4f78d776e [2fa] "UptimeKuma" to "Uptime Kuma" 2021-09-12 02:25:51 +08:00
No0Vad
f8f9f59464 Added support for a retry interval to monitors
If a check fails and retries are used you can now specify a specific value for that. So you can check faster if the site goes back up again.
2021-09-11 18:54:55 +02:00
LouisLam
934685637a [Status Page] WIP: Checkpoint 2021-09-11 23:43:07 +08:00
Ponkhy
295ccba44b Adjusted for new db patch management 2021-09-11 16:37:33 +02:00
Ponkhy
8cd5bad44c Merge branch 'master' into 2fa 2021-09-11 16:32:11 +02:00
Ponkhy
d003abcd60 Update src/languages/en.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-11 14:34:23 +02:00
Ponkhy
f6d1a82989 Update server/server.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-11 14:34:19 +02:00
Ponkhy
651b525d06 Update server/server.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-11 14:34:12 +02:00
Lars Sørensen
66769e1c79 Fixed inconsistent white-space for the "Avg."-Ping/Response title. 2021-09-11 13:52:41 +02:00
LouisLam
3e25f0e9d9 [Status Page] WIP: Checkpoint 2021-09-11 19:40:03 +08:00
Lars Sørensen
39c7b5e748 Added new Strings to Danish translation 2021-09-11 13:37:53 +02:00
Lars Sørensen
b709857e19 Better wording for Danish language 2021-09-11 13:20:40 +02:00
Nelson Chan
9e10f7d35f Fix: Fix events table width on mobile 2021-09-11 18:56:27 +08:00
Louis Lam
6caae725f9 Merge pull request #375 from Saibamen/format_backup_json
Format JSON file before download
2021-09-11 16:57:33 +08:00
Adam Stachowicz
c387fb264e Format JSON file before download 2021-09-11 10:50:56 +02:00
LouisLam
4b0a8087a2 do not connect to socket io for status page 2021-09-11 16:22:30 +08:00
LouisLam
08c7a37052 Merge branch 'master' into public-dashboard 2021-09-11 15:09:08 +08:00
LouisLam
0969be5981 Revert "WIP: Add login page, nav bar buttons"
This reverts commit b9a6088f50.
2021-09-11 15:08:56 +08:00
LouisLam
2ed8f12dc0 Merge remote-tracking branch 'origin/master' 2021-09-11 14:46:04 +08:00
LouisLam
2da77d8448 fix ipv6 connection problem 2021-09-11 14:37:05 +08:00
Louis Lam
f8322de5da Update bug_report.md 2021-09-11 13:44:06 +08:00
Louis Lam
e21a18a593 Update ask-for-help.md 2021-09-11 13:41:22 +08:00
Ponkhy
14b7688b70 Added NOT NULL to twofa_status 2021-09-11 00:13:05 +02:00
LouisLam
d953ba7c60 update to 1.6.1 2021-09-11 03:12:25 +08:00
LouisLam
ef1604675b change to node:14-bullseye-slim, and reduce the docker image size 2021-09-11 02:50:29 +08:00
Louis Lam
83fc844e8e Update deployment.yml 2021-09-10 22:32:11 +08:00
Louis Lam
22a7acbaf6 Update README.md 2021-09-10 22:03:28 +08:00
LouisLam
201bba63d7 add a healthcheck comment 2021-09-10 21:17:20 +08:00
Ioma Taani
0d6888c586 Merge branch 'louislam:master' into italian-language-update 2021-09-10 13:36:43 +02:00
Ioma Taani
a06fc14213 Merge branch 'louislam:master' into italian-language-update 2021-09-10 12:08:29 +02:00
LouisLam
31b4a5c33e build-docker, debian first 2021-09-10 18:08:23 +08:00
Paride Barison
951ece8a65 updated 2021-09-10 12:07:54 +02:00
LouisLam
a49df29a87 update to 1.6.0 2021-09-10 17:56:33 +08:00
LouisLam
08de0090dc add a better approach for patching db, change setting.value from varchar to TEXT, restore Database.close() to 1.2.0 2021-09-10 17:23:45 +08:00
Louis Lam
97df200d6c Merge pull request #365 from Ponkhy/master
Minor translation fixes
2021-09-10 11:46:20 +08:00
Louis Lam
d5b17a3778 Merge pull request #367 from xinac721/master
update Simplified Chinese language(更新简体中文语言)
2021-09-10 11:45:57 +08:00
新逸Cary
2f0d994c83 update Simplified Chinese language(更新简体中文语言) 2021-09-10 09:26:01 +08:00
新逸Cary
e683033f4e Merge pull request #2 from louislam/master
update
2021-09-10 08:52:38 +08:00
Ponkhy
c3c576bd13 Added "Show URI" translation 2021-09-10 01:33:26 +02:00
Ponkhy
c62732fa9c Minor translation fixes 2021-09-10 01:24:21 +02:00
Ponkhy
d823493fad Added maxlengh to token verify input 2021-09-09 22:08:34 +02:00
Ponkhy
463c385cf1 Only show modal footer if uri was generated 2021-09-09 21:38:39 +02:00
Ponkhy
59cccf8c50 Fixed typo 2021-09-09 21:12:29 +02:00
Ponkhy
403202d4d4 Added simple TOTP Two Factor Authentication 2021-09-09 21:10:31 +02:00
Louis Lam
2583dbe0e0 Update README.md 2021-09-09 22:58:31 +08:00
LouisLam
ca479673e7 avoid Chrome duplicate id warning 2021-09-09 21:28:27 +08:00
LouisLam
573c7faddd switch on the notification, if it is added in EditMonitor.vue 2021-09-09 21:24:29 +08:00
LouisLam
7a4432de1e better switch button color in dark mode 2021-09-09 20:45:58 +08:00
LouisLam
94a6c1a344 update language files 2021-09-09 20:38:19 +08:00
Louis Lam
ee9e48fe53 Merge pull request #361 from iomataani/italian-translation-update
Italian translation update
2021-09-09 20:26:07 +08:00
LouisLam
a4aee49b03 Merge remote-tracking branch 'origin/master' 2021-09-09 20:22:44 +08:00
LouisLam
e330875c80 fix restore fail if no isDefault 2021-09-09 20:22:32 +08:00
Paride Barison
44eba70b78 altri errorini sistemati 2021-09-09 14:19:15 +02:00
Paride Barison
c6dab944d1 altra correzione 2021-09-09 14:12:30 +02:00
Ioma Taani
0f4bc5850b Merge branch 'louislam:master' into italian-translation-update 2021-09-09 14:05:00 +02:00
Louis Lam
f37190a73d Update README.md 2021-09-09 18:02:58 +08:00
Louis Lam
29f96fae93 Update README.md 2021-09-09 18:01:15 +08:00
Louis Lam
331ae5ec20 Merge pull request #306 from Ponkhy/import-export
Added import and export function
2021-09-09 16:15:48 +08:00
LouisLam
8ee34c7904 also handle the first beat problem in uptime 2021-09-09 15:55:34 +08:00
LouisLam
4f07c2ea9a uptime calculation fully sum in sql 2021-09-09 15:46:28 +08:00
LouisLam
0b1d0d22ff add indexes, improve queries 2021-09-09 12:43:18 +08:00
LouisLam
24facc79d7 sendHeartbeatList use raw data 2021-09-09 11:57:23 +08:00
LouisLam
9f9c1007d7 increase sqlite cache size from 2MB to 12MB 2021-09-09 11:56:42 +08:00
LouisLam
70a6f0313c update .dockerignore 2021-09-09 11:41:43 +08:00
LouisLam
1d05df6ec9 [docker healthcheck] use retries instead, longer start-period causes starting problem in Docker Swarm mode 2021-09-09 11:41:28 +08:00
Ioma Taani
b54bbc302d migliorata la traduzione 2021-09-08 21:34:48 +02:00
LouisLam
dd283423ab improve smtp with cc, bbc and ignore tls 2021-09-09 01:13:09 +08:00
LouisLam
6006038689 fix monitor.stop() in some cases 2021-09-08 20:00:16 +08:00
LouisLam
a7b50c3630 Revert "add user-monitor-list"
This reverts commit 230a9bfaf9.
2021-09-08 19:54:38 +08:00
LouisLam
0ddbac5109 Revert "move userMonitorList out of server.js"
This reverts commit a7cf14c663.
2021-09-08 19:54:38 +08:00
LouisLam
0f440596c8 Revert "cache last heartbeat list in memory"
This reverts commit 87678ea92d.
2021-09-08 19:54:37 +08:00
LouisLam
5a0fcebd6e update link style 2021-09-08 18:59:30 +08:00
LouisLam
87678ea92d cache last heartbeat list in memory 2021-09-08 18:58:02 +08:00
LouisLam
0bf0cfa104 Merge remote-tracking branch 'origin/master' 2021-09-08 18:56:43 +08:00
LouisLam
a7cf14c663 move userMonitorList out of server.js 2021-09-08 16:27:37 +08:00
Louis Lam
325ce72a71 Merge pull request #352 from iomataani/italian-language
Italian language
2021-09-08 16:12:44 +08:00
Louis Lam
9d00bd9029 Merge pull request #357 from Saibamen/nav_from_dashHome
Route to monitor on `DashboardHome`
2021-09-08 16:11:39 +08:00
Adam Stachowicz
f6a168282e Route to monitor on DashboardHome 2021-09-08 09:55:08 +02:00
Ponkhy
acf6f1883b Fixed missing spaces in backup file 2021-09-08 09:02:24 +02:00
Paride Barison
f44f951e40 Tradotte le ultime cose come richiesto 2021-09-08 08:41:19 +02:00
Ioma Taani
dea9b05d49 Merge branch 'louislam:master' into italian-language 2021-09-08 08:30:10 +02:00
LouisLam
230a9bfaf9 add user-monitor-list 2021-09-08 14:16:30 +08:00
Louis Lam
d761d54d0e Merge pull request #340 from Ponkhy/default-notification
Added the option for default notifications
2021-09-08 12:49:14 +08:00
LouisLam
e37621853e Merge branch 'estonian'
# Conflicts:
#	src/pages/Settings.vue
2021-09-08 11:00:19 +08:00
LouisLam
f2cec60481 minor 2021-09-08 10:48:03 +08:00
LouisLam
2212cf9c08 fix confirmDisableAuth no msg if not tranlated 2021-09-08 10:28:40 +08:00
LouisLam
f7562e00c1 improve notification component, no double template 2021-09-08 10:25:03 +08:00
Ponkhy
678e248966 Added indicator while changing database records 2021-09-08 01:10:19 +02:00
Ponkhy
c1aebef005 Fixed SQL error due notification setup 2021-09-08 01:03:24 +02:00
Ponkhy
1ef4562905 Paused monitors stay paused after import 2021-09-07 23:32:25 +02:00
Ponkhy
69a7c4dab4 Improved importBackup handling 2021-09-07 23:14:44 +02:00
jtagcat
2c3880a326 Added Estonian.
- "Avg.": using ≈, as it's commonly enough known.
   There is no known shorthand for 'average' that I know of.

- Leaved some strings empty, as repeating the same words is useless, just noise.
2021-09-07 23:31:48 +03:00
Ponkhy
f4e885982d Added export/import description for de-DE 2021-09-07 21:10:47 +02:00
Ioma Taani
dcf6dd8b32 Ultimi aggiustamenti 2021-09-07 19:16:29 +02:00
Ioma Taani
093cfec8dd Typo. 2021-09-07 19:13:04 +02:00
Ioma Taani
f13dcb3c5b Update it-IT.js
Completed.
2021-09-07 19:07:50 +02:00
LouisLam
1a5ffd4755 add description for export/import 2021-09-08 00:46:48 +08:00
Ioma Taani
a2f9e9e9c4 Creata lingua italiana 2021-09-07 18:25:24 +02:00
LouisLam
62712f5cc4 Merge branch 'master' into import-export 2021-09-08 00:18:43 +08:00
LouisLam
f0f1847ad8 update language files 2021-09-07 23:53:20 +08:00
LouisLam
0aeaf87f5b Merge branch 'master' into default-notification
# Conflicts:
#	server/notification.js
#	src/components/NotificationDialog.vue
2021-09-07 23:40:42 +08:00
LouisLam
5ca0dd628d remove debug msg 2021-09-07 23:36:55 +08:00
LouisLam
4a106431f3 convert Telegram into a vue components 2021-09-07 23:32:05 +08:00
LouisLam
d164b6ccce prevent Chrome ask for saving password for notification settings (change to one-time-code to solve it) 2021-09-07 23:06:49 +08:00
LouisLam
da74391c3e convert notifications into modules 2021-09-07 22:42:46 +08:00
Louis Lam
850563442a Merge pull request #349 from Ponkhy/redirect-after-setup
Auto login after setup
2021-09-07 21:16:54 +08:00
Ponkhy
242e494cb5 Merge branch 'master' into import-export 2021-09-07 14:12:53 +02:00
Ponkhy
4faa409027 Merge branch 'master' into default-notification 2021-09-07 14:07:50 +02:00
Louis Lam
f842fb409e Update README.md 2021-09-07 17:44:51 +08:00
Louis Lam
72dd894856 Update README.md 2021-09-07 17:44:39 +08:00
LouisLam
0b0417e064 Merge remote-tracking branch 'origin/master' 2021-09-07 17:40:36 +08:00
LouisLam
fe35d95441 merge language files 2021-09-07 17:38:04 +08:00
LouisLam
da131a5156 Merge branch 'master' into clear-monitor-data
# Conflicts:
#	src/languages/da-DK.js
#	src/languages/en.js
#	src/languages/es-ES.js
#	src/languages/fr-FR.js
#	src/languages/ja.js
#	src/languages/ko-KR.js
#	src/languages/nl-NL.js
#	src/languages/ru-RU.js
#	src/languages/sr-latn.js
#	src/languages/sr.js
#	src/languages/sv-SE.js
#	src/languages/zh-CN.js
#	src/languages/zh-HK.js
2021-09-07 17:36:37 +08:00
Louis Lam
926c15ea40 Update healthcheck.js 2021-09-07 17:30:50 +08:00
LouisLam
87e874406a Merge branch 'Ponkhy_master_hidden' 2021-09-07 17:09:24 +08:00
LouisLam
0e288ea92d disable chrome save password dialog for autocompelete = off only 2021-09-07 17:06:33 +08:00
LouisLam
8a4a87716f disable chrome save password dialog 2021-09-07 16:46:42 +08:00
Ponkhy
d01fa9bcfc Auto login after setup 2021-09-07 10:25:25 +02:00
LouisLam
ec8c1cad31 update healthcheck.js for changing ssl cert / hostname / port 2021-09-07 16:06:28 +08:00
LouisLam
fb0fa2a843 add sqlite cli to docker 2021-09-07 15:36:29 +08:00
LouisLam
f5c6d422d5 switch debian to be the main docker base 2021-09-07 15:31:32 +08:00
Louis Lam
ea4240455f Merge pull request #347 from gaby/refactor-docker
Debian Dockerfile refactoring and improvements
2021-09-07 15:21:19 +08:00
Juan Calderon-Perez
ce30ee74e9 Revert changes breaking ARM releases 2021-09-07 01:26:42 -04:00
Juan Calderon-Perez
66b5f157eb Update Dockerfile order to improve layer caching. 2021-09-07 00:13:07 -04:00
Juan Calderon-Perez
5fe8a0917a Refactor Debian Dockerfile 2021-09-06 22:20:12 -04:00
Ponkhy
848296b77a Changed input for sensitive data to HiddenInput 2021-09-07 02:30:53 +02:00
Ponkhy
edfaacbb5f Added component HiddenInput.vue 2021-09-07 02:24:02 +02:00
Ponkhy
bb8385d690 Merge branch 'default-notification' of https://github.com/Ponkhy/uptime-kuma into default-notification 2021-09-06 09:46:36 +02:00
Ponkhy
b95404b6e0 Fixed suggestions 2021-09-06 09:45:52 +02:00
Louis Lam
cc351b2883 Merge pull request #339 from Minvinea/master
Update few words and file name
2021-09-06 13:38:26 +08:00
Louis Lam
3c06f249ca Merge pull request #338 from Saibamen/pl_fixes
[LANG] `pl` fixes
2021-09-06 12:44:56 +08:00
Minvinea
31648dc5e8 Update #2 2021-09-05 23:41:57 +02:00
Minvinea
1197cfa11e Update file name 2021-09-05 23:37:26 +02:00
Ponkhy
fd8c95d64e Merge branch 'master' into default-notification 2021-09-05 23:32:31 +02:00
Ponkhy
58240aceef Added the option for default notifications 2021-09-05 23:23:06 +02:00
Adam Stachowicz
e8b814733d Fix typo 2021-09-05 23:14:56 +02:00
Minvinea
dcc7799108 Update few words and name of file
https://prnt.sc/1rbosiy
2021-09-05 21:34:32 +02:00
Adam Stachowicz
424f20f8e1 Better upsideDownModeDescription 2021-09-05 20:59:04 +02:00
Adam Stachowicz
d4ff5d8b32 [LANG] pl fixes 2021-09-05 20:55:25 +02:00
LouisLam
899b33b3a9 add language missing keys 2021-09-06 01:31:05 +08:00
Ponkhy
1b8b33c4c3 Added set language to the Setup.vue 2021-09-05 15:40:35 +02:00
Louis Lam
d34ed00841 Merge pull request #333 from Misly16/master
Add Polish Locale
2021-09-05 12:03:07 +08:00
Louis Lam
f9c177b150 Merge pull request #315 from tgxn/patch-1
Notifications Content Improvements: SMTP, LunaSea, PushBullet
2021-09-05 11:52:50 +08:00
Misly
9952463350 Add Polish Locale 2021-09-04 20:38:53 +00:00
LouisLam
5837c353b7 change the default theme to auto from light 2021-09-05 02:47:31 +08:00
LouisLam
d5b32ffbb8 add language missing keys 2021-09-05 02:25:40 +08:00
LouisLam
61936ae5eb Merge remote-tracking branch 'Ponkhy/clear-monitor-data' into clear-monitor-data 2021-09-05 02:04:48 +08:00
LouisLam
299506ce45 reset the heartbeat list instead of reload the page after cleared events or heartbeats 2021-09-05 02:03:40 +08:00
LouisLam
ca8d4ab61b Merge branch 'master' into clear-monitor-data 2021-09-05 00:24:09 +08:00
LouisLam
ffbdf97478 improve heartbeat bar rendering in different dpi 2021-09-05 00:08:24 +08:00
LouisLam
cc25787878 improve heartbeat bar rendering in different dpi 2021-09-04 23:32:46 +08:00
Louis Lam
17453a8812 Merge pull request #332 from LeviSnoot/master
Update & Improve Swedish Translation
2021-09-04 23:16:01 +08:00
Levi
f1a151b4a1 Update & Improve Swedish Translation 2021-09-04 16:03:34 +02:00
Levi
d35b205fcc Update & Improve Swedish Translation 2021-09-04 16:01:41 +02:00
Levi
2a34e41d8c Improved Swedish translation 2021-09-04 15:59:49 +02:00
Domenic Horner
41d32bb9dd Undo parm changes 2021-09-04 20:08:18 +08:00
Ponkhy
0b9e410ea5 Added i18n key to en.js 2021-09-04 13:36:08 +02:00
Ponkhy
904ed326ca Merge branch 'louislam:master' into clear-monitor-data 2021-09-04 13:34:29 +02:00
LouisLam
778995a4fb add dockerfile-debian 2021-09-04 15:48:25 +08:00
LouisLam
ee60d74910 fix dockerfile path 2021-09-04 15:32:55 +08:00
LouisLam
6a603203cc update to 1.5.3 2021-09-04 15:07:32 +08:00
LouisLam
4b8e7fcffc update "build-docker" to build both platforms 2021-09-04 15:03:26 +08:00
LouisLam
7fd12f5485 rename nl_NL.js to nl-NL.js 2021-09-04 14:42:55 +08:00
LouisLam
0d87a6dfea update vue to 3.2.8 2021-09-04 14:41:45 +08:00
Domenic Horner
b0acda52f9 Add time to smtp body content 2021-09-04 11:27:18 +08:00
Domenic Horner
e9cd9be03a Use constants for UP/DOWN through notifications class 2021-09-04 11:09:34 +08:00
Domenic Horner
6ae279c7f3 Move title generation to notification class 2021-09-04 11:06:06 +08:00
Domenic Horner
9c32adfb55 Update pushbullet down body
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-04 18:26:44 +08:00
Domenic Horner
d346afd33b Update pushbullet up body
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-04 18:26:38 +08:00
Domenic Horner
3bf380c684 Update lunasea "up" body content
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-04 18:26:10 +08:00
Domenic Horner
dca5c59982 Update lunasea body content
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-04 18:24:43 +08:00
Ponkhy
8f9a973ede Merge branch 'master' into import-export 2021-09-04 01:26:48 +02:00
Ponkhy
b98ec0c3d4 Added i18n keys if necessary for some languages 2021-09-04 01:26:06 +02:00
Louis Lam
2082c3f68a Merge pull request #313 from xoniq/lang-nl
Add Dutch/Nederlands language (nl_NL)
2021-09-04 00:05:05 +08:00
Louis Lam
ea9f434553 Merge pull request #328 from Ponkhy/german-language
Small german language adjustments
2021-09-03 23:06:32 +08:00
Louis Lam
fa1216c198 Merge pull request #329 from dhfhfk/New-string
Add missing strings for Korean
2021-09-03 23:05:48 +08:00
dhfhfk
6d8aa20fc6 Add missing string for Korean
confirmDisableAuth, new string
2021-09-03 23:18:18 +09:00
Ponkhy
5430da955a Small german language adjustments 2021-09-03 15:54:14 +02:00
J Posthuma
e6e2b0ebf8 Update nl_NL.js 2021-09-03 13:42:14 +02:00
J Posthuma
445dc486be Merge branch 'master' into lang-nl 2021-09-03 13:41:10 +02:00
Louis Lam
d2151737c1 Update README.md 2021-09-03 17:09:11 +08:00
Louis Lam
78fc6de542 Merge pull request #325 from Saibamen/patch-1
Update `README.md` - Open Collective URL
2021-09-03 15:49:23 +08:00
Adam Stachowicz
c15e6631ae Update README.md
Open Collective URL
2021-09-03 09:16:54 +02:00
LouisLam
ebf362754c Merge branch 'master' into clear-monitor-data 2021-09-03 14:56:43 +08:00
Louis Lam
f84135ca67 Merge pull request #322 from chakflying/patch-6
Fix: Fix Notification "Test" btn styling
2021-09-03 14:34:39 +08:00
LouisLam
80eca886ce Merge branch 'add-serbian-latin'
# Conflicts:
#	src/main.js
#	src/pages/Settings.vue
2021-09-03 14:32:12 +08:00
Louis Lam
274a9050c0 Merge pull request #321 from dusansimic/add-serbian-cyrillic
Add Serbian Cyrillic locale
2021-09-03 14:00:43 +08:00
Louis Lam
1f4ad938b1 Merge pull request #323 from xinac721/master
Update Chinese Translation(更新简体中文语言翻译)
2021-09-03 13:55:30 +08:00
新逸Cary
312aedf391 Update Chinese Translation(更新简体中文语言翻译) 2021-09-03 13:33:26 +08:00
Louis Lam
4f28bfbde3 Merge pull request #309 from Saibamen/updateDependencies
Update dependencies
2021-09-03 12:56:55 +08:00
Louis Lam
ee76ab4ec2 Merge pull request #317 from AtaxyaNetwork/master
change translation FR
2021-09-03 12:56:11 +08:00
Nelson Chan
18616ee590 Fix: Fix Notification "Test" btn styling 2021-09-03 12:05:49 +08:00
Dušan Simić
19a4d570ec Fix word capitalization 2021-09-03 02:24:31 +02:00
Dušan Simić
79fda8f442 Add Serbian Latin locale 2021-09-03 02:20:01 +02:00
Dušan Simić
53a14cf4f5 Add Serbian Cyrilic locale 2021-09-03 02:06:26 +02:00
cecile
2241d8817f change translation FR 2021-09-02 23:41:47 +02:00
Louis Lam
3831dfe0b9 Update README.md 2021-09-03 02:55:36 +08:00
Louis Lam
fdde862549 Merge pull request #316 from aictur/feature/es-ES
Add spanish language and update Readme
2021-09-02 23:00:36 +08:00
LouisLam
e31be8caf5 demo mode 2021-09-02 22:52:20 +08:00
LouisLam
60f2f08cea add demo db 2021-09-02 22:39:04 +08:00
LouisLam
b1647a310e add demo db 2021-09-02 22:37:51 +08:00
Victor M. Vicente Cuevas
23f1a73fc8 Add language to src/main and update README 2021-09-02 16:31:45 +02:00
Victor M. Vicente Cuevas
d2bf2a551d Add spanish language and update Readme 2021-09-02 16:23:07 +02:00
Ponkhy
7d70c4d8cd Code optimizations 2021-09-02 16:13:31 +02:00
Domenic Horner
532ad3044c Add space to pushbullet and lunasea notifications
Start changes regarding standardization of notification messages
2021-09-02 21:55:25 +08:00
LouisLam
f23ecef636 add missing cert parameters 2021-09-02 21:16:04 +08:00
LouisLam
51cf2ff6f9 add missing cert parameters 2021-09-02 21:13:59 +08:00
LouisLam
b30b1d3a52 create data dir before copy 2021-09-02 21:11:20 +08:00
LouisLam
582e14098d create data dir before copy 2021-09-02 21:10:18 +08:00
LouisLam
6e3e2fc85c fix db path 2021-09-02 21:08:00 +08:00
LouisLam
b604807cfe create data dir if not exists 2021-09-02 20:42:55 +08:00
LouisLam
3ee13bddd1 dash style for args 2021-09-02 20:36:52 +08:00
LouisLam
c74986647e allow changing data dir 2021-09-02 20:27:18 +08:00
LouisLam
dac410c850 Merge remote-tracking branch 'origin/master' 2021-09-02 20:20:47 +08:00
LouisLam
b88b357b55 add support for https 2021-09-02 20:18:27 +08:00
Louis Lam
9a5cd5172b Merge pull request #314 from xinac721/master
Chinese Translation (from zh-CN.js)
2021-09-02 20:14:05 +08:00
新逸Cary
941788db49 Chinese Translation (from zh-CN.js) 2021-09-02 18:33:09 +08:00
Jelle Posthuma
99725aabe7 Add Dutch/Nederlands language (nl_NL) 2021-09-02 11:10:54 +02:00
Ponkhy
2dd392e609 Added uptime kuma version to backup file 2021-09-02 10:15:25 +02:00
Louis Lam
9d41da4aa2 Merge pull request #311 from xinac721/master
Chinese Translation (from zh-CN.js)
2021-09-02 15:59:06 +08:00
新逸Cary
a0f372e946 Chinese Translation (from zh-CN.js) 2021-09-02 15:34:46 +08:00
新逸Cary
877ad1438f Merge branch 'louislam:master' into master 2021-09-02 15:25:09 +08:00
LouisLam
9116654a33 update language files and run eslint on these 2021-09-02 15:21:46 +08:00
新逸Cary
dbc70bc5ed Merge pull request #1 from louislam/master
update
2021-09-02 14:33:34 +08:00
Louis Lam
a29b65e801 Merge pull request #308 from DX37/translation-ru
Add Russian translation
2021-09-02 12:56:12 +08:00
Louis Lam
bd9568ce5b Merge pull request #310 from Saibamen/more_i18n
Make `Resp. Time (ms)` and `N/A` i18n
2021-09-02 12:55:11 +08:00
Ponkhy
c13cc62d3d Update server/server.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-09-01 21:32:33 +02:00
Adam Stachowicz
7a109689d9 Make Resp. Time (ms) and N/A i18n 2021-09-01 21:17:50 +02:00
Adam Stachowicz
e7929f461d Update dependencies 2021-09-01 20:53:12 +02:00
DX37
a2cf7f394e Add Russian translation 2021-09-02 01:37:01 +07:00
Louis Lam
e1f378ee6c Update README.md 2021-09-02 02:11:44 +08:00
LouisLam
eeb00a5511 fix data type 2021-09-02 01:56:02 +08:00
LouisLam
8e1e4b9204 override file-selector-button hover color 2021-09-02 01:51:51 +08:00
LouisLam
66f9ad5754 Merge branch 'master' into import-export 2021-09-02 01:35:42 +08:00
Louis Lam
129dc3324b Merge pull request #307 from dhfhfk/master
Added Korean Language
2021-09-02 01:17:54 +08:00
Louis Lam
268d2e2353 Merge branch 'master' into master 2021-09-02 01:17:48 +08:00
Louis Lam
7d2cf0ee57 Merge pull request #304 from LeviSnoot/master
Added Swedish Language
2021-09-02 01:17:10 +08:00
오로라
2d408732db Update main.js
Prevent conflict with #304 (Added Swedish Language)
2021-09-02 01:01:18 +09:00
dhfhfk
0cc5053f14 Update ko-KR.js 2021-09-02 00:35:50 +09:00
dhfhfk
1c4e5b79be Create ko-KR.js 2021-09-02 00:30:08 +09:00
dhfhfk
4aae402b36 Update main.js 2021-09-02 00:29:01 +09:00
Ponkhy
b604910bbb Merge branch 'master' into clear-monitor-data 2021-09-01 17:17:40 +02:00
Ponkhy
2f6c5963c5 Added import and export function 2021-09-01 17:09:32 +02:00
Levi
dce2ba8f9f Update sv-SE.js 2021-09-01 16:41:51 +02:00
Levi
ed5c75282c Update main.js 2021-09-01 16:38:05 +02:00
Levi
00ac560bd6 Create sv-SE.js 2021-09-01 16:30:08 +02:00
Louis Lam
8ea4dec5a0 Merge pull request #303 from Saibamen/patch-1
Update translation docs
2021-09-01 22:08:44 +08:00
Adam Stachowicz
3006d13aee Update translation docs 2021-09-01 15:37:56 +02:00
LouisLam
c7e6cb9f37 update language files 2021-09-01 20:10:54 +08:00
LouisLam
9b82bb248e Merge branch 'master' into kometchtech_patch-1
# Conflicts:
#	src/main.js
2021-09-01 19:46:44 +08:00
Louis Lam
e55cf65f28 Merge pull request #291 from Ponkhy/master
Added translation to Setup.vue
2021-09-01 19:45:20 +08:00
Louis Lam
f24002838c Merge branch 'master' into master 2021-09-01 19:45:06 +08:00
Louis Lam
b4fd4f7d90 Merge pull request #301 from Lrss/master
Added Danish language
2021-09-01 19:44:01 +08:00
kometchtech
3a3f1762ac Update ja.js
* Perform translation for added keys.
2021-09-01 19:04:35 +09:00
Lars Sørensen
6376d4eb92 Translated to Danish 2021-09-01 11:51:22 +02:00
LouisLam
e37cf9b1a7 add missing and add Japanese to the list 2021-09-01 17:32:41 +08:00
LouisLam
3b0191210b Merge branch 'master' into kometchtech_patch-1 2021-09-01 17:28:49 +08:00
LouisLam
923d325b44 add language file preparation script 2021-09-01 17:10:12 +08:00
LouisLam
ad38e61c26 add language file preparation script 2021-09-01 17:08:27 +08:00
LouisLam
22095c09b1 add translation guide 2021-09-01 15:49:35 +08:00
LouisLam
a5e62141d5 update to 1.5.2 2021-09-01 15:04:31 +08:00
LouisLam
e4b76717be revert back to node-sqlite3 2021-09-01 15:02:04 +08:00
LouisLam
bc70ecfba7 fix install script 2021-09-01 14:56:19 +08:00
LouisLam
f1238ab762 update to 1.5.1 2021-09-01 14:41:06 +08:00
LouisLam
cd1a3a2fb9 revert back to node-sqlite3, as better-sqlite3 causes a lot of installation problems 2021-09-01 14:33:00 +08:00
kometchtech
25db162721 Create ja.js
* Created a Japanese language file.
2021-09-01 13:23:44 +09:00
Ponkhy
7b92166d18 Added clear all db statistics function 2021-09-01 00:36:24 +02:00
Ponkhy
1341d220ed Merge branch 'louislam:master' into clear-monitor-data 2021-08-31 23:22:45 +02:00
LouisLam
3e7bb355fd update to 1.5.0 2021-08-31 23:10:12 +08:00
LouisLam
697fa6bdfd fix discord notification appended port unexpectedly 2021-08-31 22:15:02 +08:00
LouisLam
527e0c3444 raise the ping timeout from 2s to 10s (avoid #294) 2021-08-31 22:14:33 +08:00
LouisLam
a41534ca60 no declare vars with comma, one line only one statement 2021-08-31 22:08:05 +08:00
LouisLam
fa549cb80e fix npm7 broken dependencies 2021-08-31 20:36:17 +08:00
LouisLam
0127d5102e Merge remote-tracking branch 'origin/master' 2021-08-31 20:03:24 +08:00
LouisLam
ec731d174d Merge branch 'MichelBaie_master' 2021-08-31 20:02:39 +08:00
LouisLam
0d65918a6a change bcrypt to bcryptjs, use my own prebuilt better-sqlite3, supports more prebuilt 2021-08-31 19:56:44 +08:00
Louis Lam
21db31bb30 Update README.md 2021-08-30 21:56:33 +08:00
Louis Lam
3ee0addb1f Merge pull request #281 from MichelBaie/master
Traduction pour le language France (FR Translation)
2021-08-30 20:09:55 +08:00
LouisLam
8c5d1945be add fr to the list 2021-08-30 19:46:10 +08:00
Tristan
bb799163e8 French Translation (from zh-HK.js) 2021-08-30 11:11:22 +02:00
LouisLam
bf29f28726 send stats only if there is at least one client in the room 2021-08-30 14:55:33 +08:00
LouisLam
22db9c9b8a Merge remote-tracking branch 'origin/master' into scroll-into-view 2021-08-30 14:00:34 +08:00
LouisLam
96ff70faaa reduce shifting when click the monitor list item (still shift in some cases, but acceptable) 2021-08-30 13:09:24 +08:00
henrygd
2776f942ab fix monitor list jumping to top on route change 2021-08-29 15:28:43 -07:00
Ponkhy
14b9afb400 Added translation to Setup.vue 2021-08-29 23:07:58 +02:00
LouisLam
3ad736692f improve monitor list 2021-08-30 02:22:49 +08:00
Ponkhy
1952e34110 Added the possibility to clear monitor data 2021-08-29 18:47:01 +02:00
LouisLam
e644a1e36f Merge branch 'master' into scroll-into-view 2021-08-30 00:46:26 +08:00
Louis Lam
78b7e36a38 Update domain name 2021-08-29 19:21:13 +08:00
Louis Lam
f30232c35d Create CNAME 2021-08-29 19:15:40 +08:00
Louis Lam
257a4ee994 Update patch7.sql 2021-08-29 18:58:05 +08:00
Louis Lam
fd1ba46d3d Merge pull request #287 from Ponkhy/dns-monitor
[Before 1.5.0] Show latest dns result in Details.vue
2021-08-29 11:17:35 +08:00
LouisLam
ada6606217 move the new sql to patch8.sql 2021-08-29 11:16:06 +08:00
Ponkhy
dd877cfc70 Added translation to pause monitor confirmation 2021-08-29 04:03:55 +02:00
Ponkhy
93edb8817d More uniform look 2021-08-29 03:57:26 +02:00
Ponkhy
858affa808 Removed useless database query 2021-08-28 21:29:24 +02:00
Louis Lam
2bb182b2b4 Create FUNDING.yml 2021-08-29 03:28:40 +08:00
Ponkhy
303adbf9b1 Show latest dns result in Details.vue 2021-08-28 21:20:25 +02:00
Louis Lam
712da02324 Merge pull request #286 from arnishb/fix-readme
fix-readme
2021-08-28 19:32:01 +08:00
Arnish Baruah
27a4dbb722 fix-readme 2021-08-28 16:40:32 +05:30
Louis Lam
0e676060f2 Update CONTRIBUTING.md 2021-08-28 13:46:47 +08:00
Louis Lam
a14c40f9bb move k8s to advanced installation section 2021-08-28 12:33:10 +08:00
Louis Lam
309fbfa094 Update README.md 2021-08-28 12:32:35 +08:00
Louis Lam
46dcd31142 Update README.md 2021-08-28 12:29:57 +08:00
LouisLam
59e9315647 show dns type and hostname in Details.vue 2021-08-28 11:48:34 +08:00
LouisLam
91e82bd12c set default value for dns resolve type and code refactor 2021-08-28 11:46:26 +08:00
LouisLam
d4dd650bfe translate for zh-hk 2021-08-28 11:20:02 +08:00
Louis Lam
354ee1a58c Merge pull request #283 from Ponkhy/german-language
Added German language for DNS Monitor
2021-08-28 11:10:39 +08:00
henrygd
2901a38628 add position: sticky to monitor details 2021-08-27 15:28:01 -07:00
Ponkhy
6464207f4b Added German language for DNS Monitor 2021-08-27 18:41:58 +02:00
Louis Lam
7652b4849a Merge pull request #238 from Ponkhy/dns-monitor
Added DNS Monitor Type
2021-08-28 00:21:10 +08:00
LouisLam
03b4086372 add CAA test and remove some files added by mistake 2021-08-27 23:57:42 +08:00
Ponkhy
acd5cf63fd Removed wrong PTR answer 2021-08-27 17:41:22 +02:00
Ponkhy
177af2d588 Added more dns types to simple-dns-server 2021-08-27 17:32:50 +02:00
Tristan
b46b214175 Traduction pour le language France (FR Translation) 2021-08-27 11:12:22 +02:00
Louis Lam
d2f0a15076 Merge pull request #264 from antiseptikk/master
feat: add rocket.chat notification
2021-08-26 23:34:07 +08:00
LouisLam
2d50d24276 more translation for zh-HK 2021-08-26 23:32:25 +08:00
Louis Lam
34b6976a03 Merge pull request #269 from Ponkhy/german-language
Added German language and new translations
2021-08-26 23:14:05 +08:00
Louis Lam
d60c11e845 Merge pull request #260 from Thiesjoo/discord-notification
Discord notification updates
2021-08-26 23:03:32 +08:00
LouisLam
890aea8756 Merge branch 'duzun_patch-1' 2021-08-26 23:02:10 +08:00
LouisLam
c55f2b93f7 change to pm2 start server/server.js directly due to (#273) 2021-08-26 22:55:44 +08:00
Louis Lam
d4cf838af7 Merge pull request #273 from duzun/patch-1
Dockerfile: Avoid keeping npm in RAM
2021-08-26 22:45:59 +08:00
LouisLam
508586fcfd add codesandbox config for demo 2021-08-26 20:36:58 +08:00
Dumitru Uzun
feb0feda76 Dockerfile: Avoid keeping npm in RAM
By running node directly, we save some RAM. In my case npm consumes 300MB and does nothing, just waits for the node process to exit.
On small VPSes 300MB is a lot!
2021-08-26 12:53:57 +03:00
Ponkhy
34ca5c5c15 Merge branch 'master' of https://github.com/louislam/uptime-kuma 2021-08-26 02:43:35 +02:00
Ponkhy
2b8c5e2e65 Added German Language 2021-08-26 02:43:26 +02:00
Thomas Ferney
44d9967cfb feat: add rocket.chat notification 2021-08-25 21:01:29 +02:00
LouisLam
8318c2e8ff add a simple dns server for testing, and disable ipRegex for dev only (need to input port) 2021-08-26 01:50:27 +08:00
LouisLam
46ac753c46 Merge branch 'master' into dns-monitor 2021-08-26 01:05:46 +08:00
Thies
72740ba477 Update the styling to better match existing styles
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-08-25 14:08:41 +02:00
Thies Nieborg
5d438ca2b6 Discord notification URL now also represents non http services 2021-08-25 13:07:52 +02:00
Ponkhy
02a12e68b8 Used ALTER TABLE instead of rebuilding the table 2021-08-25 12:45:47 +02:00
Louis Lam
a7cd70f7de Merge pull request #253 from chakflying/chart-fix
Fix: More Chart improvements
2021-08-25 17:35:25 +08:00
Louis Lam
26db0471da Merge pull request #254 from RasHas/master
added mattermost notification support
2021-08-25 17:06:07 +08:00
Ponkhy
d313a06d5c Optimizations for output handling 2021-08-25 09:31:42 +02:00
LouisLam
4c1f2f85f8 manual fix stylelint 2021-08-25 12:25:19 +08:00
Rashad
23851ef539 added mattermost notification support 2021-08-24 21:19:21 +03:00
LouisLam
397fd12081 remove unused import 2021-08-25 01:26:10 +08:00
LouisLam
564bc96735 eslint: camelcase rule do not check properties, because it could be database field name 2021-08-25 01:25:57 +08:00
LouisLam
682e4d45e2 eslint for notification.js 2021-08-25 01:21:06 +08:00
LouisLam
f96d792fa1 fix patch database using better-sqlite3 2021-08-25 01:11:19 +08:00
Nelson Chan
2d20634738 Chore: Add comments, improve performance & styling 2021-08-25 01:03:20 +08:00
Nelson Chan
9442c3fa05 Fix: Fix chart bars to be full width 2021-08-25 01:02:58 +08:00
LouisLam
302d2665d2 run stylelint for the project 2021-08-24 23:38:25 +08:00
LouisLam
2b68be52b0 Merge branch 'clean-mobile-table' 2021-08-24 23:22:33 +08:00
LouisLam
393c4fb1a7 update stylelint 2021-08-24 23:22:04 +08:00
Louis Lam
13f6c79e79 Merge pull request #236 from Ponkhy/clean-mobile-table
Added clean monitor table for smaller screens
2021-08-24 23:21:22 +08:00
LouisLam
ca69d06e0d update border color 2021-08-24 22:27:26 +08:00
LouisLam
d8d428907e Merge branch 'master' into clean-mobile-table 2021-08-24 21:55:16 +08:00
Ponkhy
a17c14ea1c Centered title, badge and datetime 2021-08-24 13:24:35 +02:00
LouisLam
28a51d806b translate to Traditional Chinese (Hong Kong) 2021-08-24 18:26:44 +08:00
Ponkhy
6eead46fa6 Merge branch 'dns-monitor' of https://github.com/Ponkhy/uptime-kuma into dns-monitor 2021-08-24 11:47:24 +02:00
Ponkhy
44d9fa63f0 Adjusted the output for A and AAAA records 2021-08-24 11:47:12 +02:00
LouisLam
dd4c00eed3 add vue i18n 2021-08-24 16:44:58 +08:00
LouisLam
752ac05149 Merge remote-tracking branch 'origin/master' 2021-08-24 15:46:48 +08:00
LouisLam
14652c9b5f Remove unused variables 2021-08-24 15:46:22 +08:00
Louis Lam
054186370e add source of ipRegex 2021-08-24 15:00:30 +08:00
Louis Lam
40d80dfdfd clarify pull request rule 2021-08-24 14:42:35 +08:00
Louis Lam
b9684e32d3 Update CONTRIBUTING.md 2021-08-24 14:06:23 +08:00
LouisLam
8e726da82a eslint: add camelcase rule 2021-08-24 13:58:52 +08:00
Louis Lam
df41c40cc2 add mit license badge in readme 2021-08-24 13:38:21 +08:00
Ponkhy
5dc834794c Row spacing reduced and badge centered 2021-08-24 03:14:33 +02:00
LouisLam
36ace3e56c naming convention and wrap all styles inside .table-shadow-box to avoid unexpected style in the future 2021-08-24 02:02:38 +08:00
LouisLam
3f12afce28 Merge branch 'master' into clean-mobile-table 2021-08-24 01:53:13 +08:00
Louis Lam
833b4733a8 Merge pull request #246 from chakflying/patch-4
Proj: Add npm lint commands
2021-08-24 01:15:49 +08:00
Nelson Chan
066b67dfce Proj: Add lint commands 2021-08-23 23:54:15 +08:00
Ponkhy
b2041cb36b Fixed ESLint Errors 2021-08-23 16:30:11 +02:00
LouisLam
aa2233eb2d log notification error 2021-08-23 20:57:42 +08:00
Ponkhy
e5981b10ce Replaced var with let and removed re-declaration 2021-08-23 13:08:22 +02:00
LouisLam
46cb955172 afterLogin change to non blocking 2021-08-23 18:52:55 +08:00
LouisLam
50f300dd28 heartbeat interval change to use setTimeout() 2021-08-23 18:52:24 +08:00
LouisLam
2f50fc4c00 plan to switch to better-sqlite3, drop node-sqlite3 2021-08-23 17:27:03 +08:00
LouisLam
a02edf1b4f fix detail page empty if the monitor list is not yet ready 2021-08-23 16:59:27 +08:00
LouisLam
a61a65e5ae Merge remote-tracking branch 'origin/master' 2021-08-23 15:50:00 +08:00
Louis Lam
ffaaeae794 Merge pull request #239 from chakflying/fix-ts
Fix: fix typescript errors
2021-08-23 15:49:53 +08:00
Nelson Chan
ee3bf2961c Fix: fix typescript errors 2021-08-23 11:33:24 +08:00
Ponkhy
ce79f8bfc7 CSS optimizations 2021-08-23 01:22:55 +02:00
Ponkhy
c79be19ec3 Added DNS Monitor Type 2021-08-23 00:05:48 +02:00
LouisLam
b892a92fc8 retry if acquire error 2021-08-22 23:35:24 +08:00
Louis Lam
2912ca1248 Merge pull request #237 from Ponkhy/master
Added animation for list page change
2021-08-22 15:11:51 +08:00
LouisLam
2bff1ebe0f update to 1.3.2 2021-08-22 14:44:08 +08:00
LouisLam
ec0dbf3cbe probably still memory leak over time, not sure what happen, change back to singal pool. 2021-08-22 14:43:26 +08:00
LouisLam
210a0d414c fix check update interval too short 2021-08-22 14:07:56 +08:00
Ponkhy
ca38cc91e9 Use bootstrap integraded class instead of new ones 2021-08-22 03:15:25 +02:00
Ponkhy
c90d17bd66 Added animation for list page change 2021-08-21 23:01:43 +02:00
Ponkhy
dbd3f48f68 Added clean monitor table for smaller screens 2021-08-21 21:12:44 +02:00
LouisLam
49ba5fb1b2 update to 1.3.1 2021-08-22 02:13:00 +08:00
LouisLam
d27789a8ae Revert "update to 1.3.1"
This reverts commit b53582a812.
2021-08-22 02:11:40 +08:00
LouisLam
b53582a812 update to 1.3.1 2021-08-22 02:09:16 +08:00
LouisLam
05680472a7 fix high memory usage 2021-08-22 02:07:10 +08:00
LouisLam
ca3b0a0f19 fix setInterval 2021-08-22 00:39:29 +08:00
LouisLam
4571a9b8c1 check update 2021-08-21 19:50:22 +08:00
LouisLam
362eabab8d allow empty block for catch 2021-08-21 19:45:29 +08:00
Louis Lam
a22d0f6951 Merge pull request #231 from ClemontX/master
added K8s-Deployment and edited README
2021-08-21 02:00:33 +08:00
LouisLam
b1168d4cdb update to 1.3.0 2021-08-21 01:44:43 +08:00
Carl Sander
6fcc2253ec changed domain names to example.com 2021-08-20 06:21:59 +00:00
LouisLam
f21937b197 add animation for page change 2021-08-20 02:37:59 +08:00
Louis Lam
1e7623c459 Update README.md 2021-08-19 21:22:16 +08:00
Carl Sander
22047fe932 removed doubled names of ressources 2021-08-19 11:50:05 +00:00
LouisLam
209e44c2e1 prevent all monitors making requests at the same moment when start the server 2021-08-19 18:41:31 +08:00
LouisLam
30b8d3d0ab prevent all monitors making requests at the same moment when start the server 2021-08-19 18:33:52 +08:00
LouisLam
64498163e1 add /list for mobile 2021-08-19 18:12:52 +08:00
LouisLam
4f70a70dda splite the left monitor list into a component 2021-08-19 18:05:14 +08:00
Carl Sander
5b5a32967c fixed README 2021-08-19 09:55:43 +00:00
Carl Sander
ae8b5eea5a Merge branch 'master' into master 2021-08-19 11:50:27 +02:00
LouisLam
b761aaffdf Merge remote-tracking branch 'origin/master' 2021-08-19 17:49:27 +08:00
LouisLam
7ffdb2eb80 also backup sqlite shm, val file 2021-08-19 17:49:19 +08:00
Louis Lam
2d36f4cd4a Create SECURITY.md 2021-08-19 17:32:57 +08:00
Louis Lam
2339405f90 Update README.md 2021-08-19 14:13:30 +08:00
LouisLam
8f5e5ad944 install.sh - check docker is running 2021-08-19 12:47:11 +08:00
LouisLam
575c3ee182 install.sh - check docker is running 2021-08-19 12:39:51 +08:00
LouisLam
c9aa110f6c install.sh - check docker is running 2021-08-19 12:15:07 +08:00
LouisLam
bb0af35d47 wip: implementing install script 2021-08-19 02:38:45 +08:00
LouisLam
61944d642e wip: implementing install script 2021-08-19 02:04:49 +08:00
Carl Dominik Sander
21640e1bbe changed to tag 1 2021-08-18 17:58:17 +02:00
Louis Lam
de4515ea6e Merge pull request #230 from chakflying/patch-3
Fix: Improve chart styling on mobile
2021-08-18 23:21:18 +08:00
Carl Dominik Sander
b41799f801 reolved suggestions from @srgvg and @louislam 2021-08-18 16:09:06 +02:00
Nelson Chan
d8bcfcaaa2 Fix: Reduce chart padding on mobile 2021-08-18 17:04:13 +08:00
Nelson Chan
cf5168a4e6 Fix: Resize chart on screen breakpoints 2021-08-18 17:03:25 +08:00
Carl Sander
60b0ee2959 added K8s-Deployment and edited README 2021-08-18 08:38:05 +00:00
LouisLam
f1e5e53e8f Merge branch 'patch-2' 2021-08-18 15:32:43 +08:00
LouisLam
432388a905 Merge branch 'Ponkhy_master' 2021-08-18 15:09:56 +08:00
LouisLam
746c1b6acc Merge remote-tracking branch 'origin/master' 2021-08-18 14:55:27 +08:00
LouisLam
269ac2410b install.sh add supports for CentOS 2021-08-18 14:55:03 +08:00
Nelson Chan
f72cdcc663 Feat: Add time to beat tooltip, misc. fixes 2021-08-18 11:40:20 +08:00
Louis Lam
6b3fbcd1e7 Merge pull request #228 from Ismaaa/patch-1
Fix typo in README.md
2021-08-18 01:06:36 +08:00
Ismail D
8a48f5dd71 Fix typo in README.md 2021-08-17 17:59:34 +02:00
LouisLam
d218661f3d wip: implementing install script 2021-08-17 23:08:35 +08:00
Ponkhy
77369bd002 Fixed invisible heartbeat bar after page switch 2021-08-17 15:40:22 +02:00
Louis Lam
29a89df524 Merge pull request #227 from Ponkhy/line-messenger
Added Line Messenger Notification Service
2021-08-17 20:25:01 +08:00
Louis Lam
e257fa7b2d Merge pull request #221 from chakflying/patch-1
Fix: Improve Chart axis, use 24Hr format
2021-08-17 20:05:48 +08:00
LouisLam
6980c38a6c fix #226 a workaround fix similar to https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 2021-08-17 20:00:31 +08:00
LouisLam
8d57df7256 fix #226 a workaround fix similar to https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 2021-08-17 19:58:09 +08:00
Ponkhy
64501bf065 Added Line Messenger Notification Service 2021-08-17 13:41:36 +02:00
LouisLam
440c178403 change sqlite to WAL mode 2021-08-17 18:18:41 +08:00
LouisLam
c9c51e47e1 add some comments 2021-08-17 16:43:59 +08:00
LouisLam
5e52f230b1 create datetime mixin 2021-08-17 16:41:12 +08:00
LouisLam
61e758d872 disable pool for sqlite, re-use a connection to improve the performance. 2021-08-17 15:59:23 +08:00
LouisLam
86826fb826 Merge remote-tracking branch 'origin/master' 2021-08-17 15:32:55 +08:00
LouisLam
7a32e5e6ff catch rejection error globally 2021-08-17 15:32:34 +08:00
Louis Lam
610f2f9c47 Merge pull request #225 from AverageHumanoid/master
Add ping support in FreeBSD
2021-08-17 14:03:28 +08:00
AverageHumanoid
01e9c76a6f Use ping in FreeBSD 2021-08-16 19:48:37 -07:00
Ponkhy
5927c2703f Merge branch 'louislam:master' into master 2021-08-17 02:55:41 +02:00
LouisLam
316db89b9a Merge remote-tracking branch 'origin/master' 2021-08-17 02:09:56 +08:00
LouisLam
eed6d3e847 add more query log for dev env 2021-08-17 02:09:40 +08:00
Louis Lam
2a62f6daae Update ask-for-help.md 2021-08-17 01:32:42 +08:00
Louis Lam
e09c296410 Update bug_report.md 2021-08-17 01:32:21 +08:00
Louis Lam
d7f660ec57 Update bug_report.md 2021-08-17 01:29:34 +08:00
LouisLam
798f39acf0 Merge remote-tracking branch 'origin/master' 2021-08-17 01:26:35 +08:00
LouisLam
31d5b4fd3d do not pass smtp user/pass to nodemailer if both are empty 2021-08-17 01:26:21 +08:00
LouisLam
fc76c2836b increase the query timeout 2021-08-17 01:22:22 +08:00
Nelson Chan
0b30bfff87 Fix: Improve Chart axis, use 24Hr format 2021-08-16 23:58:02 +08:00
Ponkhy
72f0724b9a Update src/mixins/theme.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-08-16 17:14:21 +02:00
Ponkhy
35176a614f Update src/mixins/theme.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-08-16 17:14:13 +02:00
Ponkhy
8e883c9c6a Update src/mixins/theme.js
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-08-16 17:14:05 +02:00
Louis Lam
2f89ee4937 Update README.md 2021-08-16 21:31:05 +08:00
LouisLam
5d0b6190c3 update to 1.2.0 2021-08-16 20:40:28 +08:00
LouisLam
cb85905c33 minor 2021-08-16 20:40:16 +08:00
Ponkhy
233c5661af Added user choice heartbeat bar 2021-08-15 20:46:21 +02:00
Ponkhy
91d4c15b4d Merge branch 'louislam:master' into master 2021-08-15 20:28:30 +02:00
LouisLam
981ed5f29f Merge remote-tracking branch 'origin/master' 2021-08-16 01:42:54 +08:00
LouisLam
0b45694f2f update all dependencies 2021-08-16 01:42:39 +08:00
Louis Lam
60531d0b15 Update README.md 2021-08-16 01:38:37 +08:00
Louis Lam
a3de63ac3c Update README.md 2021-08-16 01:29:47 +08:00
Louis Lam
80eadcb236 Merge pull request #214 from ChrisTheBaron/pushbullet
Add Pushbullet notification service
2021-08-16 01:06:27 +08:00
LouisLam
7e5a8c896b Merge remote-tracking branch 'chakflying/ping-graph' 2021-08-16 01:00:18 +08:00
Chris Taylor
efe75bde75 Add Pushbullet notification service 2021-08-13 21:18:43 +01:00
Louis Lam
af34e861c5 Merge pull request #200 from proffalken/feature/187_add_cert_checks_to_prometheus
Add certificate monitoring to the Prometheus handler
2021-08-13 00:26:58 +08:00
Louis Lam
2ae2022e62 Merge pull request #211 from AlexandreGagner/master
Add Octopush Notification Service
2021-08-13 00:26:35 +08:00
LouisLam
37f1d60f82 also change meta tag theme-color 2021-08-13 00:23:40 +08:00
LouisLam
d39b43dacc fix require problem 2021-08-13 00:13:46 +08:00
Louis Lam
7ca80fc086 fix auto theme 2021-08-12 22:17:20 +08:00
Alexandre Gagner
eb34dc6cc2 Update notification.js
Fix remove non ascii char from msg
2021-08-12 00:58:51 +02:00
Alexandre Gagner
ed93aae1c2 add octopush notification service 2021-08-12 00:15:53 +02:00
Ponkhy
e1a38f64f8 Merge branch 'louislam:master' into master 2021-08-11 21:19:33 +02:00
LouisLam
6a8ccf627a add version to user agent 2021-08-12 01:31:07 +08:00
Nelson Chan
8f150aaeb9 Feat: Use Async Component 2021-08-12 00:47:58 +08:00
Nelson Chan
6ed1d8cb2f Feat: Use selective import, improve tooltip UI 2021-08-12 00:31:21 +08:00
Nelson Chan
71bec74081 Feat: Add down-ed bars, improve UI 2021-08-11 23:40:56 +08:00
Nelson Chan
2bd735035c Misc: Show graph by default 2021-08-11 23:40:56 +08:00
Nelson Chan
48c6d8f19f Feat: Display recent ping chart 2021-08-11 23:40:51 +08:00
LouisLam
2d176a38af Merge remote-tracking branch 'origin/master' 2021-08-11 23:38:48 +08:00
LouisLam
b14f63491d timeout change to 80% of its interval 2021-08-11 23:12:38 +08:00
LouisLam
24b87fcd5a update vue to 3.2.1 2021-08-11 22:41:33 +08:00
Ponkhy
45c162583b Added more space over the badge on mobile screens 2021-08-11 11:16:53 +02:00
LouisLam
365ea0a189 add batsh 2021-08-11 14:52:25 +08:00
Louis Lam
2461f5084e Merge pull request #205 from Ponkhy/master
Fixed function buttons for smaller screens
2021-08-11 00:50:43 +08:00
Ponkhy
1d0b332b42 Fixed function buttons for smaller screens 2021-08-10 18:29:47 +02:00
LouisLam
d5149f90b4 fix ping 2021-08-10 22:00:29 +08:00
LouisLam
e0ae9a9e73 improve space-before-function-paren 2021-08-10 21:59:15 +08:00
LouisLam
3227a2660b log undefined ping 2021-08-10 21:47:14 +08:00
LouisLam
764160f38c add eslint: space-before-function-paren 2021-08-10 21:44:29 +08:00
LouisLam
70e7945a66 fix possible race condition 2021-08-10 21:37:51 +08:00
LouisLam
b413427a37 graceful shutdown when listen error 2021-08-10 21:28:54 +08:00
LouisLam
debcac4924 run eslint 2021-08-10 14:24:05 +01:00
Matthew Macdonald-Wallace
268dd33792 Add TLS Info to Prometheus metric output 2021-08-10 14:24:05 +01:00
LouisLam
692a11e51e pass tls info to prometheus.update 2021-08-10 14:24:05 +01:00
Matthew Macdonald-Wallace
5eb4f55dfd Add the new gauges to the prometheus handler 2021-08-10 14:24:05 +01:00
LouisLam
e7cc5340e5 ping ipv6 for macos 2021-08-10 21:07:11 +08:00
LouisLam
4d4d504d6e retry ping domain with ipv6, if domain is not found 2021-08-10 21:03:14 +08:00
LouisLam
2a4695a774 add -6 to ping cmd if ipv6 address 2021-08-10 20:39:58 +08:00
LouisLam
f089bf73c3 Merge remote-tracking branch 'origin/master' 2021-08-10 20:23:29 +08:00
LouisLam
f099e4270d change to Accept: */* to better support all websites 2021-08-10 20:23:15 +08:00
Louis Lam
81636c7b44 Delete reviewdog.yml 2021-08-10 20:03:25 +08:00
Louis Lam
98fa995d3f Update reviewdog.yml 2021-08-10 19:19:55 +08:00
Louis Lam
42d24258cf Delete app.json 2021-08-10 18:41:38 +08:00
Louis Lam
3f56167198 Update reviewdog.yml 2021-08-10 17:56:30 +08:00
Louis Lam
5163e16482 Update reviewdog.yml 2021-08-10 17:36:45 +08:00
LouisLam
d93f6e2716 server.listen bind to ipv6 too 2021-08-10 16:45:37 +08:00
LouisLam
d6fad7f1ef server.listen bind to ipv6 too 2021-08-10 16:36:21 +08:00
LouisLam
5512b15162 add better token for github-pr-review for reviewdog 2021-08-10 15:39:39 +08:00
LouisLam
8979311653 Merge remote-tracking branch 'origin/master' 2021-08-10 15:04:15 +08:00
LouisLam
4f058c5b47 do not fix height for h1 2021-08-10 15:04:01 +08:00
LouisLam
9ba1743900 split mobile mixin from socket mixin 2021-08-10 15:02:46 +08:00
Louis Lam
1e4f9c7e15 Update README.md 2021-08-10 13:10:03 +08:00
Louis Lam
974672f7c1 Delete deploy.template.yaml 2021-08-10 13:09:36 +08:00
Louis Lam
01ac6d54be Merge pull request #199 from chakflying/patch-1
Fix: unify styling of theme switch btn
2021-08-10 12:50:50 +08:00
Nelson Chan
113899e278 Fix: unify styling of theme switch with UI 2021-08-10 12:20:06 +08:00
LouisLam
d1d000bd74 remove red circle around the btn-close while focus 2021-08-10 00:16:13 +08:00
Louis Lam
ef4677a640 Merge pull request #194 from Ponkhy/master
Fixed Close Button Color in Dark Mode
2021-08-10 00:04:25 +08:00
Ponkhy
e39c46ff9b Fixed Close Button Color in Dark Mode 2021-08-09 17:56:44 +02:00
Louis Lam
0e46ce42d1 Update README.md 2021-08-09 22:31:32 +08:00
LouisLam
efc9a254f4 update to 1.1.0 2021-08-09 21:03:30 +08:00
LouisLam
116d803592 minor 2021-08-09 21:03:22 +08:00
LouisLam
ba1d271afa fix jwt error 2021-08-09 20:09:01 +08:00
LouisLam
12910b23ed cache more layers for docker build 2021-08-09 19:23:18 +08:00
LouisLam
550c9703a6 fix radio button not checked 2021-08-09 18:46:57 +08:00
LouisLam
b69185ee9e control search engine visibility 2021-08-09 18:16:27 +08:00
LouisLam
ddcfa558f7 Merge remote-tracking branch 'origin/master' 2021-08-09 15:45:59 +08:00
LouisLam
478d2c4e8c add more favicon 2021-08-09 15:44:32 +08:00
Louis Lam
1352a0a162 Update bug_report.md 2021-08-09 14:53:21 +08:00
Louis Lam
7274b82143 Update ask-for-help.md 2021-08-09 14:52:55 +08:00
Louis Lam
69b1454cf5 Update feature_request.md 2021-08-09 14:52:31 +08:00
LouisLam
8f2a9fe883 chnage sqlite3 package in dockerfile 2021-08-09 14:47:53 +08:00
Louis Lam
1b8476417d Update README.md 2021-08-09 14:47:10 +08:00
Louis Lam
2a65402ad8 fix update command 2021-08-09 14:11:26 +08:00
LouisLam
59ef1f13db set longer timeout for axios request 2021-08-09 13:54:24 +08:00
LouisLam
bf33f97c9e code re-use and eslint 2021-08-09 13:49:37 +08:00
LouisLam
d0aad3400c add reset password in cli 2021-08-09 13:34:44 +08:00
LouisLam
6f489e7e0f Accepted Status Codes / Max Redirects for http/keyword only 2021-08-09 02:01:08 +08:00
LouisLam
f9cb8293f3 improve a bit ux 2021-08-09 01:58:56 +08:00
LouisLam
11b8c61079 wip: add search engine control in setting 2021-08-09 01:58:24 +08:00
Louis Lam
f69ba12c10 update reviewdog, add vue,ts ext 2021-08-09 00:33:28 +08:00
Louis Lam
e78cfaa492 Merge pull request #189 from Saibamen/save_maxredirects
Save `maxredirects` on monitor edit
2021-08-09 00:27:44 +08:00
Adam Stachowicz
9c17f59fe8 Fix few markdown lint warnings 2021-08-08 18:24:30 +02:00
Adam Stachowicz
519add4fab ESLint vite.config.js 2021-08-08 18:24:05 +02:00
Adam Stachowicz
46c7e5d058 Save maxredirects on edit 2021-08-08 18:23:51 +02:00
LouisLam
6291b7b8bb update reviewdog 2021-08-09 00:12:35 +08:00
LouisLam
3fb515e871 Merge remote-tracking branch 'origin/master' 2021-08-09 00:09:45 +08:00
LouisLam
8e440f7dff add a bot for eslint on github 2021-08-09 00:09:33 +08:00
Louis Lam
6d58c98b24 Update README.md 2021-08-08 23:51:23 +08:00
LouisLam
6ca7ca4e7e improve alignment and font size 2021-08-08 21:42:37 +08:00
Louis Lam
44391117ab Merge pull request #173 from chakflying/redirects&status
Feat: Implement Max.Redirects & Accepted Status Codes
2021-08-08 21:19:20 +08:00
LouisLam
9fa8d5c1fa improve multiselect 2021-08-08 21:14:29 +08:00
LouisLam
3265c3cbc3 improve multiselect 2021-08-08 21:03:10 +08:00
Louis Lam
b3721e03a8 Merge pull request #186 from chakflying/patch-3
Chore: Improve logging during db development
2021-08-08 19:24:50 +08:00
Nelson Chan
4ff68238c4 Chore: Improve logging during db development 2021-08-08 15:04:20 +08:00
LouisLam
7b1000d995 Merge remote-tracking branch 'chakflying/redirects&status' into redirects&status 2021-08-08 15:03:39 +08:00
LouisLam
a79e6aa338 dark theme for multiselect 2021-08-08 15:02:33 +08:00
LouisLam
3005585c0f Merge branch 'master' into redirects&status 2021-08-08 14:48:00 +08:00
Philipp Dormann
123fca43a1 FEAT: darkmode (#155)
* darkmode fixes

* fix: darkmode: empty beats in active/ hovered state

* fix: color for empty beats

* fix: navbar background color

* Update src/assets/vars.scss

Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>

* Update src/assets/app.scss

Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>

* wip, split dark theme style by .dark and store light theme to normal

* add back missing css

* working switch theme button and tuning dark theme

* finish dark theme

Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
Co-authored-by: LouisLam <louislam@users.noreply.github.com>
2021-08-08 13:47:29 +08:00
LouisLam
d5b40dfebf better code reuse and "Username" to "Bot Display Name" 2021-08-08 11:03:22 +08:00
LouisLam
c990edc87d allowElseIf for else return, since its auto fix removes "else" but without newline 2021-08-08 02:34:51 +08:00
LouisLam
2677f5dd87 run eslint for discord enhancement 2021-08-08 02:18:33 +08:00
Niyas
4469b3a19b Added discord username field 2021-08-07 11:13:25 +05:30
Niyas
ebf207c2f5 Custom embed username 2021-08-07 11:12:36 +05:30
Nelson Chan
a50aa93e84 Fix: Fix monitor creation json parsing 2021-08-07 02:10:38 +08:00
Niyas
91fce75a93 Removed UptimeKuma url field 2021-08-06 17:38:16 +05:30
Niyas
3a7414125a Updated discord embeds 2021-08-06 17:37:22 +05:30
LouisLam
5a6e5b7948 change multiselect color 2021-08-06 19:48:51 +08:00
LouisLam
adcd251076 Merge branch 'master' into redirects&status 2021-08-06 19:26:44 +08:00
LouisLam
dadc270876 Merge branch 'master' into discord-enhancements 2021-08-06 19:13:43 +08:00
LouisLam
a98ba41c8e minor 2021-08-06 19:12:49 +08:00
LouisLam
a40816b948 fix high severity vulnerabilities by using my fork sqlite3 package 2021-08-06 19:09:00 +08:00
LouisLam
d3e24df225 fix high severity vulnerabilities by using my fork sqlite3 package 2021-08-06 18:22:30 +08:00
Niyas
908176c910 Discord enhancements 2021-08-05 21:42:45 +05:30
Niyas
9ade9af1e2 Discord enhancements 2021-08-05 21:41:11 +05:30
LouisLam
8350bff629 update dependencies 2021-08-05 22:46:48 +08:00
Nelson Chan
93ea2c277a Update src/pages/EditMonitor.vue
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-08-05 21:06:47 +08:00
LouisLam
6251f47050 fix the min height of monitor list 2021-08-05 19:56:20 +08:00
Nelson Chan
8f7885e58a Feat: Implement MaxRedirects & StatusCodes 2021-08-05 19:04:38 +08:00
LouisLam
dffe3cf8f2 Revert "try to support subdirectory reverse proxy"
This reverts commit a03dd91e40.
2021-08-05 18:20:34 +08:00
LouisLam
d411143f3c Merge remote-tracking branch 'origin/master' 2021-08-05 17:56:50 +08:00
LouisLam
a03dd91e40 try to support subdirectory reverse proxy 2021-08-05 17:56:38 +08:00
Louis Lam
2c2ac9dc59 Delete dependabot.yml 2021-08-05 12:13:39 +08:00
Louis Lam
d06711a1a7 Update README.md 2021-08-04 15:19:06 +08:00
Louis Lam
94f2219715 Create dependabot.yml 2021-08-04 14:51:05 +08:00
LouisLam
d315e8306b update to 1.0.10 2021-08-04 13:59:42 +08:00
LouisLam
8cd0e7a058 a better script for version update 2021-08-04 13:53:21 +08:00
LouisLam
8fce62632d a better script for version update 2021-08-04 13:53:13 +08:00
LouisLam
38c0c170e7 add some comments 2021-08-04 13:31:17 +08:00
Nelson Chan
655536e457 Fix: use send() instead of end() (#161) 2021-08-04 11:56:10 +08:00
LouisLam
807db8a2d8 update to 1.0.9 2021-08-04 01:04:13 +08:00
LouisLam
d707eba046 fix disable auth 2021-08-04 01:03:40 +08:00
Philipp Dormann
e34a8e2e4a FEAT: PUSHY Notifier (#154)
FEAT: PUSHY Notifier (#154)
2021-08-03 23:14:27 +08:00
Louis Lam
6bd9d85a9a Merge pull request #150 from chakflying/created_date
Fix: [DB] Add default for created_date in monitor
2021-08-03 22:58:56 +08:00
LouisLam
f2de6299f6 update .dockerignore 2021-08-03 20:42:32 +08:00
LouisLam
a28d6eafae remove apprise --version from dockerfile 2021-08-03 20:35:41 +08:00
LouisLam
fce0edebc9 Merge remote-tracking branch 'origin/master' 2021-08-03 19:56:23 +08:00
LouisLam
48a4ced9a5 update to 1.0.8 2021-08-03 19:36:21 +08:00
Nelson Chan
221aad55de Chore: Add new line at EOF 2021-08-03 17:46:09 +08:00
Nelson Chan
377d475e05 Fix: Add now columns 2021-08-03 17:43:39 +08:00
Nelson Chan
0c3c59df4e Fix: [DB] Add default for created_date in monitor 2021-08-03 17:42:57 +08:00
Louis Lam
eba996b0f2 Delete codeql-analysis.yml 2021-08-03 15:17:48 +08:00
LouisLam
4d71e03039 improve #39 2021-08-03 15:14:26 +08:00
LouisLam
2740f096c0 Merge remote-tracking branch 'origin/master' 2021-08-03 13:07:37 +08:00
LouisLam
8ebaca4c5c improve disableAuth handling 2021-08-03 13:07:20 +08:00
Louis Lam
fceb594442 Merge pull request #145 from chakflying/patch-3
Fix: Increase width of status pill
2021-08-03 11:04:30 +08:00
Nelson Chan
5b9d3357aa Fix: Increase width of status pill 2021-08-03 10:57:56 +08:00
LouisLam
5689b30985 Merge remote-tracking branch 'origin/master' 2021-08-03 00:08:59 +08:00
LouisLam
44c8ca9da8 requires empty username/password if set disableAuth for basic auth 2021-08-03 00:08:46 +08:00
Louis Lam
6f044de6e6 Update README.md 2021-08-01 11:11:04 +08:00
Louis Lam
7877adf7a3 Merge pull request #137 from louislam/add-code-of-conduct-1
Create CODE_OF_CONDUCT.md
2021-08-01 00:36:05 +08:00
Louis Lam
f0e5e9f463 Create CODE_OF_CONDUCT.md 2021-08-01 00:35:47 +08:00
Louis Lam
0263cfa7e4 Create CONTRIBUTING.md
move wiki to CONTRIBUTING.md
2021-08-01 00:29:30 +08:00
Louis Lam
8b733592cb Update README.md 2021-08-01 00:23:40 +08:00
Louis Lam
71fa55c218 Update README.md 2021-08-01 00:19:04 +08:00
Louis Lam
ee071e41f5 Update README.md 2021-08-01 00:15:33 +08:00
LouisLam
6f868c9ec3 implement no auth 2021-07-31 23:41:24 +08:00
LouisLam
33d7f8645a json format for setting value 2021-07-31 22:02:30 +08:00
LouisLam
c6a66fad79 add setting for disable auth 2021-07-31 21:57:58 +08:00
LouisLam
9f0be5f531 improve the connection error msg 2021-07-31 21:13:32 +08:00
LouisLam
7f42888546 fix eslint for vue (https://github.com/louislam/uptime-kuma/pull/121#issuecomment-889729900) 2021-07-31 20:42:51 +08:00
LouisLam
642a711bcd Confirm Dialog: allow changing the button text 2021-07-31 18:58:12 +08:00
LouisLam
659d83b13c turn off vue/html-self-closing, empty div should be allowed 2021-07-31 18:31:17 +08:00
LouisLam
4b93900866 fix eslint for vue (https://github.com/louislam/uptime-kuma/pull/121#issuecomment-889729900) 2021-07-31 14:46:57 +08:00
Louis Lam
204624bfe9 Merge pull request #133 from NiNiyas/lunasea-support
Adds support for LunaSea notifications
2021-07-31 14:02:29 +08:00
LouisLam
b7fbc2c0e6 add LinaSea option in select box 2021-07-31 13:37:42 +08:00
LouisLam
2ebd79d037 run eslint for lunasea change 2021-07-31 13:35:18 +08:00
Niyas
3f84e5e8ab Update notification.js 2021-07-31 10:51:13 +05:30
Niyas
ab1fe2e2d1 LunaSea Support 2021-07-31 10:33:20 +05:30
Niyas
67a4e949a2 LunaSea Support 2021-07-31 10:31:41 +05:30
Louis Lam
15ee853fac Merge pull request #132 from sashkab/dockerfile-fix
Simplify apprise installation
2021-07-31 12:45:09 +08:00
LouisLam
d58be56cb9 remove "pip3 cache purge" that causes error 2021-07-31 12:21:39 +08:00
Aleks Bunin
00cc140acd Simplify apprise instalation 2021-07-30 22:32:59 -04:00
LouisLam
63f0a36811 implement upside down mode and ignore tls error 2021-07-31 00:01:04 +08:00
LouisLam
06377af7e5 turn off object-curly-newline, it makes const { a, b, c, d } = require(...) ugly 2021-07-30 22:11:14 +08:00
LouisLam
60aa67892d store ignoreTls and upsideDown into db 2021-07-30 19:18:26 +08:00
LouisLam
17b58eac9a Merge remote-tracking branch 'origin/master' 2021-07-30 15:45:18 +08:00
Nelson Chan
b9a6088f50 WIP: Add login page, nav bar buttons 2021-07-30 15:27:18 +08:00
Louis Lam
2b3a48995b Merge pull request #121 from chakflying/patch-1
Fix: Update ESLint to handle class static member
2021-07-30 15:21:14 +08:00
LouisLam
e032072900 eslint: allow while (true) 2021-07-30 15:13:51 +08:00
LouisLam
bcf2a319c2 update readme 2021-07-30 15:04:52 +08:00
Nelson Chan
cdaa0a54a4 Fix: use new version of babel-eslint-parser 2021-07-30 12:35:33 +08:00
Nelson Chan
47b19ea2f2 ESLint: fix file 2021-07-30 12:35:02 +08:00
Nelson Chan
1006b37a67 Fix: Add fix for babel-eslist 2021-07-30 12:33:01 +08:00
Nelson Chan
b91e9ddb7a Fix: Add babel-eslint 2021-07-30 12:33:01 +08:00
Nelson Chan
be22fcb87d Fix: Bump ES version in ESlint config 2021-07-30 12:33:00 +08:00
LouisLam
5a053e5875 parse the port to int 2021-07-30 11:33:44 +08:00
LouisLam
081abcb6a1 add util.ts for sharing common functions between frontend and backend 2021-07-30 11:23:04 +08:00
LouisLam
71af902a4e add fields to EditMonitor.vue 2021-07-30 01:09:14 +08:00
LouisLam
4b86c84c36 fix icon for "Resume" 2021-07-30 01:02:41 +08:00
LouisLam
f9a10d1672 add back maxretries field 2021-07-30 00:13:48 +08:00
LouisLam
e6915d8964 unexpected space add to router-link due vue/singleline-html-element-content-newline, set it to off 2021-07-29 01:01:55 +08:00
LouisLam
063697c20a set the port by env.PORT, specific node version in package.json 2021-07-29 00:52:41 +08:00
LouisLam
435e4faef3 test heroku deployment 2021-07-29 00:38:52 +08:00
LouisLam
1425d0e91a test heroku deployment 2021-07-29 00:36:35 +08:00
LouisLam
7dbec90c95 cache index.html and fix basic auth applied to all routes 2021-07-28 23:40:50 +08:00
LouisLam
53a90347ca update database schema, add upside_down and ignore_tls 2021-07-28 23:26:27 +08:00
LouisLam
133c7230bc fix resize problem 2021-07-28 23:03:37 +08:00
LouisLam
3666ebb931 change no-unused-vars from error to warn 2021-07-28 20:52:49 +08:00
LouisLam
6bce270f42 cleanup code 2021-07-28 20:35:55 +08:00
LouisLam
4a9690437f Merge branch 'eslint_stylelint'
# Conflicts:
#	server/server.js
2021-07-28 20:20:10 +08:00
Louis Lam
c8c2300483 Merge pull request #120 from chakflying/patch-1
Fix: passwordHash is not imported
2021-07-28 19:34:01 +08:00
Nelson Chan
ac0f418294 Fix: passwordHash is not imported 2021-07-28 10:58:36 +08:00
Adam Stachowicz
d54bc866b4 Fix block-no-empty error from Stylelint 2021-07-27 22:23:46 +02:00
Adam Stachowicz
be1fc0c2b6 Missing this part 2 2021-07-27 20:03:53 +02:00
Adam Stachowicz
d97091af51 Missing this 2021-07-27 20:02:20 +02:00
Adam Stachowicz
4c8fdd07d9 Manual fixes 2021-07-27 19:53:59 +02:00
Adam Stachowicz
9648d700d7 Autofix on save 2021-07-27 19:47:13 +02:00
Adam Stachowicz
8331e795e7 Merge branch 'master' into eslint_stylelint 2021-07-27 19:37:07 +02:00
Adam Stachowicz
3c6af6d3f4 Add ESLint and StyleLint 2021-07-27 19:33:44 +02:00
LouisLam
209fa83cff Add Basic Auth for /metrics 2021-07-28 00:52:31 +08:00
LouisLam
cc6f1d7487 Merge branch 'feature/add_prometheus_metrics' 2021-07-27 23:21:37 +08:00
LouisLam
36436ed4ef Move all Prometheus guides to wiki 2021-07-27 23:14:13 +08:00
LouisLam
934b797623 Merge branch 'master' into feature/add_prometheus_metrics
# Conflicts:
#	server/model/monitor.js
2021-07-27 23:13:03 +08:00
Louis Lam
0f0a6299c0 Create codeql-analysis.yml 2021-07-27 20:25:59 +08:00
Louis Lam
e6ca105600 Update ask-for-help.md 2021-07-27 18:18:38 +08:00
Louis Lam
ef45aedda5 Delete help.md 2021-07-27 18:18:27 +08:00
Louis Lam
7edd79a74d Update issue templates 2021-07-27 18:06:26 +08:00
Louis Lam
fade240c7f Delete --please-go-to--discussion--tab-if-you-want-to-ask-or-share-something.md 2021-07-27 18:05:11 +08:00
Louis Lam
46337ec348 Update issue templates 2021-07-27 18:04:55 +08:00
LouisLam
cafd2c7388 add vue-fontawesone 2021-07-27 16:52:44 +08:00
LouisLam
4d7c2d329b Update to 1.0.7 2021-07-27 13:47:15 +08:00
Louis Lam
1982e2f8b8 Update README.md 2021-07-27 00:53:26 +08:00
LouisLam
2819094377 improve the page load performance 2021-07-26 23:26:47 +08:00
LouisLam
06c4523ce3 update the latest db version to 3 2021-07-26 23:05:04 +08:00
LouisLam
ac3732f6cc Merge remote-tracking branch 'chakflying/tls-expiry' into tls-expiry
# Conflicts:
#	server/model/monitor.js
#	src/pages/Details.vue
2021-07-26 22:56:17 +08:00
LouisLam
bf3e9dccd2 improve the ui of cert info 2021-07-26 22:53:07 +08:00
LouisLam
5b18a6a518 Merge branch 'master' into tls-expiry
# Conflicts:
#	server/model/monitor.js
2021-07-26 20:35:50 +08:00
LouisLam
caec933186 prevent unexpected error throw from checkCertificate interrupt the beat 2021-07-26 12:25:44 +08:00
Nelson Chan
51ac7a58dc Fix: Fix incorrect error handling 2021-07-26 12:24:13 +08:00
Nelson Chan
db26b7d123 Fix: Fix no certificate caused by session reuse 2021-07-26 12:24:13 +08:00
Nelson Chan
7b8459c73a Fix: use Optional chaining 2021-07-26 12:24:12 +08:00
Nelson Chan
d0c63ebe3e Feat: Add database storage for TLS info 2021-07-26 12:24:12 +08:00
Nelson Chan
803f0d6219 Feat: Add Barebones certificate info display 2021-07-26 12:24:06 +08:00
LouisLam
d556509d07 戈mprove the readibility of important condition 2021-07-24 11:42:14 +08:00
Louis Lam
3cc4955cad Merge pull request #105 from rezzorix/master
Apple touch icon 192px with preserved transparency
2021-07-23 13:00:37 +08:00
LouisLam
48f82b55f8 prevent unexpected error throw from checkCertificate interrupt the beat 2021-07-23 12:58:05 +08:00
rezzorix
280ba84aca Apple touch icon 192px with preserved transparency
Resized icon.png to 192px but preserved transparency
2021-07-23 12:41:02 +08:00
Louis Lam
0dbecca10f Merge pull request #102 from NiNiyas/pushover-enhancements
Pushover enhancements
2021-07-23 12:32:36 +08:00
Louis Lam
8279368b4d Merge pull request #104 from rezzorix/patch-1
Small grammar updates to Settings.vue
2021-07-23 11:57:32 +08:00
rezzorix
2450b3d082 Small grammar updates to Settings.vue
Just small grammar corrections.
2021-07-23 11:48:39 +08:00
Nelson Chan
6b72d5033a Fix: Fix incorrect error handling 2021-07-23 11:23:43 +08:00
Nelson Chan
4d262bbb6a Fix: Fix no certificate caused by session reuse 2021-07-23 11:22:37 +08:00
Louis Lam
d1370a62bd Merge pull request #103 from Spiritreader/master
Fix parenthesis mistake in notification checker (fixes #86)
2021-07-23 09:11:14 +08:00
Sam
063fd6ef43 Merge branch 'master' of https://github.com/Spiritreader/uptime-kuma 2021-07-22 20:25:08 +02:00
Sam
1d4d7fa9c4 fix parenthesis mistake 2021-07-22 20:25:03 +02:00
Louis Lam
248b5292dc Merge pull request #86 from Spiritreader/master
Implement retries (#56)
2021-07-23 00:11:24 +08:00
Matthew Macdonald-Wallace
47d830db1f Remove examples so they can go on the wiki instead 2021-07-22 16:15:19 +01:00
Matthew Macdonald-Wallace
3a8fbff514 Change casing in README, apply DRY to label values 2021-07-22 16:00:56 +01:00
Matthew Macdonald-Wallace
a93fd274fd Update README to include examples for Prometheus 2021-07-22 15:02:33 +01:00
Niyas
77fbfc23be Pushover enhancements 2021-07-22 19:28:25 +05:30
Matthew Macdonald-Wallace
3b45006567 Move common labels into dedicated const 2021-07-22 14:58:22 +01:00
Niyas
b7a32d4ab6 Pushover enhancements 2021-07-22 19:26:54 +05:30
LouisLam
5a219554b3 grammar 2021-07-22 19:49:46 +08:00
LouisLam
70b1f197c1 rename "Retry Pings" to "Retries" 2021-07-22 19:02:44 +08:00
Matthew Macdonald-Wallace
720051a351 Typo in monitor status name 2021-07-22 11:18:20 +01:00
LouisLam
32a5e838ba add patch3.sql and fix duplicate id in EditMonitor.vue 2021-07-22 17:44:59 +08:00
LouisLam
86e18ac11d Merge branch 'master' into Spiritreader_master
# Conflicts:
#	src/pages/EditMonitor.vue
2021-07-22 17:34:41 +08:00
Matthew Macdonald-Wallace
3dcbae0889 Add labels to metrics for querying 2021-07-22 10:21:20 +01:00
Matthew Macdonald-Wallace
96242dce0d Expose check status and response time to Prometheus 2021-07-22 09:38:27 +01:00
Nelson Chan
f20ab4b0e3 Fix: use Optional chaining 2021-07-22 16:13:58 +08:00
Nelson Chan
96c60dd94a Feat: Add database storage for TLS info 2021-07-22 16:04:32 +08:00
Matthew Macdonald-Wallace
7acb265559 Remove bcryptjs and node-gyp, they should not be here... 2021-07-22 09:01:51 +01:00
Matthew Macdonald-Wallace
582fb2fe29 Export general metrics via the /metrics endpoint 2021-07-22 08:43:04 +01:00
Matthew Macdonald-Wallace
e3d4a896b1 Fix up some formatting 2021-07-22 08:33:21 +01:00
Matthew Macdonald-Wallace
9a1bf6006a Add initial package import and config 2021-07-22 08:24:25 +01:00
Matthew Macdonald-Wallace
ef41a32353 Merge pull request #1 from louislam/master
Pull down upstream
2021-07-22 08:23:24 +01:00
Nelson Chan
ccda6f05f5 Feat: Add Barebones certificate info display 2021-07-22 14:26:43 +08:00
LouisLam
03b3bb5b30 fix if notification throw exception, the heartbeat is not stored in to the db. 2021-07-22 12:28:47 +08:00
LouisLam
7e4a1ad279 remove used vars 2021-07-22 11:15:53 +08:00
LouisLam
916b9da0dc Merge branch 'master' into something
# Conflicts:
#	server/notification.js
#	src/components/NotificationDialog.vue
2021-07-22 11:12:52 +08:00
LouisLam
a64ce81457 update package-lock.json 2021-07-22 10:55:55 +08:00
LouisLam
c575afc8e0 Merge remote-tracking branch 'origin/master' 2021-07-22 10:47:39 +08:00
Louis Lam
1e42343aee Update patch1.sql
minor
2021-07-22 10:45:22 +08:00
LouisLam
afd4cf2425 Merge branch 'master' into simple_pagination 2021-07-22 10:42:30 +08:00
LouisLam
e02eb72863 add db migration 2021-07-22 02:02:35 +08:00
LouisLam
1c0dc18d72 Merge remote-tracking branch 'origin/master' 2021-07-22 01:30:22 +08:00
Louis Lam
c00612c1a9 Update --please-go-to--discussion--tab-if-you-want-to-ask-or-share-something.md 2021-07-21 16:29:15 +08:00
Louis Lam
32345fcbe9 Update issue templates 2021-07-21 16:28:31 +08:00
Louis Lam
fd90458e77 Update issue templates 2021-07-21 16:25:58 +08:00
Louis Lam
d89e6f4649 Merge pull request #89 from Saibamen/more_info_in_server_logs
More info in server logs
2021-07-21 11:34:27 +08:00
Adam Stachowicz
c4ca8e2acb More info in server logs 2021-07-21 00:41:38 +02:00
LouisLam
94b5a557bf Merge remote-tracking branch 'origin/master' 2021-07-20 23:43:59 +08:00
Sam
14e1d1f105 add .vscode directory to dockerignore 2021-07-20 17:39:21 +02:00
Sam
8b905b6b12 Indentation fix in editor
Co-authored-by: Adam Stachowicz <saibamenppl@gmail.com>
2021-07-20 17:38:21 +02:00
Louis Lam
fa57d40c3c Update README.md 2021-07-20 20:27:34 +08:00
Louis Lam
62e231e92b Update README.md 2021-07-20 20:27:15 +08:00
LouisLam
02b4dfc100 prevent the telegram getUpdates URL go out of box 2021-07-20 20:18:56 +08:00
LouisLam
657acf748b update to 1.0.6 2021-07-20 20:04:54 +08:00
Sam
054269ecf0 fix notification when changing from pending -> up 2021-07-20 11:50:33 +02:00
Louis Lam
71dd68bb6d Update README.md 2021-07-20 13:04:21 +08:00
Sam
02230930c5 Merge branch 'master' of https://github.com/Spiritreader/uptime-kuma 2021-07-19 18:26:00 +02:00
Sam
a8b102ad4a add retries for pinging function
backend:
- new field for monitor: maxretries
- new pending status while service is retrying: 2
- pending status event is not marked important
- pending pings however register as downtime in the calculation

frontend:
- added pending status while service is retrying
- added color for new pending status
- added field to configure amount of retries

database:
- IMPORTANT: THIS REQUIRES MIGRATION!!!!
- added field: maxretries with default value 0
2021-07-19 18:23:06 +02:00
Louis Lam
58d029445d Merge pull request #79 from Saibamen/remove_debug_spam
Remove debug spam
2021-07-19 23:12:33 +08:00
LouisLam
77af41bfff env default to production 2021-07-19 23:06:42 +08:00
Louis Lam
058032a26a Merge pull request #81 from Saibamen/use_NODE_ENV
Use `NODE_ENV` from Express and Socket.IO
2021-07-19 22:59:36 +08:00
Louis Lam
cbb9d3f91b set version for docker 2021-07-19 20:18:27 +08:00
Adam Stachowicz
5bd3184ebf Use connect_error event 2021-07-18 20:59:00 +02:00
Adam Stachowicz
59ebe134f1 Fix indentation 2021-07-18 20:46:45 +02:00
Adam Stachowicz
851ceef3d5 Use NODE_ENV from Express and Socket.IO 2021-07-18 20:21:17 +02:00
LouisLam
efd7608ba2 Merge remote-tracking branch 'origin/master' 2021-07-19 00:43:45 +08:00
LouisLam
05fdaf0c96 update package-lock.json 2021-07-19 00:43:25 +08:00
Louis Lam
01b0e82d52 Update README.md 2021-07-19 00:40:10 +08:00
Louis Lam
d2ccfd5366 Update README.md 2021-07-19 00:39:07 +08:00
Adam Stachowicz
7cba9ce231 Remove debug spam 2021-07-18 18:35:40 +02:00
Louis Lam
69e8c56e3e Update README.md 2021-07-19 00:34:48 +08:00
Adam Stachowicz
9928ea8c30 Merge branch 'master' into simple_pagination 2021-07-18 16:48:53 +02:00
LouisLam
25c370c9ff Merge branch 'update_packages'
# Conflicts:
#	package-lock.json
#	package.json
2021-07-18 22:22:19 +08:00
LouisLam
9227ff6ea3 add nightly build for amd64 only 2021-07-18 22:21:34 +08:00
Adam Stachowicz
2d943620c7 Merge branch 'master' into simple_pagination 2021-07-18 15:37:32 +02:00
Louis Lam
f7bd67c413 Merge pull request #77 from Saibamen/fix_docker
Fix Docker build
2021-07-18 20:53:06 +08:00
LouisLam
9ca2444dab improve testing notification response 2021-07-18 20:49:46 +08:00
Adam Stachowicz
1d45a7606d Fix Docker build 2021-07-18 13:51:44 +02:00
Adam Stachowicz
16f363ac38 Merge branch 'master' into simple_pagination 2021-07-18 13:36:57 +02:00
Louis Lam
d6b9403f60 Merge pull request #76 from Saibamen/fix_remember_me
Fix multiple labels for `Remember me`
2021-07-18 19:28:48 +08:00
Louis Lam
92e5ddd97c Merge pull request #69 from Saibamen/dockerignore
Update .dockerignore
2021-07-18 19:27:43 +08:00
Louis Lam
23611e540c Merge pull request #70 from Saibamen/fix_npm_warnings
Fix NPM warnings
2021-07-18 19:27:00 +08:00
Adam Stachowicz
f9274557f3 Fix center 2021-07-18 13:22:39 +02:00
Adam Stachowicz
44b66cbd2e Fix Remember me label 2021-07-18 13:00:59 +02:00
LouisLam
66037e236c add apprise support 2021-07-18 18:51:58 +08:00
Adam Stachowicz
386c002fda Merge branch 'master' into fix_npm_warnings 2021-07-18 11:48:08 +02:00
Adam Stachowicz
7c1aab6a15 Merge branch 'master' into dockerignore 2021-07-18 11:47:53 +02:00
Adam Stachowicz
37884cfd08 Merge branch 'master' into update_packages 2021-07-18 11:47:08 +02:00
Adam Stachowicz
ce6841eae7 Merge branch 'master' into simple_pagination 2021-07-18 11:46:32 +02:00
Adam Stachowicz
7c94c3b502 Update server/notification.js 2021-07-18 09:42:34 +00:00
Adam Stachowicz
268c8e50f5 Merge branch 'master' into something 2021-07-18 09:42:08 +00:00
LouisLam
13c9244e3f fix apprise import issue and loose the healthcheck rule 2021-07-18 17:42:00 +08:00
Louis Lam
13b3a5be9c Merge pull request #68 from Saibamen/use_console_error
Improve printing to console
2021-07-18 14:55:30 +08:00
Louis Lam
2e31e780a1 Merge pull request #67 from Saibamen/lighthouse_improvements
[Lighthouse] Some improvements
2021-07-18 13:48:35 +08:00
Louis Lam
6a2b5f9dd8 Merge pull request #66 from Saibamen/resize_apple_icon
[Lighthouse] Resize apple icon to 192px
2021-07-18 13:47:50 +08:00
Louis Lam
16767dc042 Merge pull request #65 from Saibamen/robots
[Lighthouse] Add robots.txt
2021-07-18 13:47:39 +08:00
Louis Lam
fb3e000dc3 Merge pull request #63 from NiNiyas/docker-healthcheck
Docker Healthcheck
2021-07-18 13:47:25 +08:00
Louis Lam
6f3ea21864 Merge pull request #61 from NiNiyas/slack-enhancements
Slack Enhancements and aligns footer to center
2021-07-18 13:47:04 +08:00
Louis Lam
403137280e Merge pull request #62 from NiNiyas/pushover-support
Pushover support
2021-07-18 12:20:41 +08:00
Adam Stachowicz
d94894b7e0 Fix require-v-for-key, remove unused declarations and double spaces 2021-07-18 03:10:15 +02:00
Adam Stachowicz
a173700cd4 Add pagination 2021-07-18 03:04:40 +02:00
Adam Stachowicz
9c248776e7 Update dependencies 2021-07-18 00:08:35 +02:00
Adam Stachowicz
309caa4279 Fix indentation 2021-07-17 23:57:48 +02:00
Adam Stachowicz
28b14ceb70 Fix NPM warnings 2021-07-17 23:45:36 +02:00
Adam Stachowicz
9f9c42c30b Update .dockerignore 2021-07-17 23:31:44 +02:00
Adam Stachowicz
2bff62cade Improve printing to console 2021-07-17 23:13:54 +02:00
Adam Stachowicz
bfb4a5bcd4 Add alt="Logo" 2021-07-17 22:56:54 +02:00
Adam Stachowicz
e87b78501b rel="noopener" for external link 2021-07-17 22:55:53 +02:00
Adam Stachowicz
637422494f Add description 2021-07-17 22:53:32 +02:00
Adam Stachowicz
db34484ff2 Add theme-color 2021-07-17 22:51:07 +02:00
Adam Stachowicz
790c071f2c Resize apple icon to 192px 2021-07-17 22:45:28 +02:00
Adam Stachowicz
149688e669 Add robots.txt 2021-07-17 22:24:10 +02:00
Niyas
7dae5279fb Docker healthcheck
Copied from https://scoutapm.com/blog/how-to-use-docker-healthcheck
2021-07-17 20:08:01 +05:30
Niyas
c203317b3b Docker healthcheck
Copied from https://scoutapm.com/blog/how-to-use-docker-healthcheck
2021-07-17 20:07:35 +05:30
Niyas
01f2fccb23 Update notification.js 2021-07-17 18:59:26 +05:30
Niyas
7808aef58f Pushover support 2021-07-17 18:42:54 +05:30
Niyas
ce2d78f45a Pushover support 2021-07-17 17:55:02 +05:30
Niyas
20cad50593 Pushover support 2021-07-17 17:49:56 +05:30
Niyas
829a2a191d Footer center align 2021-07-17 13:42:05 +05:30
Niyas
65b320d06b Slack Enhancements 2021-07-17 12:48:42 +05:30
Niyas
1935da5b16 Slack Enhancements 2021-07-17 12:47:52 +05:30
LouisLam
78f5d2cd8b update to 1.0.5 2021-07-17 02:31:31 +08:00
LouisLam
f62b70c9a9 add nightly to version number 2021-07-17 02:30:16 +08:00
LouisLam
dfa9b3a0ca fix require() actually not working after build in the frontend 2021-07-17 00:51:28 +08:00
LouisLam
b3bff8d735 add graceful shutdown 2021-07-16 01:44:51 +08:00
Louis Lam
f2af5bc064 Merge pull request #46 from NiNiyas/slack-webhook
Added Slack webhook notification
2021-07-15 11:59:41 +08:00
Louis Lam
91b736f391 Merge pull request #52 from philippdormann/feature/gotify-upstream-merge
customize Gotify priority
2021-07-15 11:59:20 +08:00
Louis Lam
275f77d4bb Merge pull request #45 from R0GGER/master
Apple icon for iPhone/iPad
2021-07-15 11:03:46 +08:00
Louis Lam
b00524067a Update README.md 2021-07-15 10:59:36 +08:00
Philipp Dormann
25a93b05dc easier merging 🤞 2021-07-14 22:00:15 +02:00
Philipp Dormann
53e203d2f9 add gotify priority
ref https://github.com/louislam/uptime-kuma/pull/43
closes https://github.com/louislam/uptime-kuma/issues/50
2021-07-14 21:56:38 +02:00
LouisLam
f48f957ba9 update to 1.0.4 2021-07-15 01:44:15 +08:00
LouisLam
bfb117cb76 minor 2021-07-15 01:01:47 +08:00
LouisLam
2b8e33caed dockerfile: change the base image to node:14-alpine3.12; add apprise cli, prepare for implementing notification 2021-07-15 00:36:44 +08:00
Niyas
60493f0f86 Updated Slack test notification 2021-07-14 21:59:16 +05:30
Niyas
63c6e29e62 Added Slack Webhook support 2021-07-14 21:08:38 +05:30
Niyas
5f6d5588a6 Added Slack Webhook support 2021-07-14 21:07:14 +05:30
R0GGER
18744d834f Add files via upload 2021-07-14 14:35:59 +02:00
R0GGER
8dd5b97b79 Apple icon 2021-07-14 14:34:50 +02:00
Louis Lam
386c8bfdf1 Merge pull request #43 from philippdormann/feature/gotify-upstream-merge
 Gotify Support
2021-07-14 17:36:21 +08:00
Philipp Dormann
126f00e739 added Gotify Support 2021-07-14 11:25:10 +02:00
Louis Lam
80466ac957 Update README.md 2021-07-14 17:10:51 +08:00
LouisLam
3b52433202 cache the sqlite built when docker build 2021-07-14 12:42:52 +08:00
Louis Lam
137f5da3da Update README.md 2021-07-14 01:48:55 +08:00
Louis Lam
338d002d42 Update README.md 2021-07-14 01:39:04 +08:00
Louis Lam
77ab9fbc57 Add some shields by shields.io 2021-07-14 01:36:25 +08:00
LouisLam
b6b7835d7e update to 1.0.3 2021-07-13 23:34:33 +08:00
LouisLam
d4fe5908f5 fix merging problem 2021-07-13 23:29:40 +08:00
LouisLam
af838d62e8 update 1.0.2 2021-07-13 23:09:12 +08:00
LouisLam
5a6e83b777 remove debug msg 2021-07-13 23:05:52 +08:00
LouisLam
c81930cacc add build-docker-nightly script 2021-07-13 23:03:55 +08:00
LouisLam
6d4694da43 add version-global-replace.js 2021-07-13 22:58:30 +08:00
LouisLam
9c23cd09ce use bcrypt for password hash 2021-07-13 22:22:46 +08:00
LouisLam
a60bf1528a drop ie support when build the frontend 2021-07-13 18:34:09 +08:00
LouisLam
1f3b337806 reset auto increment for new users 2021-07-13 18:21:06 +08:00
LouisLam
010ebea210 show version in the footer 2021-07-13 18:08:12 +08:00
LouisLam
b3a5d868a7 catch timezone error if browser do not have 2021-07-13 17:46:39 +08:00
LouisLam
312dec7393 add png icon 2021-07-13 12:38:59 +08:00
LouisLam
be1ef24cce add a comment 2021-07-13 12:24:33 +08:00
Louis Lam
c5de82b220 Merge pull request #35 from louislam/revert-32-feature/darkmode
Revert "basic darkmode"
2021-07-13 12:16:24 +08:00
Louis Lam
fef41b44a8 Revert "basic darkmode" 2021-07-13 12:16:11 +08:00
Louis Lam
6af65b688d Merge pull request #32 from philippdormann/feature/darkmode
basic darkmode
2021-07-13 11:58:57 +08:00
LouisLam
3e4a98b6bc Merge branch 'dev'
# Conflicts:
#	server/notification.js
2021-07-13 11:42:51 +08:00
LouisLam
866bf56319 add build-docker-nightly script 2021-07-13 11:32:40 +08:00
LouisLam
99afdabcac change the docker base image to node:14-alpine3.14, reduce the container size 2021-07-13 11:32:09 +08:00
LouisLam
0f1a95fde9 smtp without username password 2021-07-13 11:01:02 +08:00
LouisLam
edbab8163e update .editorconfig 2021-07-13 10:31:31 +08:00
LouisLam
551d00fc24 add some comments and remove traefik-network from docker-composer.yml 2021-07-13 10:28:07 +08:00
Louis Lam
3e4cdbecf2 Merge pull request #28 from yatadev/master
Create docker-compose.yml
2021-07-13 10:21:21 +08:00
Louis Lam
622681470d Merge pull request #22 from TheGuyDanish/master
Discord notification rework
2021-07-13 10:20:47 +08:00
Philipp Dormann
d9e2c230bf Merge branch 'master' of philippdormann/uptime-kuma into philippdormann/uptime-kuma->feature/darkmode
darkmode based on css variables. ref https://github.com/louislam/uptime-kuma/issues/21
2021-07-12 22:21:19 +02:00
Philipp Dormann
010302395f clean, multistage Dockerfile 2021-07-12 22:11:47 +02:00
jacr13
e053ee6573 fix bad pasting 2021-07-12 22:10:26 +02:00
Philipp Dormann
c4bc95927f dependency bumps 2021-07-12 22:09:27 +02:00
jacr13
3e305b79b2 remove debub console log 2021-07-12 22:08:42 +02:00
jacr13
c6237277c0 add support for signal notifications 2021-07-12 22:06:03 +02:00
Philipp Dormann
900219deb1 Merge remote-tracking branch 'theguydanish/master'
# Conflicts:
#	package-lock.json
#	package.json
2021-07-12 21:58:13 +02:00
Philipp Dormann
7ebeee3455 README: add sample docker-compose link
ref https://github.com/louislam/uptime-kuma/issues/25
2021-07-12 21:53:49 +02:00
Philipp Dormann
0abd3b2d16 README cleanup 2021-07-12 21:53:28 +02:00
Philipp Dormann
f452bf6b13 properly name Dockerfile 2021-07-12 21:50:51 +02:00
Philipp Dormann
8cd90d1e96 🐳 Docker 2021-07-12 21:50:39 +02:00
Philipp Dormann
789094a2ee formatting socket.js + deal with broken windows ports - default :50013 2021-07-12 21:49:18 +02:00
Philipp Dormann
5515437eab 🧹 cleanup 2021-07-12 21:47:32 +02:00
Philipp Dormann
7acb347012 🧹 fix formatting in server.js 2021-07-12 21:43:31 +02:00
Philipp Dormann
9d57e93367 Merge branch 'master' of https://github.com/philippdormann/uptime-kuma 2021-07-12 21:41:01 +02:00
Philipp Dormann
dae92d0ae4 Merge remote-tracking branch 'upstream/master'
# Conflicts:
#	package.json
2021-07-12 21:40:35 +02:00
LouisLam
1259ff5368 smtp username/password is not required 2021-07-13 01:02:50 +08:00
yatadev
8debce82b1 Create docker-compose.yml 2021-07-12 18:23:38 +02:00
LouisLam
11a2adcb7c Merge remote-tracking branch 'origin/master' 2021-07-12 23:29:13 +08:00
LouisLam
ad615d1a90 remove some timezones which may cause error 2021-07-12 23:28:56 +08:00
TheGuyDanish
613c42b6d8 Discord revamp! Changed from bot to webhook, removed discord.js dep 2021-07-12 14:13:36 +01:00
Louis Lam
a6e16116f2 improve the docker script 2021-07-12 20:08:51 +08:00
Louis Lam
c7dfb36349 Update README.md 2021-07-12 20:00:12 +08:00
LouisLam
459dde2761 update the setup script to 1.0.1 2021-07-12 19:03:25 +08:00
LouisLam
cb94ab3bb5 add update guide 2021-07-12 18:59:48 +08:00
LouisLam
0176857a2c add ability to change the listening port and hostname 2021-07-12 18:33:25 +08:00
Philipp Dormann
763d7f2683 Merge branch 'louislam:master' into master 2021-07-12 12:01:00 +02:00
Louis Lam
c436ef4e05 Update README.md 2021-07-12 11:42:36 +08:00
LouisLam
56fcfc9369 fix show N/A if the ping is 0ms 2021-07-12 11:20:18 +08:00
LouisLam
a9d19ae06a support json for keyword type 2021-07-12 10:52:41 +08:00
Louis Lam
35ce54f30c Merge pull request #6 from TheGuyDanish/patch-1
Introduce custom user agent. Fixes #5
2021-07-12 09:39:15 +08:00
Philipp Dormann
e4f38d833d 🌑 darkmode support for nav link hover 2021-07-12 00:41:28 +02:00
Philipp Dormann
8b83266b00 🌑 add darkmode support for focused input elements 2021-07-12 00:37:08 +02:00
Philipp Dormann
6fb1b344f6 🌑 darkmode support on form elements 2021-07-12 00:33:52 +02:00
Philipp Dormann
b15b44e290 🐳 move Dockerfile to base node:alpine image
reduces size from about 1.08GB to 345MB (still not great but hey)
2021-07-12 00:28:11 +02:00
Philipp Dormann
66d991bd05 🐞 added missing v-bind:key to Dashboard 2021-07-12 00:27:29 +02:00
Philipp Dormann
673d3c124c 🚧 WIP on darkmode 🌑 2021-07-12 00:26:33 +02:00
Philipp Dormann
e568cad22c dependency bump + version pin 2021-07-12 00:25:22 +02:00
TheGuyDanish
f84f7aca75 Introduce custom user agent. Fixes #5
Quick and easy fix. Could be improved by adding a version number as well. Like `Uptime-Kuma/0.0.1`, for example.
2021-07-11 21:01:34 +01:00
LouisLam
b198b3dde4 Merge remote-tracking branch 'origin/master' 2021-07-12 01:18:18 +08:00
LouisLam
0b294815c7 add back arm/v7 for build-docker 2021-07-12 01:18:02 +08:00
Louis Lam
83935a2cf4 Update README.md 2021-07-11 23:41:21 +08:00
Louis Lam
838913f0a1 Update README.md 2021-07-11 23:41:04 +08:00
179 changed files with 29153 additions and 5672 deletions

View File

@@ -1,11 +0,0 @@
spec:
name: uptime-kuma
services:
- name: server
git:
repo_clone_url: https://github.com/louislam/uptime-kuma
branch: master
http_port: 3001
build_command: npm run setup
run_command: npm run start-server

View File

@@ -1,4 +1,46 @@
/.idea
/dist
/node_modules
/data/kuma.db
/data
/out
/test
/kubernetes
/.do
**/.dockerignore
/private
**/.git
**/.gitignore
**/docker-compose*
**/[Dd]ockerfile*
LICENSE
README.md
.editorconfig
.vscode
.eslint*
.stylelint*
/.github
package-lock.json
yarn.lock
app.json
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CNAME
install.sh
SECURITY.md
tsconfig.json
### .gitignore content (commented rules are duplicated)
#node_modules
.DS_Store
#dist
dist-ssr
*.local
#.idea
#/data
#!/data/.gitkeep
#.vscode
### End of .gitignore content

View File

@@ -13,3 +13,9 @@ trim_trailing_whitespace = false
[*.yaml]
indent_size = 2
[*.yml]
indent_size = 2
[*.vue]
trim_trailing_whitespace = false

96
.eslintrc.js Normal file
View File

@@ -0,0 +1,96 @@
module.exports = {
root: true,
env: {
browser: true,
commonjs: true,
es2020: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:vue/vue3-recommended",
],
parser: "vue-eslint-parser",
parserOptions: {
parser: "@babel/eslint-parser",
sourceType: "module",
requireConfigFile: false,
},
rules: {
"linebreak-style": ["error", "unix"],
"camelcase": ["warn", {
"properties": "never",
"ignoreImports": true
}],
// override/add rules settings here, such as:
// 'vue/no-unused-vars': 'error'
"no-unused-vars": "warn",
indent: [
"error",
4,
{
ignoredNodes: ["TemplateLiteral"],
SwitchCase: 1,
},
],
quotes: ["warn", "double"],
semi: "warn",
"vue/html-indent": ["warn", 4], // default: 2
"vue/max-attributes-per-line": "off",
"vue/singleline-html-element-content-newline": "off",
"vue/html-self-closing": "off",
"vue/attribute-hyphenation": "off", // This change noNL to "no-n-l" unexpectedly
"no-multi-spaces": ["error", {
ignoreEOLComments: true,
}],
"space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}],
"curly": "error",
"object-curly-spacing": ["error", "always"],
"object-curly-newline": "off",
"object-property-newline": "error",
"comma-spacing": "error",
"brace-style": "error",
"no-var": "error",
"key-spacing": "warn",
"keyword-spacing": "warn",
"space-infix-ops": "warn",
"arrow-spacing": "warn",
"no-trailing-spaces": "warn",
"no-constant-condition": ["error", {
"checkLoops": false,
}],
"space-before-blocks": "warn",
//'no-console': 'warn',
"no-extra-boolean-cast": "off",
"no-multiple-empty-lines": ["warn", {
"max": 1,
"maxBOF": 0,
}],
"lines-between-class-members": ["warn", "always", {
exceptAfterSingleLine: true,
}],
"no-unneeded-ternary": "error",
"array-bracket-newline": ["error", "consistent"],
"eol-last": ["error", "always"],
//'prefer-template': 'error',
"comma-dangle": ["warn", "only-multiline"],
"no-empty": ["error", {
"allowEmptyCatch": true
}],
"no-control-regex": "off",
"one-var": ["error", "never"],
"max-statements-per-line": ["error", { "max": 1 }]
},
"overrides": [
{
"files": [ "src/languages/*.js", "src/icon.js" ],
"rules": {
"comma-dangle": ["error", "always-multiline"],
}
}
]
};

12
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,12 @@
# These are supported funding model platforms
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
#patreon: # Replace with a single Patreon username
open_collective: uptime-kuma # Replace with a single Open Collective username
#ko_fi: # Replace with a single Ko-fi username
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
#liberapay: # Replace with a single Liberapay username
#issuehunt: # Replace with a single IssueHunt username
#otechie: # Replace with a single Otechie username
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']

18
.github/ISSUE_TEMPLATE/ask-for-help.md vendored Normal file
View File

@@ -0,0 +1,18 @@
---
name: Ask for help
about: You can ask any question related to Uptime Kuma.
title: ''
labels: help
assignees: ''
---
**Is it a duplicate question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Info**
Uptime Kuma Version:
Using Docker?: Yes/No
Docker Version:
Node.js Version (Without Docker only):
OS:
Browser:

42
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,42 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Is it a duplicate question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Info**
Uptime Kuma Version:
Using Docker?: Yes/No
Docker Version:
Node.js Version (Without Docker only):
OS:
Browser:
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Error Log**
It is easier for us to find out the problem.
Docker: `docker logs <container id>`
PM2: `~/.pm2/logs/` (e.g. `/home/ubuntu/.pm2/logs`)

View File

@@ -0,0 +1,22 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is it a duplicate question?**
Please search in Issues without filters: https://github.com/louislam/uptime-kuma/issues?q=
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

4
.gitignore vendored
View File

@@ -7,3 +7,7 @@ dist-ssr
/data
!/data/.gitkeep
.vscode
/private
/out

9
.stylelintrc Normal file
View File

@@ -0,0 +1,9 @@
{
"extends": "stylelint-config-standard",
"rules": {
"indentation": 4,
"no-descending-specificity": null,
"selector-list-comma-newline-after": null,
"declaration-empty-line-before": null
}
}

1
CNAME Normal file
View File

@@ -0,0 +1 @@
git.kuma.pet

128
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,128 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
louis@uptimekuma.louislam.net.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

144
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,144 @@
# Project Info
First of all, thank you everyone who made pull requests for Uptime Kuma, I never thought GitHub Community can be that nice! And also because of this, I also never thought other people actually read my code and edit my code. It is not structed and commented so well, lol. Sorry about that.
The project was created with vite.js (vue3). Then I created a sub-directory called "server" for server part. Both frontend and backend share the same package.json.
The frontend code build into "dist" directory. The server uses "dist" as root. This is how production is working.
# Can I create a pull request for Uptime Kuma?
Generally, if the pull request is working fine and it do not affect any existing logic, workflow and perfomance, I will merge to the master branch once it is tested.
If you are not sure, feel free to create an empty pull request draft first.
## Pull Request Examples
### ✅ High - Medium Priority
- Add a new notification
- Add a chart
- Fix a bug
### *️⃣ Requires one more reviewer
I do not have such knowledge to test it.
- Add k8s supports
### *️⃣ Low Priority
It changed my current workflow and require further studies.
- Change my release approach
### ❌ Won't Merge
- Duplicated pull request
- Buggy
- Existing logic is completely modified or deleted
- A function that is completely out of scope
# Project Styles
I personally do not like something need to learn so much and need to config so much before you can finally start the app.
For example, recently, because I am not a python expert, I spent a 2 hours to resolve all problems in order to install and use the Apprise cli. Apprise requires so many hidden requirements, I have to figure out myself how to solve the problems by Google search for my OS. That is painful. I do not want Uptime Kuma to be like this way, so:
- Easy to install for non-Docker users, no native build dependency is needed (at least for x86_64), no extra config, no extra effort to get it run
- Single container for Docker users, no very complex docker-composer file. Just map the volume and expose the port, then good to go
- All settings in frontend.
- Easy to use
# Coding Styles
- Follow `.editorconfig`
- Follow ESLint
## Name convention
- Javascript/Typescript: camelCaseType
- SQLite: underscore_type
- CSS/SCSS: dash-type
# Tools
- Node.js >= 14
- Git
- IDE that supports EditorConfig and ESLint (I am using Intellji Idea)
- A SQLite tool (I am using SQLite Expert Personal)
# Install dependencies
```bash
npm install --dev
```
For npm@7, you need --legacy-peer-deps
```bash
npm install --legacy-peer-deps --dev
```
# Backend Dev
(2021-09-23 Update)
```bash
npm run start-server-dev
```
It binds to `0.0.0.0:3001` by default.
## Backend Details
It is mainly a socket.io app + express.js.
express.js is just used for serving the frontend built files (index.html, .js and .css etc.)
# Frontend Dev
Start frontend dev server. Hot-reload enabled in this way. It binds to `0.0.0.0:3000` by default.
```bash
npm run dev
```
PS: You can ignore those scss warnings, those warnings are from Bootstrap that I cannot fix.
You can use Vue.js devtools Chrome extension for debugging.
After the frontend server started. It cannot connect to the websocket server even you have started the server. You need to tell the frontend that is a dev env by running this in DevTool console and refresh:
```javascript
localStorage.dev = "dev";
```
So that the frontend will try to connect websocket server in 3001.
Alternately, you can specific `NODE_ENV` to "development".
## Build the frontend
```bash
npm run build
```
## Frontend Details
Uptime Kuma Frontend is a single page application (SPA). Most paths are handled by Vue Router.
The router is in `src/router.js`
As you can see, most data in frontend is stored in root level, even though you changed the current router to any other pages.
The data and socket logic are in `src/mixins/socket.js`.
# Database Migration
1. Create `patch{num}.sql` in `./db/`
2. Update `latestVersion` in `./server/database.js`
# Unit Test
Yes, no unit test for now. I know it is very important, but at the same time my spare time is very limited. I want to implement my ideas first. I will go back to this in some points.

View File

@@ -1,5 +1,7 @@
# Uptime Kuma
<a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/stars/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/pulls/louislam/uptime-kuma" /></a> <a target="_blank" href="https://hub.docker.com/r/louislam/uptime-kuma"><img src="https://img.shields.io/docker/v/louislam/uptime-kuma/latest?label=docker%20image%20ver." /></a> <a target="_blank" href="https://github.com/louislam/uptime-kuma"><img src="https://img.shields.io/github/last-commit/louislam/uptime-kuma" /></a>
<div align="center" width="100%">
<img src="./public/icon.svg" width="128" alt="" />
</div>
@@ -8,49 +10,84 @@ It is a self-hosted monitoring tool like "Uptime Robot".
<img src="https://louislam.net/uptimekuma/1.jpg" width="512" alt="" />
# Features
## 🥔 Live Demo
* Monitoring uptime for HTTP(s) / TCP / Ping.
Try it!
https://demo.uptime.kuma.pet
It is a 5 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.
VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollective.com/uptime-kuma)! Thank you so much!
## ⭐ Features
* Monitoring uptime for HTTP(s) / TCP / Ping / DNS Record.
* Fancy, Reactive, Fast UI/UX.
* Notifications via Webhook, Telegram, Discord and email (SMTP).
* 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/issues/284).
* 20 seconds interval.
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
# How to Use
## 🔧 How to Install
### 🐳 Docker
### Docker
```bash
docker run -d --restart=always -p 3001:3001 louislam/uptime-kuma
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.
### Without Docker
### 💪🏻 Without Docker
Required Tools: Node.js >= 14, git and pm2.
Required Tools: Node.js >= 14, git and pm2.
```bash
# Update your npm to the latest version
npm install npm -g
git clone https://github.com/louislam/uptime-kuma.git
cd uptime-kuma
npm run setup
# Option 1. Try it
npm run start-server
node server/server.js
# (Recommanded)
# Option 2. Run in background using PM2
# (Recommended) Option 2. Run in background using PM2
# Install PM2 if you don't have: npm install pm2 -g
pm2 start npm --name uptime-kuma -- run start-server
pm2 start server/server.js --name uptime-kuma
```
Browse to http://localhost:3001 after started.
### One-click Deploy to DigitalOcean
### Advanced Installation
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/louislam/uptime-kuma/tree/master&refcode=e2c7eb658434)
If you need more options or need to browse via a reserve proxy, please read:
https://github.com/louislam/uptime-kuma/wiki/%F0%9F%94%A7-How-to-Install
# More Screenshots
## 🆙 How to Update
Please read:
https://github.com/louislam/uptime-kuma/wiki/%F0%9F%86%99-How-to-Update
## 🆕 What's Next?
I will mark requests/issues to the next milestone.
https://github.com/louislam/uptime-kuma/milestones
Project Plan:
https://github.com/louislam/uptime-kuma/projects/1
## 🖼 More Screenshots
Dark Mode:
<img src="https://user-images.githubusercontent.com/1336778/128710166-908f8d88-9256-43f3-9c49-bfc2c56011d2.png" width="400" alt="" />
Settings Page:
@@ -60,16 +97,33 @@ Telegram Notification Sample:
<img src="https://louislam.net/uptimekuma/3.jpg" width="400" alt="" />
## Motivation
# Motivation
* I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close one is statping. Unfortunately, it is not stable and unmaintained.
* I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and unmaintained.
* Want to build a fancy UI.
* Learn Vue 3 and vite.js.
* Show the power of Bootstrap 5.
* Show the power of Bootstrap 5.
* Try to use WebSocket with SPA instead of REST API.
* Deploy my first Docker image to Docker Hub.
If you love this project, please consider giving me a ⭐.
## 🗣️ Discussion
### Issues Page
You can discuss or ask for help in [Issues](https://github.com/louislam/uptime-kuma/issues).
### Subreddit
My Reddit account: louislamlam
You can mention me if you ask question on Reddit.
https://www.reddit.com/r/UptimeKuma/
## Contribute
If you want to report a bug or request a new feature. Free feel to open a [new issue](https://github.com/louislam/uptime-kuma/issues).
If you want to translate Uptime Kuma into your langauge, please read: https://github.com/louislam/uptime-kuma/tree/master/src/languages
If you want to modify Uptime Kuma, this guideline may be useful for you: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md
English proofreading is needed too because my grammar is not that great sadly. Feel free to correct my grammar in this readme, source code, or wiki.

15
SECURITY.md Normal file
View File

@@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | ------------------ |
| 1.x.x | :white_check_mark: |
## Reporting a Vulnerability
Please report security issues to uptime@kuma.pet.
Do not use the issue tracker or discuss it in the public as it will cause more damage.

Binary file not shown.

10
db/patch-2fa.sql Normal file
View File

@@ -0,0 +1,10 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE user
ADD twofa_secret VARCHAR(64);
ALTER TABLE user
ADD twofa_status BOOLEAN default 0 NOT NULL;
COMMIT;

View File

@@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD retry_interval INTEGER default 0 not null;
COMMIT;

30
db/patch-group-table.sql Normal file
View File

@@ -0,0 +1,30 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
create table `group`
(
id INTEGER not null
constraint group_pk
primary key autoincrement,
name VARCHAR(255) not null,
created_date DATETIME default (DATETIME('now')) not null,
public BOOLEAN default 0 not null,
active BOOLEAN default 1 not null,
weight BOOLEAN NOT NULL DEFAULT 1000
);
CREATE TABLE [monitor_group]
(
[id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[monitor_id] INTEGER NOT NULL REFERENCES [monitor] ([id]) ON DELETE CASCADE ON UPDATE CASCADE,
[group_id] INTEGER NOT NULL REFERENCES [group] ([id]) ON DELETE CASCADE ON UPDATE CASCADE,
weight BOOLEAN NOT NULL DEFAULT 1000
);
CREATE INDEX [fk]
ON [monitor_group] (
[monitor_id],
[group_id]);
COMMIT;

View File

@@ -0,0 +1,10 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
-- For sendHeartbeatList
CREATE INDEX monitor_time_index ON heartbeat (monitor_id, time);
-- For sendImportantHeartbeatList
CREATE INDEX monitor_important_time_index ON heartbeat (monitor_id, important,time);
COMMIT;

View File

@@ -0,0 +1,18 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
create table incident
(
id INTEGER not null
constraint incident_pk
primary key autoincrement,
title VARCHAR(255) not null,
content TEXT not null,
style VARCHAR(30) default 'warning' not null,
created_date DATETIME default (DATETIME('now')) not null,
last_updated_date DATETIME,
pin BOOLEAN default 1 not null,
active BOOLEAN default 1 not null
);
COMMIT;

View File

@@ -0,0 +1,22 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
-- Generated by Intellij IDEA
create table setting_dg_tmp
(
id INTEGER
primary key autoincrement,
key VARCHAR(200) not null
unique,
value TEXT,
type VARCHAR(20)
);
insert into setting_dg_tmp(id, key, value, type) select id, key, value, type from setting;
drop table setting;
alter table setting_dg_tmp rename to setting;
COMMIT;

37
db/patch1.sql Normal file
View File

@@ -0,0 +1,37 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
-- Change Monitor.created_date from "TIMESTAMP" to "DATETIME"
-- SQL Generated by Intellij Idea
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,
keyword VARCHAR(255)
);
insert into monitor_dg_tmp(id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword) select id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword 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;

19
db/patch10.sql Normal file
View File

@@ -0,0 +1,19 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
CREATE TABLE tag (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
name VARCHAR(255) NOT NULL,
color VARCHAR(255) NOT NULL,
created_date DATETIME DEFAULT (DATETIME('now')) NOT NULL
);
CREATE TABLE monitor_tag (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
monitor_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
value TEXT,
CONSTRAINT FK_tag FOREIGN KEY (tag_id) REFERENCES tag(id) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT FK_monitor FOREIGN KEY (monitor_id) REFERENCES monitor(id) ON DELETE CASCADE ON UPDATE CASCADE
);
CREATE INDEX monitor_tag_monitor_id_index ON monitor_tag (monitor_id);
CREATE INDEX monitor_tag_tag_id_index ON monitor_tag (tag_id);

9
db/patch2.sql Normal file
View File

@@ -0,0 +1,9 @@
BEGIN TRANSACTION;
CREATE TABLE monitor_tls_info (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
monitor_id INTEGER NOT NULL,
info_json TEXT
);
COMMIT;

37
db/patch3.sql Normal file
View File

@@ -0,0 +1,37 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
-- Add maxretries column to monitor
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,
keyword VARCHAR(255),
maxretries INTEGER NOT NULL DEFAULT 0
);
insert into monitor_dg_tmp(id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword) select id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword 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;

40
db/patch4.sql Normal file
View File

@@ -0,0 +1,40 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
-- OK.... serious wrong, missing maxretries column
-- Developers should patch it manually if you have missing the maxretries column
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,
keyword VARCHAR(255),
maxretries INTEGER NOT NULL DEFAULT 0,
ignore_tls BOOLEAN default 0 not null,
upside_down BOOLEAN default 0 not null
);
insert into monitor_dg_tmp(id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword, maxretries) select id, name, active, user_id, interval, url, type, weight, hostname, port, created_date, keyword, maxretries 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;

70
db/patch5.sql Normal file
View File

@@ -0,0 +1,70 @@
-- 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
);
insert into
monitor_dg_tmp(
id,
name,
active,
user_id,
interval,
url,
type,
weight,
hostname,
port,
keyword,
maxretries,
ignore_tls,
upside_down
)
select
id,
name,
active,
user_id,
interval,
url,
type,
weight,
hostname,
port,
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;

74
db/patch6.sql Normal file
View File

@@ -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;

10
db/patch7.sql Normal file
View File

@@ -0,0 +1,10 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD dns_resolve_type VARCHAR(5);
ALTER TABLE monitor
ADD dns_resolve_server VARCHAR(255);
COMMIT;

7
db/patch8.sql Normal file
View File

@@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD dns_last_result VARCHAR(255);
COMMIT;

7
db/patch9.sql Normal file
View File

@@ -0,0 +1,7 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE notification
ADD is_default BOOLEAN default 0 NOT NULL;
COMMIT;

13
docker-compose.yml Normal file
View File

@@ -0,0 +1,13 @@
# Simple docker-composer.yml
# You can change your port or volume location
version: '3.3'
services:
uptime-kuma:
image: louislam/uptime-kuma
container_name: uptime-kuma
volumes:
- ./uptime-kuma:/app/data
ports:
- 3001:3001

View File

@@ -1,10 +1,57 @@
FROM node:14
# DON'T UPDATE TO node:14-bullseye-slim, see #372.
# If the image changed, the second stage image should be changed too
FROM node:14-buster-slim AS build
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
RUN npm install --legacy-peer-deps && \
npm run build && \
npm prune --production && \
chmod +x /app/extra/entrypoint.sh
FROM node:14-buster-slim AS release
WORKDIR /app
# Install Apprise, add sqlite3 cli for debugging in the future, iputils-ping for ping, util-linux for setpriv
RUN apt update && \
apt --yes install python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \
sqlite3 iputils-ping util-linux dumb-init && \
pip3 --no-cache-dir install apprise && \
rm -rf /var/lib/apt/lists/*
# Copy app files from build layer
COPY --from=build /app /app
EXPOSE 3001
VOLUME ["/app/data"]
CMD ["npm", "run", "start-server"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"]
CMD ["node", "server/server.js"]
FROM release AS nightly
RUN npm run mark-as-nightly
# Upload the artifact to Github
FROM node:14-buster-slim AS upload-artifact
WORKDIR /
RUN apt update && \
apt --yes install curl file
ARG GITHUB_TOKEN
ARG TARGETARCH
ARG PLATFORM=debian
ARG VERSION=1.5.0
COPY --from=build /app /app
RUN FILE=uptime-kuma.tar.gz
RUN tar -czf $FILE app
RUN curl \
-H "Authorization: token $GITHUB_TOKEN" \
-H "Content-Type: $(file -b --mime-type $FILE)" \
--data-binary @$FILE \
"https://uploads.github.com/repos/louislam/uptime-kuma/releases/$VERSION/assets?name=$(basename $FILE)"

30
dockerfile-alpine Normal file
View File

@@ -0,0 +1,30 @@
# DON'T UPDATE TO alpine3.13, 1.14, see #41.
FROM node:14-alpine3.12 AS build
WORKDIR /app
COPY . .
RUN npm install --legacy-peer-deps && \
npm run build && \
npm prune --production && \
chmod +x /app/extra/entrypoint.sh
FROM node:14-alpine3.12 AS release
WORKDIR /app
# Install apprise, iputils for non-root ping, setpriv
RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib && \
pip3 --no-cache-dir install apprise && \
rm -rf /root/.cache
# Copy app files from build layer
COPY --from=build /app /app
EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js
ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"]
CMD ["node", "server/server.js"]
FROM release AS nightly
RUN npm run mark-as-nightly

View File

@@ -0,0 +1,2 @@
# Must enable File Sharing in Docker Desktop
docker run -it --rm -v ${pwd}:/app louislam/batsh /usr/bin/batsh bash --output ./install.sh ./extra/install.batsh

21
extra/entrypoint.sh Normal file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env sh
# set -e Exit the script if an error happens
set -e
PUID=${PUID=0}
PGID=${PGID=0}
files_ownership () {
# -h Changes the ownership of an encountered symbolic link and not that of the file or directory pointed to by the symbolic link.
# -R Recursively descends the specified directories
# -c Like verbose but report only when a change is made
chown -hRc "$PUID":"$PGID" /app/data
}
echo "==> Performing startup jobs and maintenance tasks"
files_ownership
echo "==> Starting application with user $PUID group $PGID"
# --clear-groups Clear supplementary groups.
exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups "$@"

34
extra/healthcheck.js Normal file
View File

@@ -0,0 +1,34 @@
/*
* This script should be run after a period of time (180s), because the server may need some time to prepare.
*/
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let client;
if (process.env.SSL_KEY && process.env.SSL_CERT) {
client = require("https");
} else {
client = require("http");
}
let options = {
host: process.env.HOST || "127.0.0.1",
port: parseInt(process.env.PORT) || 3001,
timeout: 28 * 1000,
};
let request = client.request(options, (res) => {
console.log(`Health Check OK [Res Code: ${res.statusCode}]`);
if (res.statusCode === 200) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on("error", function (err) {
console.error("Health Check ERROR");
process.exit(1);
});
request.end();

245
extra/install.batsh Normal file
View File

@@ -0,0 +1,245 @@
// install.sh is generated by ./extra/install.batsh, do not modify it directly.
// "npm run compile-install-script" to compile install.sh
// The command is working on Windows PowerShell and Docker for Windows only.
// curl -o kuma_install.sh https://raw.githubusercontent.com/louislam/uptime-kuma/master/install.sh && sudo bash kuma_install.sh
println("=====================");
println("Uptime Kuma Installer");
println("=====================");
println("Supported OS: CentOS 7/8, Ubuntu >= 16.04 and Debian");
println("---------------------------------------");
println("This script is designed for Linux and basic usage.");
println("For advanced usage, please go to https://github.com/louislam/uptime-kuma/wiki/Installation");
println("---------------------------------------");
println("");
println("Local - Install Uptime Kuma in your current machine with git, Node.js 14 and pm2");
println("Docker - Install Uptime Kuma Docker container");
println("");
if ("$1" != "") {
type = "$1";
} else {
call("read", "-p", "Which installation method do you prefer? [DOCKER/local]: ", "type");
}
defaultPort = "3001";
function checkNode() {
bash("nodeVersion=$(node -e 'console.log(process.versions.node.split(`.`)[0])')");
println("Node Version: " ++ nodeVersion);
if (nodeVersion < "12") {
println("Error: Required Node.js 14");
call("exit", "1");
}
if (nodeVersion == "12") {
println("Warning: NodeJS " ++ nodeVersion ++ " is not tested.");
}
}
function deb() {
bash("nodeCheck=$(node -v)");
bash("apt --yes update");
if (nodeCheck != "") {
checkNode();
} else {
// Old nodejs binary name is "nodejs"
bash("check=$(nodejs --version)");
if (check != "") {
println("Error: 'node' command is not found, but 'nodejs' command is found. Your NodeJS should be too old.");
bash("exit 1");
}
bash("curlCheck=$(curl --version)");
if (curlCheck == "") {
println("Installing Curl");
bash("apt --yes install curl");
}
println("Installing Node.js 14");
bash("curl -sL https://deb.nodesource.com/setup_14.x | bash - > log.txt");
bash("apt --yes install nodejs");
bash("node -v");
bash("nodeCheckAgain=$(node -v)");
if (nodeCheckAgain == "") {
println("Error during Node.js installation");
bash("exit 1");
}
}
bash("check=$(git --version)");
if (check == "") {
println("Installing Git");
bash("apt --yes install git");
}
}
if (type == "local") {
defaultInstallPath = "/opt/uptime-kuma";
if (exists("/etc/redhat-release")) {
os = call("cat", "/etc/redhat-release");
distribution = "rhel";
} else if (exists("/etc/issue")) {
bash("os=$(head -n1 /etc/issue | cut -f 1 -d ' ')");
if (os == "Ubuntu") {
distribution = "ubuntu";
}
if (os == "Debian") {
distribution = "debian";
}
}
bash("arch=$(uname -i)");
println("Your OS: " ++ os);
println("Distribution: " ++ distribution);
println("Arch: " ++ arch);
if ("$3" != "") {
port = "$3";
} else {
call("read", "-p", "Listening Port [$defaultPort]: ", "port");
if (port == "") {
port = defaultPort;
}
}
if ("$2" != "") {
installPath = "$2";
} else {
call("read", "-p", "Installation Path [$defaultInstallPath]: ", "installPath");
if (installPath == "") {
installPath = defaultInstallPath;
}
}
// CentOS
if (distribution == "rhel") {
bash("nodeCheck=$(node -v)");
if (nodeCheck != "") {
checkNode();
} else {
bash("curlCheck=$(curl --version)");
if (curlCheck == "") {
println("Installing Curl");
bash("yum -y -q install curl");
}
println("Installing Node.js 14");
bash("curl -sL https://rpm.nodesource.com/setup_14.x | bash - > log.txt");
bash("yum install -y -q nodejs");
bash("node -v");
bash("nodeCheckAgain=$(node -v)");
if (nodeCheckAgain == "") {
println("Error during Node.js installation");
bash("exit 1");
}
}
bash("check=$(git --version)");
if (check == "") {
println("Installing Git");
bash("yum -y -q install git");
}
// Ubuntu
} else if (distribution == "ubuntu") {
deb();
// Debian
} else if (distribution == "debian") {
deb();
} else {
// Unknown distribution
error = 0;
bash("check=$(git --version)");
if (check == "") {
error = 1;
println("Error: git is missing");
}
bash("check=$(node -v)");
if (check == "") {
error = 1;
println("Error: node is missing");
}
if (error > 0) {
println("Please install above missing software");
bash("exit 1");
}
}
bash("check=$(pm2 --version)");
if (check == "") {
println("Installing PM2");
bash("npm install pm2 -g");
bash("pm2 startup");
}
bash("mkdir -p $installPath");
bash("cd $installPath");
bash("git clone https://github.com/louislam/uptime-kuma.git .");
bash("npm run setup");
bash("pm2 start server/server.js --name uptime-kuma -- --port=$port");
} else {
defaultVolume = "uptime-kuma";
bash("check=$(docker -v)");
if (check == "") {
println("Error: docker is not found!");
bash("exit 1");
}
bash("check=$(docker info)");
bash("if [[ \"$check\" == *\"Is the docker daemon running\"* ]]; then
\"echo\" \"Error: docker is not running\"
\"exit\" \"1\"
fi");
if ("$3" != "") {
port = "$3";
} else {
call("read", "-p", "Expose Port [$defaultPort]: ", "port");
if (port == "") {
port = defaultPort;
}
}
if ("$2" != "") {
volume = "$2";
} else {
call("read", "-p", "Volume Name [$defaultVolume]: ", "volume");
if (volume == "") {
volume = defaultVolume;
}
}
println("Port: $port");
println("Volume: $volume");
bash("docker volume create $volume");
bash("docker run -d --restart=always -p $port:3001 -v $volume:/app/data --name uptime-kuma louislam/uptime-kuma:1");
}
println("http://localhost:$port");

24
extra/mark-as-nightly.js Normal file
View File

@@ -0,0 +1,24 @@
const pkg = require("../package.json");
const fs = require("fs");
const util = require("../src/util");
util.polyfill();
const oldVersion = pkg.version
const newVersion = oldVersion + "-nightly"
console.log("Old Version: " + oldVersion)
console.log("New Version: " + newVersion)
if (newVersion) {
// Process package.json
pkg.version = newVersion
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion)
pkg.scripts["build-docker"] = pkg.scripts["build-docker"].replaceAll(oldVersion, newVersion)
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n")
// Process README.md
if (fs.existsSync("README.md")) {
fs.writeFileSync("README.md", fs.readFileSync("README.md", "utf8").replaceAll(oldVersion, newVersion))
}
}

61
extra/reset-password.js Normal file
View File

@@ -0,0 +1,61 @@
console.log("== Uptime Kuma Reset Password Tool ==");
console.log("Loading the database");
const Database = require("../server/database");
const { R } = require("redbean-node");
const readline = require("readline");
const { initJWTSecret } = require("../server/util-server");
const args = require("args-parser")(process.argv);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
(async () => {
Database.init(args);
await Database.connect();
try {
const user = await R.findOne("user");
if (! user) {
throw new Error("user not found, have you installed?");
}
console.log("Found user: " + user.username);
while (true) {
let password = await question("New Password: ");
let confirmPassword = await question("Confirm New Password: ");
if (password === confirmPassword) {
await user.resetPassword(password);
// Reset all sessions by reset jwt secret
await initJWTSecret();
rl.close();
break;
} else {
console.log("Passwords do not match, please try again.");
}
}
console.log("Password reset successfully.");
} catch (e) {
console.error("Error: " + e.message);
}
await Database.close();
console.log("Finished. You should restart the Uptime Kuma server.")
})();
function question(question) {
return new Promise((resolve) => {
rl.question(question, (answer) => {
resolve(answer);
})
});
}

144
extra/simple-dns-server.js Normal file
View File

@@ -0,0 +1,144 @@
/*
* Simple DNS Server
* For testing DNS monitoring type, dev only
*/
const dns2 = require("dns2");
const { Packet } = dns2;
const server = dns2.createServer({
udp: true
});
server.on("request", (request, send, rinfo) => {
for (let question of request.questions) {
console.log(question.name, type(question.type), question.class);
const response = Packet.createResponseFromRequest(request);
if (question.name === "existing.com") {
if (question.type === Packet.TYPE.A) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
address: "1.2.3.4"
});
} if (question.type === Packet.TYPE.AAAA) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
address: "fe80::::1234:5678:abcd:ef00",
});
} else if (question.type === Packet.TYPE.CNAME) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
domain: "cname1.existing.com",
});
} else if (question.type === Packet.TYPE.MX) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
exchange: "mx1.existing.com",
priority: 5
});
} else if (question.type === Packet.TYPE.NS) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
ns: "ns1.existing.com",
});
} else if (question.type === Packet.TYPE.SOA) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
primary: "existing.com",
admin: "admin@existing.com",
serial: 2021082701,
refresh: 300,
retry: 3,
expiration: 10,
minimum: 10,
});
} else if (question.type === Packet.TYPE.SRV) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
priority: 5,
weight: 5,
port: 8080,
target: "srv1.existing.com",
});
} else if (question.type === Packet.TYPE.TXT) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
data: "#v=spf1 include:_spf.existing.com ~all",
});
} else if (question.type === Packet.TYPE.CAA) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
flags: 0,
tag: "issue",
value: "ca.existing.com",
});
}
}
if (question.name === "4.3.2.1.in-addr.arpa") {
if (question.type === Packet.TYPE.PTR) {
response.answers.push({
name: question.name,
type: question.type,
class: question.class,
ttl: 300,
domain: "ptr1.existing.com",
});
}
}
send(response);
}
});
server.on("listening", () => {
console.log("Listening");
console.log(server.addresses());
});
server.on("close", () => {
console.log("server closed");
});
server.listen({
udp: 5300
});
function type(code) {
for (let name in Packet.TYPE) {
if (Packet.TYPE[name] === code) {
return name;
}
}
}

View File

@@ -0,0 +1,3 @@
package-lock.json
test.js
languages/

View File

@@ -0,0 +1,84 @@
// Need to use ES6 to read language files
import fs from "fs";
import path from "path";
import util from "util";
// https://stackoverflow.com/questions/13786160/copy-folder-recursively-in-node-js
/**
* Look ma, it's cp -R.
* @param {string} src The path to the thing to copy.
* @param {string} dest The path to the new copy.
*/
const copyRecursiveSync = function (src, dest) {
let exists = fs.existsSync(src);
let stats = exists && fs.statSync(src);
let isDirectory = exists && stats.isDirectory();
if (isDirectory) {
fs.mkdirSync(dest);
fs.readdirSync(src).forEach(function (childItemName) {
copyRecursiveSync(path.join(src, childItemName),
path.join(dest, childItemName));
});
} else {
fs.copyFileSync(src, dest);
}
};
console.log("Arguments:", process.argv)
const baseLangCode = process.argv[2] || "en";
console.log("Base Lang: " + baseLangCode);
fs.rmdirSync("./languages", { recursive: true });
copyRecursiveSync("../../src/languages", "./languages");
const en = (await import("./languages/en.js")).default;
const baseLang = (await import(`./languages/${baseLangCode}.js`)).default;
const files = fs.readdirSync("./languages");
console.log("Files:", files);
for (const file of files) {
if (!file.endsWith(".js")) {
console.log("Skipping " + file)
continue;
}
console.log("Processing " + file);
const lang = await import("./languages/" + file);
let obj;
if (lang.default) {
obj = lang.default;
} else {
console.log("Empty file");
obj = {
languageName: "<Your Language name in your language (not in English)>"
};
}
// En first
for (const key in en) {
if (! obj[key]) {
obj[key] = en[key];
}
}
if (baseLang !== en) {
// Base second
for (const key in baseLang) {
if (! obj[key]) {
obj[key] = key;
}
}
}
const code = "export default " + util.inspect(obj, {
depth: null,
});
fs.writeFileSync(`../../src/languages/${file}`, code);
}
fs.rmdirSync("./languages", { recursive: true });
console.log("Done. Fixing formatting by ESLint...");

View File

@@ -0,0 +1,12 @@
{
"name": "update-language-files",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

61
extra/update-version.js Normal file
View File

@@ -0,0 +1,61 @@
const pkg = require("../package.json");
const fs = require("fs");
const child_process = require("child_process");
const util = require("../src/util");
util.polyfill();
const oldVersion = pkg.version;
const newVersion = process.argv[2];
console.log("Old Version: " + oldVersion);
console.log("New Version: " + newVersion);
if (! newVersion) {
console.error("invalid version");
process.exit(1);
}
const exists = tagExists(newVersion);
if (! exists) {
// Process package.json
pkg.version = newVersion;
pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion);
pkg.scripts["build-docker"] = pkg.scripts["build-docker"].replaceAll(oldVersion, newVersion);
pkg.scripts["build-docker-alpine"] = pkg.scripts["build-docker-alpine"].replaceAll(oldVersion, newVersion);
pkg.scripts["build-docker-debian"] = pkg.scripts["build-docker-debian"].replaceAll(oldVersion, newVersion);
fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n");
commit(newVersion);
tag(newVersion);
} else {
console.log("version exists")
}
function commit(version) {
let msg = "update to " + version;
let res = child_process.spawnSync("git", ["commit", "-m", msg, "-a"]);
let stdout = res.stdout.toString().trim();
console.log(stdout)
if (stdout.includes("no changes added to commit")) {
throw new Error("commit error")
}
}
function tag(version) {
let res = child_process.spawnSync("git", ["tag", version]);
console.log(res.stdout.toString().trim())
}
function tagExists(version) {
if (! version) {
throw new Error("invalid version");
}
let res = child_process.spawnSync("git", ["tag", "-l", version]);
return res.stdout.toString().trim() === version;
}

View File

@@ -1,13 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png">
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link rel="manifest" href="manifest.json" />
<meta name="theme-color" id="theme-color" content="" />
<meta name="description" content="Uptime Kuma monitoring tool" />
<title>Uptime Kuma</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

203
install.sh Normal file
View File

@@ -0,0 +1,203 @@
# install.sh is generated by ./extra/install.batsh, do not modify it directly.
# "npm run compile-install-script" to compile install.sh
# The command is working on Windows PowerShell and Docker for Windows only.
# curl -o kuma_install.sh https://raw.githubusercontent.com/louislam/uptime-kuma/master/install.sh && sudo bash kuma_install.sh
"echo" "-e" "====================="
"echo" "-e" "Uptime Kuma Installer"
"echo" "-e" "====================="
"echo" "-e" "Supported OS: CentOS 7/8, Ubuntu >= 16.04 and Debian"
"echo" "-e" "---------------------------------------"
"echo" "-e" "This script is designed for Linux and basic usage."
"echo" "-e" "For advanced usage, please go to https://github.com/louislam/uptime-kuma/wiki/Installation"
"echo" "-e" "---------------------------------------"
"echo" "-e" ""
"echo" "-e" "Local - Install Uptime Kuma in your current machine with git, Node.js 14 and pm2"
"echo" "-e" "Docker - Install Uptime Kuma Docker container"
"echo" "-e" ""
if [ "$1" != "" ]; then
type="$1"
else
"read" "-p" "Which installation method do you prefer? [DOCKER/local]: " "type"
fi
defaultPort="3001"
function checkNode {
local _0
nodeVersion=$(node -e 'console.log(process.versions.node.split(`.`)[0])')
"echo" "-e" "Node Version: ""$nodeVersion"
_0="12"
if [ $(($nodeVersion < $_0)) == 1 ]; then
"echo" "-e" "Error: Required Node.js 14"
"exit" "1"
fi
if [ "$nodeVersion" == "12" ]; then
"echo" "-e" "Warning: NodeJS ""$nodeVersion"" is not tested."
fi
}
function deb {
nodeCheck=$(node -v)
apt --yes update
if [ "$nodeCheck" != "" ]; then
"checkNode"
else
# Old nodejs binary name is "nodejs"
check=$(nodejs --version)
if [ "$check" != "" ]; then
"echo" "-e" "Error: 'node' command is not found, but 'nodejs' command is found. Your NodeJS should be too old."
exit 1
fi
curlCheck=$(curl --version)
if [ "$curlCheck" == "" ]; then
"echo" "-e" "Installing Curl"
apt --yes install curl
fi
"echo" "-e" "Installing Node.js 14"
curl -sL https://deb.nodesource.com/setup_14.x | bash - > log.txt
apt --yes install nodejs
node -v
nodeCheckAgain=$(node -v)
if [ "$nodeCheckAgain" == "" ]; then
"echo" "-e" "Error during Node.js installation"
exit 1
fi
fi
check=$(git --version)
if [ "$check" == "" ]; then
"echo" "-e" "Installing Git"
apt --yes install git
fi
}
if [ "$type" == "local" ]; then
defaultInstallPath="/opt/uptime-kuma"
if [ -e "/etc/redhat-release" ]; then
os=$("cat" "/etc/redhat-release")
distribution="rhel"
else
if [ -e "/etc/issue" ]; then
os=$(head -n1 /etc/issue | cut -f 1 -d ' ')
if [ "$os" == "Ubuntu" ]; then
distribution="ubuntu"
fi
if [ "$os" == "Debian" ]; then
distribution="debian"
fi
fi
fi
arch=$(uname -i)
"echo" "-e" "Your OS: ""$os"
"echo" "-e" "Distribution: ""$distribution"
"echo" "-e" "Arch: ""$arch"
if [ "$3" != "" ]; then
port="$3"
else
"read" "-p" "Listening Port [$defaultPort]: " "port"
if [ "$port" == "" ]; then
port="$defaultPort"
fi
fi
if [ "$2" != "" ]; then
installPath="$2"
else
"read" "-p" "Installation Path [$defaultInstallPath]: " "installPath"
if [ "$installPath" == "" ]; then
installPath="$defaultInstallPath"
fi
fi
# CentOS
if [ "$distribution" == "rhel" ]; then
nodeCheck=$(node -v)
if [ "$nodeCheck" != "" ]; then
"checkNode"
else
curlCheck=$(curl --version)
if [ "$curlCheck" == "" ]; then
"echo" "-e" "Installing Curl"
yum -y -q install curl
fi
"echo" "-e" "Installing Node.js 14"
curl -sL https://rpm.nodesource.com/setup_14.x | bash - > log.txt
yum install -y -q nodejs
node -v
nodeCheckAgain=$(node -v)
if [ "$nodeCheckAgain" == "" ]; then
"echo" "-e" "Error during Node.js installation"
exit 1
fi
fi
check=$(git --version)
if [ "$check" == "" ]; then
"echo" "-e" "Installing Git"
yum -y -q install git
fi
# Ubuntu
else
if [ "$distribution" == "ubuntu" ]; then
"deb"
# Debian
else
if [ "$distribution" == "debian" ]; then
"deb"
else
# Unknown distribution
error=$((0))
check=$(git --version)
if [ "$check" == "" ]; then
error=$((1))
"echo" "-e" "Error: git is missing"
fi
check=$(node -v)
if [ "$check" == "" ]; then
error=$((1))
"echo" "-e" "Error: node is missing"
fi
if [ $(($error > 0)) == 1 ]; then
"echo" "-e" "Please install above missing software"
exit 1
fi
fi
fi
fi
check=$(pm2 --version)
if [ "$check" == "" ]; then
"echo" "-e" "Installing PM2"
npm install pm2 -g
pm2 startup
fi
mkdir -p $installPath
cd $installPath
git clone https://github.com/louislam/uptime-kuma.git .
npm run setup
pm2 start server/server.js --name uptime-kuma -- --port=$port
else
defaultVolume="uptime-kuma"
check=$(docker -v)
if [ "$check" == "" ]; then
"echo" "-e" "Error: docker is not found!"
exit 1
fi
check=$(docker info)
if [[ "$check" == *"Is the docker daemon running"* ]]; then
"echo" "Error: docker is not running"
"exit" "1"
fi
if [ "$3" != "" ]; then
port="$3"
else
"read" "-p" "Expose Port [$defaultPort]: " "port"
if [ "$port" == "" ]; then
port="$defaultPort"
fi
fi
if [ "$2" != "" ]; then
volume="$2"
else
"read" "-p" "Volume Name [$defaultVolume]: " "volume"
if [ "$volume" == "" ]; then
volume="$defaultVolume"
fi
fi
"echo" "-e" "Port: $port"
"echo" "-e" "Volume: $volume"
docker volume create $volume
docker run -d --restart=always -p $port:3001 -v $volume:/app/data --name uptime-kuma louislam/uptime-kuma:1
fi
"echo" "-e" "http://localhost:$port"

32
kubernetes/README.md Normal file
View File

@@ -0,0 +1,32 @@
# 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.

View File

@@ -0,0 +1,10 @@
namespace: uptime-kuma
namePrefix: uptime-kuma-
commonLabels:
app: uptime-kuma
bases:
- uptime-kuma

View File

@@ -0,0 +1,45 @@
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

View File

@@ -0,0 +1,39 @@
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

View File

@@ -0,0 +1,5 @@
resources:
- deployment.yml
- service.yml
- ingressroute.yml
- pvc.yml

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 4Gi

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: service
spec:
selector:
component: uptime-kuma
type: ClusterIP
ports:
- name: http
port: 3001
targetPort: 3001
protocol: TCP

16241
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,41 +1,109 @@
{
"name": "uptime-kuma",
"version": "1.0.0",
"version": "1.7.3",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/louislam/uptime-kuma.git"
},
"engines": {
"node": "14.*"
},
"scripts": {
"install-legacy": "npm install --legacy-peer-deps",
"update-legacy": "npm update --legacy-peer-deps",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint:style": "stylelint \"**/*.{vue,css,scss}\" --ignore-path .gitignore",
"lint": "npm run lint:js && npm run lint:style",
"dev": "vite --host",
"start": "npm run start-server",
"start-server": "node server/server.js",
"update": "",
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
"build": "vite build",
"tsc": "tsc",
"vite-preview-dist": "vite preview --host",
"build-docker": "docker buildx build --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 . --push",
"setup": "git checkout 1.0.0 && npm install && npm run build"
"build-docker": "npm run build-docker-debian && npm run build-docker-alpine",
"build-docker-alpine": "docker buildx build -f 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.7.3-alpine --target release . --push",
"build-docker-debian": "docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.7.3 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.7.3-debian --target release . --push",
"build-docker-nightly": "docker buildx build --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-amd64": "docker buildx build --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.7.3 && npm install --legacy-peer-deps && node node_modules/esbuild/install.js && npm run build && npm prune",
"update-version": "node extra/update-version.js",
"mark-as-nightly": "node extra/mark-as-nightly.js",
"reset-password": "node extra/reset-password.js",
"compile-install-script": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command ./extra/compile-install-script.ps1",
"test-install-script-centos7": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/centos7.dockerfile .",
"test-install-script-alpine3": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/alpine3.dockerfile .",
"test-install-script-ubuntu": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu.dockerfile .",
"test-install-script-ubuntu1604": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1604.dockerfile .",
"test-nodejs16": "docker build --progress plain -f test/ubuntu-nodejs16.dockerfile .",
"simple-dns-server": "node extra/simple-dns-server.js",
"update-language-files-with-base-lang": "cd extra/update-language-files && node index.js %npm_config_base_lang% && eslint ../../src/languages/**.js --fix",
"update-language-files": "cd extra/update-language-files && node index.js && eslint ../../src/languages/**.js --fix"
},
"dependencies": {
"@popperjs/core": "^2.9.2",
"axios": "^0.21.1",
"bootstrap": "^5.0.0",
"dayjs": "^1.10.4",
"discord.js": "^12.5.3",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-regular-svg-icons": "^5.15.4",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"@fortawesome/vue-fontawesome": "^3.0.0-4",
"@louislam/sqlite3": "^5.0.6",
"@popperjs/core": "^2.10.1",
"args-parser": "^1.3.0",
"axios": "^0.21.4",
"bcryptjs": "^2.4.3",
"bootstrap": "^5.1.1",
"chart.js": "^3.5.1",
"chartjs-adapter-dayjs": "^1.0.0",
"command-exists": "^1.2.9",
"compare-versions": "^3.6.0",
"dayjs": "^1.10.7",
"express": "^4.17.1",
"express-basic-auth": "^1.2.0",
"form-data": "^4.0.0",
"http-graceful-shutdown": "^3.1.4",
"jsonwebtoken": "^8.5.1",
"nodemailer": "^6.6.2",
"nodemailer": "^6.6.5",
"notp": "^2.0.3",
"password-hash": "^1.2.2",
"redbean-node": "0.0.20",
"socket.io": "^4.0.2",
"socket.io-client": "^4.1.2",
"prom-client": "^13.2.0",
"prometheus-api-metrics": "^3.2.0",
"qrcode": "^1.4.4",
"redbean-node": "0.1.2",
"socket.io": "^4.2.0",
"socket.io-client": "^4.2.0",
"tcp-ping": "^0.1.1",
"vue": "^3.0.5",
"thirty-two": "^1.0.2",
"timezones-list": "^3.0.1",
"v-pagination-3": "^0.1.6",
"vue": "next",
"vue-chart-3": "^0.5.8",
"vue-confirm-dialog": "^1.0.2",
"vue-router": "^4.0.10",
"vue-toastification": "^2.0.0-rc.1"
"vue-contenteditable": "^3.0.4",
"vue-i18n": "^9.1.7",
"vue-image-crop-upload": "^3.0.3",
"vue-multiselect": "^3.0.0-alpha.2",
"vue-qrcode": "^1.0.0",
"vue-router": "^4.0.11",
"vue-toastification": "^2.0.0-rc.1",
"vuedraggable": "^4.1.0"
},
"devDependencies": {
"@vitejs/plugin-legacy": "^1.4.3",
"@vitejs/plugin-vue": "^1.2.3",
"@vue/compiler-sfc": "^3.0.5",
"core-js": "^3.15.2",
"sass": "^1.35.1",
"vite": "^2.3.7"
"@babel/eslint-parser": "^7.15.7",
"@types/bootstrap": "^5.1.6",
"@vitejs/plugin-legacy": "^1.5.3",
"@vitejs/plugin-vue": "^1.9.1",
"@vue/compiler-sfc": "^3.2.16",
"core-js": "^3.18.0",
"cross-env": "^7.0.3",
"dns2": "^2.0.1",
"eslint": "^7.32.0",
"eslint-plugin-vue": "^7.18.0",
"sass": "^1.42.1",
"stylelint": "^13.13.1",
"stylelint-config-standard": "^22.0.0",
"typescript": "^4.4.3",
"vite": "2.5.*"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
public/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/icon-192x192.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/icon-512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

BIN
public/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

19
public/manifest.json Normal file
View File

@@ -0,0 +1,19 @@
{
"name": "Uptime Kuma",
"short_name": "Uptime Kuma",
"start_url": "/",
"background_color": "#fff",
"display": "standalone",
"icons": [
{
"src": "icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

51
server/auth.js Normal file
View File

@@ -0,0 +1,51 @@
const basicAuth = require("express-basic-auth")
const passwordHash = require("./password-hash");
const { R } = require("redbean-node");
const { setting } = require("./util-server");
const { debug } = require("../src/util");
/**
*
* @param username : string
* @param password : string
* @returns {Promise<Bean|null>}
*/
exports.login = async function (username, password) {
let user = await R.findOne("user", " username = ? AND active = 1 ", [
username,
])
if (user && passwordHash.verify(password, user.password)) {
// Upgrade the hash to bcrypt
if (passwordHash.needRehash(user.password)) {
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
passwordHash.generate(password),
user.id,
]);
}
return user;
}
return null;
}
function myAuthorizer(username, password, callback) {
setting("disableAuth").then((result) => {
if (result) {
callback(null, true)
} else {
exports.login(username, password).then((user) => {
callback(null, user != null)
})
}
})
}
exports.basicAuth = basicAuth({
authorizer: myAuthorizer,
authorizeAsync: true,
challenge: true,
});

44
server/check-version.js Normal file
View File

@@ -0,0 +1,44 @@
const { setSetting } = require("./util-server");
const axios = require("axios");
const { isDev } = require("../src/util");
exports.version = require("../package.json").version;
exports.latestVersion = null;
let interval;
exports.startInterval = () => {
let check = async () => {
try {
const res = await axios.get("https://raw.githubusercontent.com/louislam/uptime-kuma/master/package.json");
if (typeof res.data === "string") {
res.data = JSON.parse(res.data);
}
// For debug
if (process.env.TEST_CHECK_VERSION === "1") {
res.data.version = "1000.0.0";
}
exports.latestVersion = res.data.version;
console.log("Latest Version: " + exports.latestVersion);
} catch (_) { }
};
check();
interval = setInterval(check, 3600 * 1000 * 48);
};
exports.enableCheckUpdate = async (value) => {
await setSetting("checkUpdate", value);
clearInterval(interval);
if (value) {
exports.startInterval();
}
};
exports.socket = null;

88
server/client.js Normal file
View File

@@ -0,0 +1,88 @@
/*
* For Client Socket
*/
const { TimeLogger } = require("../src/util");
const { R } = require("redbean-node");
const { io } = require("./server");
async function sendNotificationList(socket) {
const timeLogger = new TimeLogger();
let result = [];
let list = await R.find("notification", " user_id = ? ", [
socket.userID,
]);
for (let bean of list) {
result.push(bean.export())
}
io.to(socket.userID).emit("notificationList", result)
timeLogger.print("Send Notification List");
return list;
}
/**
* Send Heartbeat History list to socket
* @param toUser True = send to all browsers with the same user id, False = send to the current browser only
* @param overwrite Overwrite client-side's heartbeat list
*/
async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
const timeLogger = new TimeLogger();
let list = await R.getAll(`
SELECT * FROM heartbeat
WHERE monitor_id = ?
ORDER BY time DESC
LIMIT 100
`, [
monitorID,
])
let result = list.reverse();
if (toUser) {
io.to(socket.userID).emit("heartbeatList", monitorID, result, overwrite);
} else {
socket.emit("heartbeatList", monitorID, result, overwrite);
}
timeLogger.print(`[Monitor: ${monitorID}] sendHeartbeatList`);
}
/**
* Important Heart beat list (aka event list)
* @param socket
* @param monitorID
* @param toUser True = send to all browsers with the same user id, False = send to the current browser only
* @param overwrite Overwrite client-side's heartbeat list
*/
async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) {
const timeLogger = new TimeLogger();
let list = await R.find("heartbeat", `
monitor_id = ?
AND important = 1
ORDER BY time DESC
LIMIT 500
`, [
monitorID,
])
timeLogger.print(`[Monitor: ${monitorID}] sendImportantHeartbeatList`);
if (toUser) {
io.to(socket.userID).emit("importantHeartbeatList", monitorID, list, overwrite);
} else {
socket.emit("importantHeartbeatList", monitorID, list, overwrite);
}
}
module.exports = {
sendNotificationList,
sendImportantHeartbeatList,
sendHeartbeatList,
}

376
server/database.js Normal file
View File

@@ -0,0 +1,376 @@
const fs = require("fs");
const { R } = require("redbean-node");
const { setSetting, setting } = require("./util-server");
const { debug, sleep } = require("../src/util");
const dayjs = require("dayjs");
const knex = require("knex");
/**
* Database & App Data Folder
*/
class Database {
static templatePath = "./db/kuma.db";
/**
* Data Dir (Default: ./data)
*/
static dataDir;
/**
* User Upload Dir (Default: ./data/upload)
*/
static uploadDir;
static path;
/**
* @type {boolean}
*/
static patched = false;
/**
* For Backup only
*/
static backupPath = null;
/**
* Add patch filename in key
* Values:
* true: Add it regardless of order
* false: Do nothing
* { parents: []}: Need parents before add it
*/
static patchList = {
"patch-setting-value-type.sql": true,
"patch-improve-performance.sql": true,
"patch-2fa.sql": true,
"patch-add-retry-interval-monitor.sql": true,
"patch-incident-table.sql": true,
"patch-group-table.sql": true,
}
/**
* The finally version should be 10 after merged tag feature
* @deprecated Use patchList for any new feature
*/
static latestVersion = 10;
static noReject = true;
static init(args) {
// Data Directory (must be end with "/")
Database.dataDir = process.env.DATA_DIR || args["data-dir"] || "./data/";
Database.path = Database.dataDir + "kuma.db";
if (! fs.existsSync(Database.dataDir)) {
fs.mkdirSync(Database.dataDir, { recursive: true });
}
Database.uploadDir = Database.dataDir + "upload/";
if (! fs.existsSync(Database.uploadDir)) {
fs.mkdirSync(Database.uploadDir, { recursive: true });
}
console.log(`Data Dir: ${Database.dataDir}`);
}
static async connect() {
const acquireConnectionTimeout = 120 * 1000;
const Dialect = require("knex/lib/dialects/sqlite3/index.js");
Dialect.prototype._driver = () => require("@louislam/sqlite3");
const knexInstance = knex({
client: Dialect,
connection: {
filename: Database.path,
acquireConnectionTimeout: acquireConnectionTimeout,
},
useNullAsDefault: true,
pool: {
min: 1,
max: 1,
idleTimeoutMillis: 120 * 1000,
propagateCreateError: false,
acquireTimeoutMillis: acquireConnectionTimeout,
}
});
R.setup(knexInstance);
if (process.env.SQL_LOG === "1") {
R.debug(true);
}
// Auto map the model to a bean object
R.freeze(true);
await R.autoloadModels("./server/model");
await R.exec("PRAGMA foreign_keys = ON");
// Change to WAL
await R.exec("PRAGMA journal_mode = WAL");
await R.exec("PRAGMA cache_size = -12000");
console.log("SQLite config:");
console.log(await R.getAll("PRAGMA journal_mode"));
console.log(await R.getAll("PRAGMA cache_size"));
console.log("SQLite Version: " + await R.getCell("SELECT sqlite_version()"));
}
static async patch() {
let version = parseInt(await setting("database_version"));
if (! version) {
version = 0;
}
console.info("Your database version: " + version);
console.info("Latest database version: " + this.latestVersion);
if (version === this.latestVersion) {
console.info("Database no need to patch");
} else if (version > this.latestVersion) {
console.info("Warning: Database version is newer than expected");
} else {
console.info("Database patch is needed");
this.backup(version);
// Try catch anything here, if gone wrong, restore the backup
try {
for (let i = version + 1; i <= this.latestVersion; i++) {
const sqlFile = `./db/patch${i}.sql`;
console.info(`Patching ${sqlFile}`);
await Database.importSQLFile(sqlFile);
console.info(`Patched ${sqlFile}`);
await setSetting("database_version", i);
}
} catch (ex) {
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");
this.restore();
process.exit(1);
}
}
await this.patch2();
}
/**
* Call it from patch() only
* @returns {Promise<void>}
*/
static async patch2() {
console.log("Database Patch 2.0 Process");
let databasePatchedFiles = await setting("databasePatchedFiles");
if (! databasePatchedFiles) {
databasePatchedFiles = {};
}
debug("Patched files:");
debug(databasePatchedFiles);
try {
for (let sqlFilename in this.patchList) {
await this.patch2Recursion(sqlFilename, databasePatchedFiles);
}
if (this.patched) {
console.log("Database Patched Successfully");
}
} catch (ex) {
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");
this.restore();
process.exit(1);
}
await setSetting("databasePatchedFiles", databasePatchedFiles);
}
/**
* Used it patch2() only
* @param sqlFilename
* @param databasePatchedFiles
*/
static async patch2Recursion(sqlFilename, databasePatchedFiles) {
let value = this.patchList[sqlFilename];
if (! value) {
console.log(sqlFilename + " skip");
return;
}
// Check if patched
if (! databasePatchedFiles[sqlFilename]) {
console.log(sqlFilename + " is not patched");
if (value.parents) {
console.log(sqlFilename + " need parents");
for (let parentSQLFilename of value.parents) {
await this.patch2Recursion(parentSQLFilename, databasePatchedFiles);
}
}
this.backup(dayjs().format("YYYYMMDDHHmmss"));
console.log(sqlFilename + " is patching");
this.patched = true;
await this.importSQLFile("./db/" + sqlFilename);
databasePatchedFiles[sqlFilename] = true;
console.log(sqlFilename + " is patched successfully");
} else {
debug(sqlFilename + " is already patched, skip");
}
}
/**
* Sadly, multi sql statements is not supported by many sqlite libraries, I have to implement it myself
* @param filename
* @returns {Promise<void>}
*/
static async importSQLFile(filename) {
await R.getCell("SELECT 1");
let text = fs.readFileSync(filename).toString();
// Remove all comments (--)
let lines = text.split("\n");
lines = lines.filter((line) => {
return ! line.startsWith("--");
});
// Split statements by semicolon
// Filter out empty line
text = lines.join("\n");
let statements = text.split(";")
.map((statement) => {
return statement.trim();
})
.filter((statement) => {
return statement !== "";
});
for (let statement of statements) {
await R.exec(statement);
}
}
static getBetterSQLite3Database() {
return R.knex.client.acquireConnection();
}
/**
* Special handle, because tarn.js throw a promise reject that cannot be caught
* @returns {Promise<void>}
*/
static async close() {
const listener = (reason, p) => {
Database.noReject = false;
};
process.addListener("unhandledRejection", listener);
console.log("Closing DB");
while (true) {
Database.noReject = true;
await R.close();
await sleep(2000);
if (Database.noReject) {
break;
} else {
console.log("Waiting to close the db");
}
}
console.log("SQLite closed");
process.removeListener("unhandledRejection", listener);
}
/**
* One backup one time in this process.
* Reset this.backupPath if you want to backup again
* @param version
*/
static backup(version) {
if (! this.backupPath) {
console.info("Backup the db");
this.backupPath = this.dataDir + "kuma.db.bak" + version;
fs.copyFileSync(Database.path, this.backupPath);
const shmPath = Database.path + "-shm";
if (fs.existsSync(shmPath)) {
this.backupShmPath = shmPath + ".bak" + version;
fs.copyFileSync(shmPath, this.backupShmPath);
}
const walPath = Database.path + "-wal";
if (fs.existsSync(walPath)) {
this.backupWalPath = walPath + ".bak" + version;
fs.copyFileSync(walPath, this.backupWalPath);
}
}
}
/**
*
*/
static restore() {
if (this.backupPath) {
console.error("Patch db failed!!! Restoring the backup");
const shmPath = Database.path + "-shm";
const walPath = Database.path + "-wal";
// Delete patch failed db
try {
if (fs.existsSync(Database.path)) {
fs.unlinkSync(Database.path);
}
if (fs.existsSync(shmPath)) {
fs.unlinkSync(shmPath);
}
if (fs.existsSync(walPath)) {
fs.unlinkSync(walPath);
}
} catch (e) {
console.log("Restore failed, you may need to restore the backup manually");
process.exit(1);
}
// Restore backup
fs.copyFileSync(this.backupPath, Database.path);
if (this.backupShmPath) {
fs.copyFileSync(this.backupShmPath, shmPath);
}
if (this.backupWalPath) {
fs.copyFileSync(this.backupWalPath, walPath);
}
} else {
console.log("Nothing to restore");
}
}
}
module.exports = Database;

57
server/image-data-uri.js Normal file
View File

@@ -0,0 +1,57 @@
/*
From https://github.com/DiegoZoracKy/image-data-uri/blob/master/lib/image-data-uri.js
Modified with 0 dependencies
*/
let fs = require("fs");
let ImageDataURI = (() => {
function decode(dataURI) {
if (!/data:image\//.test(dataURI)) {
console.log("ImageDataURI :: Error :: It seems that it is not an Image Data URI. Couldn't match \"data:image/\"");
return null;
}
let regExMatches = dataURI.match("data:(image/.*);base64,(.*)");
return {
imageType: regExMatches[1],
dataBase64: regExMatches[2],
dataBuffer: new Buffer(regExMatches[2], "base64")
};
}
function encode(data, mediaType) {
if (!data || !mediaType) {
console.log("ImageDataURI :: Error :: Missing some of the required params: data, mediaType ");
return null;
}
mediaType = (/\//.test(mediaType)) ? mediaType : "image/" + mediaType;
let dataBase64 = (Buffer.isBuffer(data)) ? data.toString("base64") : new Buffer(data).toString("base64");
let dataImgBase64 = "data:" + mediaType + ";base64," + dataBase64;
return dataImgBase64;
}
function outputFile(dataURI, filePath) {
filePath = filePath || "./";
return new Promise((resolve, reject) => {
let imageDecoded = decode(dataURI);
fs.writeFile(filePath, imageDecoded.dataBuffer, err => {
if (err) {
return reject("ImageDataURI :: Error :: " + JSON.stringify(err, null, 4));
}
resolve(filePath);
});
});
}
return {
decode: decode,
encode: encode,
outputFile: outputFile,
};
})();
module.exports = ImageDataURI;

34
server/model/group.js Normal file
View File

@@ -0,0 +1,34 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const { R } = require("redbean-node");
class Group extends BeanModel {
async toPublicJSON() {
let monitorBeanList = await this.getMonitorList();
let monitorList = [];
for (let bean of monitorBeanList) {
monitorList.push(await bean.toPublicJSON());
}
return {
id: this.id,
name: this.name,
weight: this.weight,
monitorList,
};
}
async getMonitorList() {
return R.convertToBeans("monitor", await R.getAll(`
SELECT monitor.* FROM monitor, monitor_group
WHERE monitor.id = monitor_group.monitor_id
AND group_id = ?
ORDER BY monitor_group.weight
`, [
this.id,
]));
}
}
module.exports = Group;

View File

@@ -1,20 +1,27 @@
const dayjs = require("dayjs");
const utc = require('dayjs/plugin/utc')
var timezone = require('dayjs/plugin/timezone')
dayjs.extend(utc)
dayjs.extend(timezone)
const axios = require("axios");
const {R} = require("redbean-node");
const {BeanModel} = require("redbean-node/dist/bean-model");
const utc = require("dayjs/plugin/utc");
let timezone = require("dayjs/plugin/timezone");
dayjs.extend(utc);
dayjs.extend(timezone);
const { BeanModel } = require("redbean-node/dist/bean-model");
/**
* status:
* 0 = DOWN
* 1 = UP
* 2 = PENDING
*/
class Heartbeat extends BeanModel {
toPublicJSON() {
return {
status: this.status,
time: this.time,
msg: "", // Hide for public
ping: this.ping,
};
}
toJSON() {
return {
monitorID: this.monitor_id,

18
server/model/incident.js Normal file
View File

@@ -0,0 +1,18 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
class Incident extends BeanModel {
toPublicJSON() {
return {
id: this.id,
style: this.style,
title: this.title,
content: this.content,
pin: this.pin,
createdDate: this.createdDate,
lastUpdatedDate: this.lastUpdatedDate,
};
}
}
module.exports = Incident;

View File

@@ -1,161 +1,396 @@
const https = require("https");
const dayjs = require("dayjs");
const utc = require('dayjs/plugin/utc')
var timezone = require('dayjs/plugin/timezone')
dayjs.extend(utc)
dayjs.extend(timezone)
const utc = require("dayjs/plugin/utc");
let timezone = require("dayjs/plugin/timezone");
dayjs.extend(utc);
dayjs.extend(timezone);
const axios = require("axios");
const {tcping, ping} = require("../util-server");
const {R} = require("redbean-node");
const {BeanModel} = require("redbean-node/dist/bean-model");
const {Notification} = require("../notification")
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 { R } = require("redbean-node");
const { BeanModel } = require("redbean-node/dist/bean-model");
const { Notification } = require("../notification");
const version = require("../../package.json").version;
/**
* status:
* 0 = DOWN
* 1 = UP
* 2 = PENDING
*/
class Monitor extends BeanModel {
/**
* Return a object that ready to parse to JSON for public
* Only show necessary data to public
*/
async toPublicJSON() {
return {
id: this.id,
name: this.name,
};
}
/**
* Return a object that ready to parse to JSON
*/
async toJSON() {
let notificationIDList = {};
let list = await R.find("monitor_notification", " monitor_id = ? ", [
this.id
])
this.id,
]);
for (let bean of list) {
notificationIDList[bean.notification_id] = true;
}
const tags = await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ?", [this.id]);
return {
id: this.id,
name: this.name,
url: this.url,
hostname: this.hostname,
port: this.port,
maxretries: this.maxretries,
weight: this.weight,
active: this.active,
type: this.type,
interval: this.interval,
retryInterval: this.retryInterval,
keyword: this.keyword,
notificationIDList
ignoreTls: this.getIgnoreTls(),
upsideDown: this.isUpsideDown(),
maxredirects: this.maxredirects,
accepted_statuscodes: this.getAcceptedStatuscodes(),
dns_resolve_type: this.dns_resolve_type,
dns_resolve_server: this.dns_resolve_server,
dns_last_result: this.dns_last_result,
notificationIDList,
tags: tags,
};
}
/**
* Parse to boolean
* @returns {boolean}
*/
getIgnoreTls() {
return Boolean(this.ignoreTls);
}
/**
* Parse to boolean
* @returns {boolean}
*/
isUpsideDown() {
return Boolean(this.upsideDown);
}
getAcceptedStatuscodes() {
return JSON.parse(this.accepted_statuscodes_json);
}
start(io) {
let previousBeat = null;
let retries = 0;
let prometheus = new Prometheus(this);
const beat = async () => {
console.log(`Monitor ${this.id}: Heartbeat`)
// Expose here for prometheus update
// undefined if not https
let tlsInfo = undefined;
if (! previousBeat) {
previousBeat = await R.findOne("heartbeat", " monitor_id = ? ORDER BY time DESC", [
this.id
])
this.id,
]);
}
let bean = R.dispense("heartbeat")
const isFirstBeat = !previousBeat;
let bean = R.dispense("heartbeat");
bean.monitor_id = this.id;
bean.time = R.isoDateTime(dayjs.utc());
bean.status = 0;
bean.status = DOWN;
if (this.isUpsideDown()) {
bean.status = flipStatus(bean.status);
}
// Duration
if (previousBeat) {
bean.duration = dayjs(bean.time).diff(dayjs(previousBeat.time), 'second');
if (! isFirstBeat) {
bean.duration = dayjs(bean.time).diff(dayjs(previousBeat.time), "second");
} else {
bean.duration = 0;
}
try {
if (this.type === "http" || this.type === "keyword") {
// Do not do any queries/high loading things before the "bean.ping"
let startTime = dayjs().valueOf();
let res = await axios.get(this.url)
bean.msg = `${res.status} - ${res.statusText}`
let res = await axios.get(this.url, {
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());
},
});
bean.msg = `${res.status} - ${res.statusText}`;
bean.ping = dayjs().valueOf() - startTime;
// Check certificate if https is used
let certInfoStartTime = dayjs().valueOf();
if (this.getUrl()?.protocol === "https:") {
try {
tlsInfo = await this.updateTlsInfo(checkCertificate(res));
} catch (e) {
if (e.message !== "No TLS certificate in response") {
console.error(e.message);
}
}
}
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
if (this.type === "http") {
bean.status = 1;
bean.status = UP;
} else {
if (res.data.includes(this.keyword)) {
bean.msg += ", keyword is found"
bean.status = 1;
let data = res.data;
// Convert to string for object/array
if (typeof data !== "string") {
data = JSON.stringify(data);
}
if (data.includes(this.keyword)) {
bean.msg += ", keyword is found";
bean.status = UP;
} else {
throw new Error(bean.msg + ", but keyword is not found")
throw new Error(bean.msg + ", but keyword is not found");
}
}
} else if (this.type === "port") {
bean.ping = await tcping(this.hostname, this.port);
bean.msg = ""
bean.status = 1;
bean.msg = "";
bean.status = UP;
} else if (this.type === "ping") {
bean.ping = await ping(this.hostname);
bean.msg = ""
bean.status = 1;
bean.msg = "";
bean.status = UP;
} else if (this.type === "dns") {
let startTime = dayjs().valueOf();
let dnsMessage = "";
let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.dns_resolve_type);
bean.ping = dayjs().valueOf() - startTime;
if (this.dns_resolve_type == "A" || this.dns_resolve_type == "AAAA" || this.dns_resolve_type == "TXT") {
dnsMessage += "Records: ";
dnsMessage += dnsRes.join(" | ");
} else if (this.dns_resolve_type == "CNAME" || this.dns_resolve_type == "PTR") {
dnsMessage = dnsRes[0];
} else if (this.dns_resolve_type == "CAA") {
dnsMessage = dnsRes[0].issue;
} else if (this.dns_resolve_type == "MX") {
dnsRes.forEach(record => {
dnsMessage += `Hostname: ${record.exchange} - Priority: ${record.priority} | `;
});
dnsMessage = dnsMessage.slice(0, -2);
} else if (this.dns_resolve_type == "NS") {
dnsMessage += "Servers: ";
dnsMessage += dnsRes.join(" | ");
} else if (this.dns_resolve_type == "SOA") {
dnsMessage += `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`;
} else if (this.dns_resolve_type == "SRV") {
dnsRes.forEach(record => {
dnsMessage += `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight} | `;
});
dnsMessage = dnsMessage.slice(0, -2);
}
if (this.dnsLastResult !== dnsMessage) {
R.exec("UPDATE `monitor` SET dns_last_result = ? WHERE id = ? ", [
dnsMessage,
this.id
]);
}
bean.msg = dnsMessage;
bean.status = UP;
}
if (this.isUpsideDown()) {
bean.status = flipStatus(bean.status);
if (bean.status === DOWN) {
throw new Error("Flip UP to DOWN");
}
}
retries = 0;
} catch (error) {
bean.msg = error.message;
// If UP come in here, it must be upside down mode
// Just reset the retries
if (this.isUpsideDown() && bean.status === UP) {
retries = 0;
} else if ((this.maxretries > 0) && (retries < this.maxretries)) {
retries++;
bean.status = PENDING;
}
}
// Mark as important if status changed
if (! previousBeat || previousBeat.status !== bean.status) {
// * ? -> ANY STATUS = important [isFirstBeat]
// UP -> PENDING = not important
// * UP -> DOWN = important
// UP -> UP = not important
// PENDING -> PENDING = not important
// * PENDING -> DOWN = important
// PENDING -> UP = not important
// DOWN -> PENDING = this case not exists
// DOWN -> DOWN = not important
// * DOWN -> UP = important
let isImportant = isFirstBeat ||
(previousBeat.status === UP && bean.status === DOWN) ||
(previousBeat.status === DOWN && bean.status === UP) ||
(previousBeat.status === PENDING && bean.status === DOWN);
// Mark as important if status changed, ignore pending pings,
// Don't notify if disrupted changes to up
if (isImportant) {
bean.important = true;
// Do not send if first beat is UP
if (previousBeat || bean.status !== 1) {
let notificationList = await R.getAll(`SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id `, [
this.id
])
let promiseList = [];
// Send only if the first beat is DOWN
if (!isFirstBeat || bean.status === DOWN) {
let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [
this.id,
]);
let text;
if (bean.status === 1) {
text = "✅ Up"
if (bean.status === UP) {
text = "✅ Up";
} else {
text = "🔴 Down"
text = "🔴 Down";
}
let msg = `[${this.name}] [${text}] ${bean.msg}`;
for(let notification of notificationList) {
promiseList.push(Notification.send(JSON.parse(notification.config), msg, await this.toJSON(), bean.toJSON()));
for (let notification of notificationList) {
try {
await Notification.send(JSON.parse(notification.config), msg, await this.toJSON(), bean.toJSON());
} catch (e) {
console.error("Cannot send notification to " + notification.name);
console.log(e);
}
}
await Promise.all(promiseList);
}
} else {
bean.important = false;
}
io.to(this.user_id).emit("heartbeat", bean.toJSON());
let beatInterval = this.interval;
await R.store(bean)
Monitor.sendStats(io, this.id, this.user_id)
if (bean.status === UP) {
console.info(`Monitor #${this.id} '${this.name}': Successful Response: ${bean.ping} ms | Interval: ${beatInterval} seconds | Type: ${this.type}`);
} else if (bean.status === PENDING) {
if (this.retryInterval > 0) {
beatInterval = this.retryInterval;
}
console.warn(`Monitor #${this.id} '${this.name}': Pending: ${bean.msg} | Max retries: ${this.maxretries} | Retry: ${retries} | Retry Interval: ${beatInterval} seconds | Type: ${this.type}`);
} else {
console.warn(`Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type}`);
}
io.to(this.user_id).emit("heartbeat", bean.toJSON());
Monitor.sendStats(io, this.id, this.user_id);
await R.store(bean);
prometheus.update(bean, tlsInfo);
previousBeat = bean;
}
if (! this.isStop) {
this.heartbeatInterval = setTimeout(beat, beatInterval * 1000);
}
};
beat();
this.heartbeatInterval = setInterval(beat, this.interval * 1000);
}
stop() {
clearInterval(this.heartbeatInterval)
clearTimeout(this.heartbeatInterval);
this.isStop = true;
}
/**
* Helper Method:
* returns URL object for further usage
* returns null if url is invalid
* @returns {null|URL}
*/
getUrl() {
try {
return new URL(this.url);
} catch (_) {
return null;
}
}
/**
* Store TLS info to database
* @param checkCertificateResult
* @returns {Promise<object>}
*/
async updateTlsInfo(checkCertificateResult) {
let tls_info_bean = await R.findOne("monitor_tls_info", "monitor_id = ?", [
this.id,
]);
if (tls_info_bean == null) {
tls_info_bean = R.dispense("monitor_tls_info");
tls_info_bean.monitor_id = this.id;
}
tls_info_bean.info_json = JSON.stringify(checkCertificateResult);
await R.store(tls_info_bean);
return checkCertificateResult;
}
static async sendStats(io, monitorID, userID) {
Monitor.sendAvgPing(24, io, monitorID, userID);
Monitor.sendUptime(24, io, monitorID, userID);
Monitor.sendUptime(24 * 30, io, monitorID, userID);
const hasClients = getTotalClientInRoom(io, userID) > 0;
if (hasClients) {
await Monitor.sendAvgPing(24, io, monitorID, userID);
await Monitor.sendUptime(24, io, monitorID, userID);
await Monitor.sendUptime(24 * 30, io, monitorID, userID);
await Monitor.sendCertInfo(io, monitorID, userID);
} else {
debug("No clients in the room, no need to send stats");
}
}
/**
@@ -163,6 +398,8 @@ class Monitor extends BeanModel {
* @param duration : int Hours
*/
static async sendAvgPing(duration, io, monitorID, userID) {
const timeLogger = new TimeLogger();
let avgPing = parseInt(await R.getCell(`
SELECT AVG(ping)
FROM heartbeat
@@ -170,74 +407,97 @@ class Monitor extends BeanModel {
AND ping IS NOT NULL
AND monitor_id = ? `, [
-duration,
monitorID
monitorID,
]));
timeLogger.print(`[Monitor: ${monitorID}] avgPing`);
io.to(userID).emit("avgPing", monitorID, avgPing);
}
static async sendCertInfo(io, monitorID, userID) {
let tls_info = await R.findOne("monitor_tls_info", "monitor_id = ?", [
monitorID,
]);
if (tls_info != null) {
io.to(userID).emit("certInfo", monitorID, tls_info.info_json);
}
}
/**
* Uptime with calculation
* Calculation based on:
* https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime
* @param duration : int Hours
*/
static async sendUptime(duration, io, monitorID, userID) {
let sec = duration * 3600;
static async calcUptime(duration, monitorID) {
const timeLogger = new TimeLogger();
let heartbeatList = await R.getAll(`
SELECT duration, time, status
const startTime = R.isoDateTime(dayjs.utc().subtract(duration, "hour"));
// Handle if heartbeat duration longer than the target duration
// e.g. If the last beat's duration is bigger that the 24hrs window, it will use the duration between the (beat time - window margin) (THEN case in SQL)
let result = await R.getRow(`
SELECT
-- SUM all duration, also trim off the beat out of time window
SUM(
CASE
WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration
THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400
ELSE duration
END
) AS total_duration,
-- SUM all uptime duration, also trim off the beat out of time window
SUM(
CASE
WHEN (status = 1)
THEN
CASE
WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration
THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400
ELSE duration
END
END
) AS uptime_duration
FROM heartbeat
WHERE time > DATETIME('now', ? || ' hours')
AND monitor_id = ? `, [
-duration,
monitorID
WHERE time > ?
AND monitor_id = ?
`, [
startTime, startTime, startTime, startTime, startTime,
monitorID,
]);
let downtime = 0;
let total = 0;
let uptime;
timeLogger.print(`[Monitor: ${monitorID}][${duration}] sendUptime`);
// Special handle for the first heartbeat only
if (heartbeatList.length === 1) {
let totalDuration = result.total_duration;
let uptimeDuration = result.uptime_duration;
let uptime = 0;
if (heartbeatList[0].status === 1) {
uptime = 1;
} else {
if (totalDuration > 0) {
uptime = uptimeDuration / totalDuration;
if (uptime < 0) {
uptime = 0;
}
} else {
for (let row of heartbeatList) {
let value = parseInt(row.duration)
let time = row.time
// Handle new monitor with only one beat, because the beat's duration = 0
let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [ monitorID ]));
// Handle if heartbeat duration longer than the target duration
// e.g. Heartbeat duration = 28hrs, but target duration = 24hrs
if (value > sec) {
let trim = dayjs.utc().diff(dayjs(time), 'second');
value = sec - trim;
if (value < 0) {
value = 0;
}
}
total += value;
if (row.status === 0) {
downtime += value;
}
}
uptime = (total - downtime) / total;
if (uptime < 0) {
uptime = 0;
if (status === UP) {
uptime = 1;
}
}
return uptime;
}
/**
* Send Uptime
* @param duration : int Hours
*/
static async sendUptime(duration, io, monitorID, userID) {
const uptime = await this.calcUptime(duration, monitorID);
io.to(userID).emit("uptime", monitorID, duration, uptime);
}
}

13
server/model/tag.js Normal file
View File

@@ -0,0 +1,13 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
class Tag extends BeanModel {
toJSON() {
return {
id: this._id,
name: this._name,
color: this._color,
};
}
}
module.exports = Tag;

21
server/model/user.js Normal file
View File

@@ -0,0 +1,21 @@
const { BeanModel } = require("redbean-node/dist/bean-model");
const passwordHash = require("../password-hash");
const { R } = require("redbean-node");
class User extends BeanModel {
/**
* Direct execute, no need R.store()
* @param newPassword
* @returns {Promise<void>}
*/
async resetPassword(newPassword) {
await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [
passwordHash.generate(newPassword),
this.id
]);
this.password = newPassword;
}
}
module.exports = User;

View File

@@ -0,0 +1,749 @@
let url = require("url");
let MemoryCache = require("./memory-cache");
let t = {
ms: 1,
second: 1000,
minute: 60000,
hour: 3600000,
day: 3600000 * 24,
week: 3600000 * 24 * 7,
month: 3600000 * 24 * 30,
};
let instances = [];
let matches = function (a) {
return function (b) {
return a === b;
};
};
let doesntMatch = function (a) {
return function (b) {
return !matches(a)(b);
};
};
let logDuration = function (d, prefix) {
let str = d > 1000 ? (d / 1000).toFixed(2) + "sec" : d + "ms";
return "\x1b[33m- " + (prefix ? prefix + " " : "") + str + "\x1b[0m";
};
function getSafeHeaders(res) {
return res.getHeaders ? res.getHeaders() : res._headers;
}
function ApiCache() {
let memCache = new MemoryCache();
let globalOptions = {
debug: false,
defaultDuration: 3600000,
enabled: true,
appendKey: [],
jsonp: false,
redisClient: false,
headerBlacklist: [],
statusCodes: {
include: [],
exclude: [],
},
events: {
expire: undefined,
},
headers: {
// 'cache-control': 'no-cache' // example of header overwrite
},
trackPerformance: false,
respectCacheControl: false,
};
let middlewareOptions = [];
let instance = this;
let index = null;
let timers = {};
let performanceArray = []; // for tracking cache hit rate
instances.push(this);
this.id = instances.length;
function debug(a, b, c, d) {
let arr = ["\x1b[36m[apicache]\x1b[0m", a, b, c, d].filter(function (arg) {
return arg !== undefined;
});
let debugEnv = process.env.DEBUG && process.env.DEBUG.split(",").indexOf("apicache") !== -1;
return (globalOptions.debug || debugEnv) && console.log.apply(null, arr);
}
function shouldCacheResponse(request, response, toggle) {
let opt = globalOptions;
let codes = opt.statusCodes;
if (!response) {
return false;
}
if (toggle && !toggle(request, response)) {
return false;
}
if (codes.exclude && codes.exclude.length && codes.exclude.indexOf(response.statusCode) !== -1) {
return false;
}
if (codes.include && codes.include.length && codes.include.indexOf(response.statusCode) === -1) {
return false;
}
return true;
}
function addIndexEntries(key, req) {
let groupName = req.apicacheGroup;
if (groupName) {
debug("group detected \"" + groupName + "\"");
let group = (index.groups[groupName] = index.groups[groupName] || []);
group.unshift(key);
}
index.all.unshift(key);
}
function filterBlacklistedHeaders(headers) {
return Object.keys(headers)
.filter(function (key) {
return globalOptions.headerBlacklist.indexOf(key) === -1;
})
.reduce(function (acc, header) {
acc[header] = headers[header];
return acc;
}, {});
}
function createCacheObject(status, headers, data, encoding) {
return {
status: status,
headers: filterBlacklistedHeaders(headers),
data: data,
encoding: encoding,
timestamp: new Date().getTime() / 1000, // seconds since epoch. This is used to properly decrement max-age headers in cached responses.
};
}
function cacheResponse(key, value, duration) {
let redis = globalOptions.redisClient;
let expireCallback = globalOptions.events.expire;
if (redis && redis.connected) {
try {
redis.hset(key, "response", JSON.stringify(value));
redis.hset(key, "duration", duration);
redis.expire(key, duration / 1000, expireCallback || function () {});
} catch (err) {
debug("[apicache] error in redis.hset()");
}
} else {
memCache.add(key, value, duration, expireCallback);
}
// add automatic cache clearing from duration, includes max limit on setTimeout
timers[key] = setTimeout(function () {
instance.clear(key, true);
}, Math.min(duration, 2147483647));
}
function accumulateContent(res, content) {
if (content) {
if (typeof content == "string") {
res._apicache.content = (res._apicache.content || "") + content;
} else if (Buffer.isBuffer(content)) {
let oldContent = res._apicache.content;
if (typeof oldContent === "string") {
oldContent = !Buffer.from ? new Buffer(oldContent) : Buffer.from(oldContent);
}
if (!oldContent) {
oldContent = !Buffer.alloc ? new Buffer(0) : Buffer.alloc(0);
}
res._apicache.content = Buffer.concat(
[oldContent, content],
oldContent.length + content.length
);
} else {
res._apicache.content = content;
}
}
}
function makeResponseCacheable(req, res, next, key, duration, strDuration, toggle) {
// monkeypatch res.end to create cache object
res._apicache = {
write: res.write,
writeHead: res.writeHead,
end: res.end,
cacheable: true,
content: undefined,
};
// append header overwrites if applicable
Object.keys(globalOptions.headers).forEach(function (name) {
res.setHeader(name, globalOptions.headers[name]);
});
res.writeHead = function () {
// add cache control headers
if (!globalOptions.headers["cache-control"]) {
if (shouldCacheResponse(req, res, toggle)) {
res.setHeader("cache-control", "max-age=" + (duration / 1000).toFixed(0));
} else {
res.setHeader("cache-control", "no-cache, no-store, must-revalidate");
}
}
res._apicache.headers = Object.assign({}, getSafeHeaders(res));
return res._apicache.writeHead.apply(this, arguments);
};
// patch res.write
res.write = function (content) {
accumulateContent(res, content);
return res._apicache.write.apply(this, arguments);
};
// patch res.end
res.end = function (content, encoding) {
if (shouldCacheResponse(req, res, toggle)) {
accumulateContent(res, content);
if (res._apicache.cacheable && res._apicache.content) {
addIndexEntries(key, req);
let headers = res._apicache.headers || getSafeHeaders(res);
let cacheObject = createCacheObject(
res.statusCode,
headers,
res._apicache.content,
encoding
);
cacheResponse(key, cacheObject, duration);
// display log entry
let elapsed = new Date() - req.apicacheTimer;
debug("adding cache entry for \"" + key + "\" @ " + strDuration, logDuration(elapsed));
debug("_apicache.headers: ", res._apicache.headers);
debug("res.getHeaders(): ", getSafeHeaders(res));
debug("cacheObject: ", cacheObject);
}
}
return res._apicache.end.apply(this, arguments);
};
next();
}
function sendCachedResponse(request, response, cacheObject, toggle, next, duration) {
if (toggle && !toggle(request, response)) {
return next();
}
let headers = getSafeHeaders(response);
// Modified by @louislam, removed Cache-control, since I don't need client side cache!
// Original Source: https://github.com/kwhitley/apicache/blob/0d5686cc21fad353c6dddee646288c2fca3e4f50/src/apicache.js#L254
Object.assign(headers, filterBlacklistedHeaders(cacheObject.headers || {}));
// only embed apicache headers when not in production environment
if (process.env.NODE_ENV !== "production") {
Object.assign(headers, {
"apicache-store": globalOptions.redisClient ? "redis" : "memory",
"apicache-version": "1.6.2-modified",
});
}
// unstringify buffers
let data = cacheObject.data;
if (data && data.type === "Buffer") {
data =
typeof data.data === "number" ? new Buffer.alloc(data.data) : new Buffer.from(data.data);
}
// test Etag against If-None-Match for 304
let cachedEtag = cacheObject.headers.etag;
let requestEtag = request.headers["if-none-match"];
if (requestEtag && cachedEtag === requestEtag) {
response.writeHead(304, headers);
return response.end();
}
response.writeHead(cacheObject.status || 200, headers);
return response.end(data, cacheObject.encoding);
}
function syncOptions() {
for (let i in middlewareOptions) {
Object.assign(middlewareOptions[i].options, globalOptions, middlewareOptions[i].localOptions);
}
}
this.clear = function (target, isAutomatic) {
let group = index.groups[target];
let redis = globalOptions.redisClient;
if (group) {
debug("clearing group \"" + target + "\"");
group.forEach(function (key) {
debug("clearing cached entry for \"" + key + "\"");
clearTimeout(timers[key]);
delete timers[key];
if (!globalOptions.redisClient) {
memCache.delete(key);
} else {
try {
redis.del(key);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + key + "\")");
}
}
index.all = index.all.filter(doesntMatch(key));
});
delete index.groups[target];
} else if (target) {
debug("clearing " + (isAutomatic ? "expired" : "cached") + " entry for \"" + target + "\"");
clearTimeout(timers[target]);
delete timers[target];
// clear actual cached entry
if (!redis) {
memCache.delete(target);
} else {
try {
redis.del(target);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + target + "\")");
}
}
// remove from global index
index.all = index.all.filter(doesntMatch(target));
// remove target from each group that it may exist in
Object.keys(index.groups).forEach(function (groupName) {
index.groups[groupName] = index.groups[groupName].filter(doesntMatch(target));
// delete group if now empty
if (!index.groups[groupName].length) {
delete index.groups[groupName];
}
});
} else {
debug("clearing entire index");
if (!redis) {
memCache.clear();
} else {
// clear redis keys one by one from internal index to prevent clearing non-apicache entries
index.all.forEach(function (key) {
clearTimeout(timers[key]);
delete timers[key];
try {
redis.del(key);
} catch (err) {
console.log("[apicache] error in redis.del(\"" + key + "\")");
}
});
}
this.resetIndex();
}
return this.getIndex();
};
function parseDuration(duration, defaultDuration) {
if (typeof duration === "number") {
return duration;
}
if (typeof duration === "string") {
let split = duration.match(/^([\d\.,]+)\s?(\w+)$/);
if (split.length === 3) {
let len = parseFloat(split[1]);
let unit = split[2].replace(/s$/i, "").toLowerCase();
if (unit === "m") {
unit = "ms";
}
return (len || 1) * (t[unit] || 0);
}
}
return defaultDuration;
}
this.getDuration = function (duration) {
return parseDuration(duration, globalOptions.defaultDuration);
};
/**
* Return cache performance statistics (hit rate). Suitable for putting into a route:
* <code>
* app.get('/api/cache/performance', (req, res) => {
* res.json(apicache.getPerformance())
* })
* </code>
*/
this.getPerformance = function () {
return performanceArray.map(function (p) {
return p.report();
});
};
this.getIndex = function (group) {
if (group) {
return index.groups[group];
} else {
return index;
}
};
this.middleware = function cache(strDuration, middlewareToggle, localOptions) {
let duration = instance.getDuration(strDuration);
let opt = {};
middlewareOptions.push({
options: opt,
});
let options = function (localOptions) {
if (localOptions) {
middlewareOptions.find(function (middleware) {
return middleware.options === opt;
}).localOptions = localOptions;
}
syncOptions();
return opt;
};
options(localOptions);
/**
* A Function for non tracking performance
*/
function NOOPCachePerformance() {
this.report = this.hit = this.miss = function () {}; // noop;
}
/**
* A function for tracking and reporting hit rate. These statistics are returned by the getPerformance() call above.
*/
function CachePerformance() {
/**
* Tracks the hit rate for the last 100 requests.
* If there have been fewer than 100 requests, the hit rate just considers the requests that have happened.
*/
this.hitsLast100 = new Uint8Array(100 / 4); // each hit is 2 bits
/**
* Tracks the hit rate for the last 1000 requests.
* If there have been fewer than 1000 requests, the hit rate just considers the requests that have happened.
*/
this.hitsLast1000 = new Uint8Array(1000 / 4); // each hit is 2 bits
/**
* Tracks the hit rate for the last 10000 requests.
* If there have been fewer than 10000 requests, the hit rate just considers the requests that have happened.
*/
this.hitsLast10000 = new Uint8Array(10000 / 4); // each hit is 2 bits
/**
* Tracks the hit rate for the last 100000 requests.
* If there have been fewer than 100000 requests, the hit rate just considers the requests that have happened.
*/
this.hitsLast100000 = new Uint8Array(100000 / 4); // each hit is 2 bits
/**
* The number of calls that have passed through the middleware since the server started.
*/
this.callCount = 0;
/**
* The total number of hits since the server started
*/
this.hitCount = 0;
/**
* The key from the last cache hit. This is useful in identifying which route these statistics apply to.
*/
this.lastCacheHit = null;
/**
* The key from the last cache miss. This is useful in identifying which route these statistics apply to.
*/
this.lastCacheMiss = null;
/**
* Return performance statistics
*/
this.report = function () {
return {
lastCacheHit: this.lastCacheHit,
lastCacheMiss: this.lastCacheMiss,
callCount: this.callCount,
hitCount: this.hitCount,
missCount: this.callCount - this.hitCount,
hitRate: this.callCount == 0 ? null : this.hitCount / this.callCount,
hitRateLast100: this.hitRate(this.hitsLast100),
hitRateLast1000: this.hitRate(this.hitsLast1000),
hitRateLast10000: this.hitRate(this.hitsLast10000),
hitRateLast100000: this.hitRate(this.hitsLast100000),
};
};
/**
* Computes a cache hit rate from an array of hits and misses.
* @param {Uint8Array} array An array representing hits and misses.
* @returns a number between 0 and 1, or null if the array has no hits or misses
*/
this.hitRate = function (array) {
let hits = 0;
let misses = 0;
for (let i = 0; i < array.length; i++) {
let n8 = array[i];
for (let j = 0; j < 4; j++) {
switch (n8 & 3) {
case 1:
hits++;
break;
case 2:
misses++;
break;
}
n8 >>= 2;
}
}
let total = hits + misses;
if (total == 0) {
return null;
}
return hits / total;
};
/**
* Record a hit or miss in the given array. It will be recorded at a position determined
* by the current value of the callCount variable.
* @param {Uint8Array} array An array representing hits and misses.
* @param {boolean} hit true for a hit, false for a miss
* Each element in the array is 8 bits, and encodes 4 hit/miss records.
* Each hit or miss is encoded as to bits as follows:
* 00 means no hit or miss has been recorded in these bits
* 01 encodes a hit
* 10 encodes a miss
*/
this.recordHitInArray = function (array, hit) {
let arrayIndex = ~~(this.callCount / 4) % array.length;
let bitOffset = (this.callCount % 4) * 2; // 2 bits per record, 4 records per uint8 array element
let clearMask = ~(3 << bitOffset);
let record = (hit ? 1 : 2) << bitOffset;
array[arrayIndex] = (array[arrayIndex] & clearMask) | record;
};
/**
* Records the hit or miss in the tracking arrays and increments the call count.
* @param {boolean} hit true records a hit, false records a miss
*/
this.recordHit = function (hit) {
this.recordHitInArray(this.hitsLast100, hit);
this.recordHitInArray(this.hitsLast1000, hit);
this.recordHitInArray(this.hitsLast10000, hit);
this.recordHitInArray(this.hitsLast100000, hit);
if (hit) {
this.hitCount++;
}
this.callCount++;
};
/**
* Records a hit event, setting lastCacheMiss to the given key
* @param {string} key The key that had the cache hit
*/
this.hit = function (key) {
this.recordHit(true);
this.lastCacheHit = key;
};
/**
* Records a miss event, setting lastCacheMiss to the given key
* @param {string} key The key that had the cache miss
*/
this.miss = function (key) {
this.recordHit(false);
this.lastCacheMiss = key;
};
}
let perf = globalOptions.trackPerformance ? new CachePerformance() : new NOOPCachePerformance();
performanceArray.push(perf);
let cache = function (req, res, next) {
function bypass() {
debug("bypass detected, skipping cache.");
return next();
}
// initial bypass chances
if (!opt.enabled) {
return bypass();
}
if (
req.headers["x-apicache-bypass"] ||
req.headers["x-apicache-force-fetch"] ||
(opt.respectCacheControl && req.headers["cache-control"] == "no-cache")
) {
return bypass();
}
// REMOVED IN 0.11.1 TO CORRECT MIDDLEWARE TOGGLE EXECUTE ORDER
// if (typeof middlewareToggle === 'function') {
// if (!middlewareToggle(req, res)) return bypass()
// } else if (middlewareToggle !== undefined && !middlewareToggle) {
// return bypass()
// }
// embed timer
req.apicacheTimer = new Date();
// In Express 4.x the url is ambigious based on where a router is mounted. originalUrl will give the full Url
let key = req.originalUrl || req.url;
// Remove querystring from key if jsonp option is enabled
if (opt.jsonp) {
key = url.parse(key).pathname;
}
// add appendKey (either custom function or response path)
if (typeof opt.appendKey === "function") {
key += "$$appendKey=" + opt.appendKey(req, res);
} else if (opt.appendKey.length > 0) {
let appendKey = req;
for (let i = 0; i < opt.appendKey.length; i++) {
appendKey = appendKey[opt.appendKey[i]];
}
key += "$$appendKey=" + appendKey;
}
// attempt cache hit
let redis = opt.redisClient;
let cached = !redis ? memCache.getValue(key) : null;
// send if cache hit from memory-cache
if (cached) {
let elapsed = new Date() - req.apicacheTimer;
debug("sending cached (memory-cache) version of", key, logDuration(elapsed));
perf.hit(key);
return sendCachedResponse(req, res, cached, middlewareToggle, next, duration);
}
// send if cache hit from redis
if (redis && redis.connected) {
try {
redis.hgetall(key, function (err, obj) {
if (!err && obj && obj.response) {
let elapsed = new Date() - req.apicacheTimer;
debug("sending cached (redis) version of", key, logDuration(elapsed));
perf.hit(key);
return sendCachedResponse(
req,
res,
JSON.parse(obj.response),
middlewareToggle,
next,
duration
);
} else {
perf.miss(key);
return makeResponseCacheable(
req,
res,
next,
key,
duration,
strDuration,
middlewareToggle
);
}
});
} catch (err) {
// bypass redis on error
perf.miss(key);
return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle);
}
} else {
perf.miss(key);
return makeResponseCacheable(req, res, next, key, duration, strDuration, middlewareToggle);
}
};
cache.options = options;
return cache;
};
this.options = function (options) {
if (options) {
Object.assign(globalOptions, options);
syncOptions();
if ("defaultDuration" in options) {
// Convert the default duration to a number in milliseconds (if needed)
globalOptions.defaultDuration = parseDuration(globalOptions.defaultDuration, 3600000);
}
if (globalOptions.trackPerformance) {
debug("WARNING: using trackPerformance flag can cause high memory usage!");
}
return this;
} else {
return globalOptions;
}
};
this.resetIndex = function () {
index = {
all: [],
groups: {},
};
};
this.newInstance = function (config) {
let instance = new ApiCache();
if (config) {
instance.options(config);
}
return instance;
};
this.clone = function () {
return this.newInstance(this.options());
};
// initialize index
this.resetIndex();
}
module.exports = new ApiCache();

View File

@@ -0,0 +1,14 @@
const apicache = require("./apicache");
apicache.options({
headerBlacklist: [
"cache-control"
],
headers: {
// Disable client side cache, only server side cache.
// BUG! Not working for the second request
"cache-control": "no-cache",
},
});
module.exports = apicache;

View File

@@ -0,0 +1,59 @@
function MemoryCache() {
this.cache = {};
this.size = 0;
}
MemoryCache.prototype.add = function (key, value, time, timeoutCallback) {
let old = this.cache[key];
let instance = this;
let entry = {
value: value,
expire: time + Date.now(),
timeout: setTimeout(function () {
instance.delete(key);
return timeoutCallback && typeof timeoutCallback === "function" && timeoutCallback(value, key);
}, time)
};
this.cache[key] = entry;
this.size = Object.keys(this.cache).length;
return entry;
};
MemoryCache.prototype.delete = function (key) {
let entry = this.cache[key];
if (entry) {
clearTimeout(entry.timeout);
}
delete this.cache[key];
this.size = Object.keys(this.cache).length;
return null;
};
MemoryCache.prototype.get = function (key) {
let entry = this.cache[key];
return entry;
};
MemoryCache.prototype.getValue = function (key) {
let entry = this.get(key);
return entry && entry.value;
};
MemoryCache.prototype.clear = function () {
Object.keys(this.cache).forEach(function (key) {
this.delete(key);
}, this);
return true;
};
module.exports = MemoryCache;

View File

@@ -0,0 +1,26 @@
const NotificationProvider = require("./notification-provider");
const child_process = require("child_process");
class Apprise extends NotificationProvider {
name = "apprise";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let s = child_process.spawnSync("apprise", [ "-vv", "-b", msg, notification.appriseURL])
let output = (s.stdout) ? s.stdout.toString() : "ERROR: maybe apprise not found";
if (output) {
if (! output.includes("ERROR")) {
return "Sent Successfully";
}
throw new Error(output)
} else {
return "No output from apprise";
}
}
}
module.exports = Apprise;

View File

@@ -0,0 +1,115 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Discord extends NotificationProvider {
name = "discord";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
const discordDisplayName = notification.discordUsername || "Uptime Kuma";
// If heartbeatJSON is null, assume we're testing.
if (heartbeatJSON == null) {
let discordtestdata = {
username: discordDisplayName,
content: msg,
}
await axios.post(notification.discordWebhookUrl, discordtestdata)
return okMsg;
}
let url;
if (monitorJSON["type"] === "port") {
url = monitorJSON["hostname"];
if (monitorJSON["port"]) {
url += ":" + monitorJSON["port"];
}
} else {
url = monitorJSON["url"];
}
// If heartbeatJSON is not null, we go into the normal alerting loop.
if (heartbeatJSON["status"] == DOWN) {
let discorddowndata = {
username: discordDisplayName,
embeds: [{
title: "❌ Your service " + monitorJSON["name"] + " went down. ❌",
color: 16711680,
timestamp: heartbeatJSON["time"],
fields: [
{
name: "Service Name",
value: monitorJSON["name"],
},
{
name: "Service URL",
value: url,
},
{
name: "Time (UTC)",
value: heartbeatJSON["time"],
},
{
name: "Error",
value: heartbeatJSON["msg"],
},
],
}],
}
if (notification.discordPrefixMessage) {
discorddowndata.content = notification.discordPrefixMessage;
}
await axios.post(notification.discordWebhookUrl, discorddowndata)
return okMsg;
} else if (heartbeatJSON["status"] == UP) {
let discordupdata = {
username: discordDisplayName,
embeds: [{
title: "✅ Your service " + monitorJSON["name"] + " is up! ✅",
color: 65280,
timestamp: heartbeatJSON["time"],
fields: [
{
name: "Service Name",
value: monitorJSON["name"],
},
{
name: "Service URL",
value: url.startsWith("http") ? "[Visit Service](" + url + ")" : url,
},
{
name: "Time (UTC)",
value: heartbeatJSON["time"],
},
{
name: "Ping",
value: heartbeatJSON["ping"] + "ms",
},
],
}],
}
if (notification.discordPrefixMessage) {
discordupdata.content = notification.discordPrefixMessage;
}
await axios.post(notification.discordWebhookUrl, discordupdata)
return okMsg;
}
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Discord;

View File

@@ -0,0 +1,28 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Gotify extends NotificationProvider {
name = "gotify";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) {
notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1);
}
await axios.post(`${notification.gotifyserverurl}/message?token=${notification.gotifyapplicationToken}`, {
"message": msg,
"priority": notification.gotifyPriority || 8,
"title": "Uptime-Kuma",
})
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Gotify;

View File

@@ -0,0 +1,60 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Line extends NotificationProvider {
name = "line";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
let lineAPIUrl = "https://api.line.me/v2/bot/message/push";
let config = {
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + notification.lineChannelAccessToken
}
};
if (heartbeatJSON == null) {
let testMessage = {
"to": notification.lineUserID,
"messages": [
{
"type": "text",
"text": "Test Successful!"
}
]
}
await axios.post(lineAPIUrl, testMessage, config)
} else if (heartbeatJSON["status"] == DOWN) {
let downMessage = {
"to": notification.lineUserID,
"messages": [
{
"type": "text",
"text": "UptimeKuma Alert: [🔴 Down]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
}
]
}
await axios.post(lineAPIUrl, downMessage, config)
} else if (heartbeatJSON["status"] == UP) {
let upMessage = {
"to": notification.lineUserID,
"messages": [
{
"type": "text",
"text": "UptimeKuma Alert: [✅ Up]\n" + "Name: " + monitorJSON["name"] + " \n" + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"]
}
]
}
await axios.post(lineAPIUrl, upMessage, config)
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Line;

View File

@@ -0,0 +1,48 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class LunaSea extends NotificationProvider {
name = "lunasea";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
let lunaseadevice = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice
try {
if (heartbeatJSON == null) {
let testdata = {
"title": "Uptime Kuma Alert",
"body": "Testing Successful.",
}
await axios.post(lunaseadevice, testdata)
return okMsg;
}
if (heartbeatJSON["status"] == DOWN) {
let downdata = {
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
}
await axios.post(lunaseadevice, downdata)
return okMsg;
}
if (heartbeatJSON["status"] == UP) {
let updata = {
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
}
await axios.post(lunaseadevice, updata)
return okMsg;
}
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = LunaSea;

View File

@@ -0,0 +1,123 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Mattermost extends NotificationProvider {
name = "mattermost";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
const mattermostUserName = notification.mattermostusername || "Uptime Kuma";
// If heartbeatJSON is null, assume we're testing.
if (heartbeatJSON == null) {
let mattermostTestData = {
username: mattermostUserName,
text: msg,
}
await axios.post(notification.mattermostWebhookUrl, mattermostTestData)
return okMsg;
}
const mattermostChannel = notification.mattermostchannel;
const mattermostIconEmoji = notification.mattermosticonemo;
const mattermostIconUrl = notification.mattermosticonurl;
if (heartbeatJSON["status"] == DOWN) {
let mattermostdowndata = {
username: mattermostUserName,
text: "Uptime Kuma Alert",
channel: mattermostChannel,
icon_emoji: mattermostIconEmoji,
icon_url: mattermostIconUrl,
attachments: [
{
fallback:
"Your " +
monitorJSON["name"] +
" service went down.",
color: "#FF0000",
title:
"❌ " +
monitorJSON["name"] +
" service went down. ❌",
title_link: monitorJSON["url"],
fields: [
{
short: true,
title: "Service Name",
value: monitorJSON["name"],
},
{
short: true,
title: "Time (UTC)",
value: heartbeatJSON["time"],
},
{
short: false,
title: "Error",
value: heartbeatJSON["msg"],
},
],
},
],
};
await axios.post(
notification.mattermostWebhookUrl,
mattermostdowndata
);
return okMsg;
} else if (heartbeatJSON["status"] == UP) {
let mattermostupdata = {
username: mattermostUserName,
text: "Uptime Kuma Alert",
channel: mattermostChannel,
icon_emoji: mattermostIconEmoji,
icon_url: mattermostIconUrl,
attachments: [
{
fallback:
"Your " +
monitorJSON["name"] +
" service went up!",
color: "#32CD32",
title:
"✅ " +
monitorJSON["name"] +
" service went up! ✅",
title_link: monitorJSON["url"],
fields: [
{
short: true,
title: "Service Name",
value: monitorJSON["name"],
},
{
short: true,
title: "Time (UTC)",
value: heartbeatJSON["time"],
},
{
short: false,
title: "Ping",
value: heartbeatJSON["ping"] + "ms",
},
],
},
],
};
await axios.post(
notification.mattermostWebhookUrl,
mattermostupdata
);
return okMsg;
}
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Mattermost;

View File

@@ -0,0 +1,36 @@
class NotificationProvider {
/**
* Notification Provider Name
* @type string
*/
name = undefined;
/**
* @param notification : BeanModel
* @param msg : string General Message
* @param monitorJSON : object Monitor details (For Up/Down only)
* @param heartbeatJSON : object Heartbeat details (For Up/Down only)
* @returns {Promise<string>} Return Successful Message
* Throw Error with fail msg
*/
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
throw new Error("Have to override Notification.send(...)");
}
throwGeneralAxiosError(error) {
let msg = "Error: " + error + " ";
if (error.response && error.response.data) {
if (typeof error.response.data === "string") {
msg += error.response.data;
} else {
msg += JSON.stringify(error.response.data)
}
}
throw new Error(msg)
}
}
module.exports = NotificationProvider;

View File

@@ -0,0 +1,40 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Octopush extends NotificationProvider {
name = "octopush";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
let config = {
headers: {
"api-key": notification.octopushAPIKey,
"api-login": notification.octopushLogin,
"cache-control": "no-cache"
}
};
let data = {
"recipients": [
{
"phone_number": notification.octopushPhoneNumber
}
],
//octopush not supporting non ascii char
"text": msg.replace(/[^\x00-\x7F]/g, ""),
"type": notification.octopushSMSType,
"purpose": "alert",
"sender": notification.octopushSenderName
};
await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Octopush;

View File

@@ -0,0 +1,50 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Pushbullet extends NotificationProvider {
name = "pushbullet";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
let pushbulletUrl = "https://api.pushbullet.com/v2/pushes";
let config = {
headers: {
"Access-Token": notification.pushbulletAccessToken,
"Content-Type": "application/json"
}
};
if (heartbeatJSON == null) {
let testdata = {
"type": "note",
"title": "Uptime Kuma Alert",
"body": "Testing Successful.",
}
await axios.post(pushbulletUrl, testdata, config)
} else if (heartbeatJSON["status"] == DOWN) {
let downdata = {
"type": "note",
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[🔴 Down] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
}
await axios.post(pushbulletUrl, downdata, config)
} else if (heartbeatJSON["status"] == UP) {
let updata = {
"type": "note",
"title": "UptimeKuma Alert: " + monitorJSON["name"],
"body": "[✅ Up] " + heartbeatJSON["msg"] + "\nTime (UTC): " + heartbeatJSON["time"],
}
await axios.post(pushbulletUrl, updata, config)
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Pushbullet;

View File

@@ -0,0 +1,49 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Pushover extends NotificationProvider {
name = "pushover";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
let pushoverlink = "https://api.pushover.net/1/messages.json"
try {
if (heartbeatJSON == null) {
let data = {
"message": "<b>Uptime Kuma Pushover testing successful.</b>",
"user": notification.pushoveruserkey,
"token": notification.pushoverapptoken,
"sound": notification.pushoversounds,
"priority": notification.pushoverpriority,
"title": notification.pushovertitle,
"retry": "30",
"expire": "3600",
"html": 1,
}
await axios.post(pushoverlink, data)
return okMsg;
}
let data = {
"message": "<b>Uptime Kuma Alert</b>\n\n<b>Message</b>:" + msg + "\n<b>Time (UTC)</b>:" + heartbeatJSON["time"],
"user": notification.pushoveruserkey,
"token": notification.pushoverapptoken,
"sound": notification.pushoversounds,
"priority": notification.pushoverpriority,
"title": notification.pushovertitle,
"retry": "30",
"expire": "3600",
"html": 1,
}
await axios.post(pushoverlink, data)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Pushover;

View File

@@ -0,0 +1,30 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Pushy extends NotificationProvider {
name = "pushy";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, {
"to": notification.pushyToken,
"data": {
"message": "Uptime-Kuma"
},
"notification": {
"body": msg,
"badge": 1,
"sound": "ping.aiff"
}
})
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Pushy;

View File

@@ -0,0 +1,46 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class RocketChat extends NotificationProvider {
name = "rocket.chat";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
if (heartbeatJSON == null) {
let data = {
"text": "Uptime Kuma Rocket.chat testing successful.",
"channel": notification.rocketchannel,
"username": notification.rocketusername,
"icon_emoji": notification.rocketiconemo,
}
await axios.post(notification.rocketwebhookURL, data)
return okMsg;
}
const time = heartbeatJSON["time"];
let data = {
"text": "Uptime Kuma Alert",
"channel": notification.rocketchannel,
"username": notification.rocketusername,
"icon_emoji": notification.rocketiconemo,
"attachments": [
{
"title": "Uptime Kuma Alert *Time (UTC)*\n" + time,
"title_link": notification.rocketbutton,
"text": "*Message*\n" + msg,
"color": "#32cd32"
}
]
}
await axios.post(notification.rocketwebhookURL, data)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = RocketChat;

View File

@@ -0,0 +1,27 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Signal extends NotificationProvider {
name = "signal";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
let data = {
"message": msg,
"number": notification.signalNumber,
"recipients": notification.signalRecipients.replace(/\s/g, "").split(","),
};
let config = {};
await axios.post(notification.signalURL, data, config)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Signal;

View File

@@ -0,0 +1,70 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Slack extends NotificationProvider {
name = "slack";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
if (heartbeatJSON == null) {
let data = {
"text": "Uptime Kuma Slack testing successful.",
"channel": notification.slackchannel,
"username": notification.slackusername,
"icon_emoji": notification.slackiconemo,
}
await axios.post(notification.slackwebhookURL, data)
return okMsg;
}
const time = heartbeatJSON["time"];
let data = {
"text": "Uptime Kuma Alert",
"channel": notification.slackchannel,
"username": notification.slackusername,
"icon_emoji": notification.slackiconemo,
"blocks": [{
"type": "header",
"text": {
"type": "plain_text",
"text": "Uptime Kuma Alert",
},
},
{
"type": "section",
"fields": [{
"type": "mrkdwn",
"text": "*Message*\n" + msg,
},
{
"type": "mrkdwn",
"text": "*Time (UTC)*\n" + time,
}],
},
{
"type": "actions",
"elements": [
{
"type": "button",
"text": {
"type": "plain_text",
"text": "Visit Uptime Kuma",
},
"value": "Uptime-Kuma",
"url": notification.slackbutton || "https://github.com/louislam/uptime-kuma",
},
],
}],
}
await axios.post(notification.slackwebhookURL, data)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Slack;

View File

@@ -0,0 +1,48 @@
const nodemailer = require("nodemailer");
const NotificationProvider = require("./notification-provider");
class SMTP extends NotificationProvider {
name = "smtp";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
const config = {
host: notification.smtpHost,
port: notification.smtpPort,
secure: notification.smtpSecure,
};
// Should fix the issue in https://github.com/louislam/uptime-kuma/issues/26#issuecomment-896373904
if (notification.smtpUsername || notification.smtpPassword) {
config.auth = {
user: notification.smtpUsername,
pass: notification.smtpPassword,
};
}
let transporter = nodemailer.createTransport(config);
let bodyTextContent = msg;
if (heartbeatJSON) {
bodyTextContent = `${msg}\nTime (UTC): ${heartbeatJSON["time"]}`;
}
// send mail with defined transport object
await transporter.sendMail({
from: notification.smtpFrom,
cc: notification.smtpCC,
bcc: notification.smtpBCC,
to: notification.smtpTo,
subject: msg,
text: bodyTextContent,
tls: {
rejectUnauthorized: notification.smtpIgnoreTLSError || false,
},
});
return "Sent Successfully.";
}
}
module.exports = SMTP;

View File

@@ -0,0 +1,124 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const { DOWN, UP } = require("../../src/util");
class Teams extends NotificationProvider {
name = "teams";
_statusMessageFactory = (status, monitorName) => {
if (status === DOWN) {
return `🔴 Application [${monitorName}] went down`;
} else if (status === UP) {
return `✅ Application [${monitorName}] is back online`;
}
return "Notification";
};
_getThemeColor = (status) => {
if (status === DOWN) {
return "ff0000";
}
if (status === UP) {
return "00e804";
}
return "008cff";
};
_notificationPayloadFactory = ({
status,
monitorMessage,
monitorName,
monitorUrl,
}) => {
const notificationMessage = this._statusMessageFactory(
status,
monitorName
);
const facts = [];
if (monitorName) {
facts.push({
name: "Monitor",
value: monitorName,
});
}
if (monitorUrl) {
facts.push({
name: "URL",
value: monitorUrl,
});
}
return {
"@context": "https://schema.org/extensions",
"@type": "MessageCard",
themeColor: this._getThemeColor(status),
summary: notificationMessage,
sections: [
{
activityImage:
"https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png",
activityTitle: "**Uptime Kuma**",
},
{
activityTitle: notificationMessage,
},
{
activityTitle: "**Description**",
text: monitorMessage,
facts,
},
],
};
};
_sendNotification = async (webhookUrl, payload) => {
await axios.post(webhookUrl, payload);
};
_handleGeneralNotification = (webhookUrl, msg) => {
const payload = this._notificationPayloadFactory({
monitorMessage: msg
});
return this._sendNotification(webhookUrl, payload);
};
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
if (heartbeatJSON == null) {
await this._handleGeneralNotification(notification.webhookUrl, msg);
return okMsg;
}
let url;
if (monitorJSON["type"] === "port") {
url = monitorJSON["hostname"];
if (monitorJSON["port"]) {
url += ":" + monitorJSON["port"];
}
} else {
url = monitorJSON["url"];
}
const payload = this._notificationPayloadFactory({
monitorMessage: heartbeatJSON.msg,
monitorName: monitorJSON.name,
monitorUrl: url,
status: heartbeatJSON.status,
});
await this._sendNotification(notification.webhookUrl, payload);
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = Teams;

View File

@@ -0,0 +1,27 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class Telegram extends NotificationProvider {
name = "telegram";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
params: {
chat_id: notification.telegramChatID,
text: msg,
},
})
return okMsg;
} catch (error) {
let msg = (error.response.data.description) ? error.response.data.description : "Error without description"
throw new Error(msg)
}
}
}
module.exports = Telegram;

View File

@@ -0,0 +1,44 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
const FormData = require("form-data");
class Webhook extends NotificationProvider {
name = "webhook";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully. ";
try {
let data = {
heartbeat: heartbeatJSON,
monitor: monitorJSON,
msg,
};
let finalData;
let config = {};
if (notification.webhookContentType === "form-data") {
finalData = new FormData();
finalData.append("data", JSON.stringify(data));
config = {
headers: finalData.getHeaders(),
}
} else {
finalData = data;
}
await axios.post(notification.webhookURL, finalData, config)
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error)
}
}
}
module.exports = Webhook;

View File

@@ -1,63 +1,77 @@
const axios = require("axios");
const {R} = require("redbean-node");
const FormData = require('form-data');
const nodemailer = require("nodemailer");
const Discord = require('discord.js');
const { R } = require("redbean-node");
const Apprise = require("./notification-providers/apprise");
const Discord = require("./notification-providers/discord");
const Gotify = require("./notification-providers/gotify");
const Line = require("./notification-providers/line");
const LunaSea = require("./notification-providers/lunasea");
const Mattermost = require("./notification-providers/mattermost");
const Octopush = require("./notification-providers/octopush");
const Pushbullet = require("./notification-providers/pushbullet");
const Pushover = require("./notification-providers/pushover");
const Pushy = require("./notification-providers/pushy");
const RocketChat = require("./notification-providers/rocket-chat");
const Signal = require("./notification-providers/signal");
const Slack = require("./notification-providers/slack");
const SMTP = require("./notification-providers/smtp");
const Teams = require("./notification-providers/teams");
const Telegram = require("./notification-providers/telegram");
const Webhook = require("./notification-providers/webhook");
class Notification {
providerList = {};
static init() {
console.log("Prepare Notification Providers");
this.providerList = {};
const list = [
new Apprise(),
new Discord(),
new Teams(),
new Gotify(),
new Line(),
new LunaSea(),
new Mattermost(),
new Octopush(),
new Pushbullet(),
new Pushover(),
new Pushy(),
new RocketChat(),
new Signal(),
new Slack(),
new SMTP(),
new Telegram(),
new Webhook(),
];
for (let item of list) {
if (! item.name) {
throw new Error("Notification provider without name");
}
if (this.providerList[item.name]) {
throw new Error("Duplicate notification provider name");
}
this.providerList[item.name] = item;
}
}
/**
*
* @param notification : BeanModel
* @param msg : string General Message
* @param monitorJSON : object Monitor details (For Up/Down only)
* @param heartbeatJSON : object Heartbeat details (For Up/Down only)
* @returns {Promise<string>} Successful msg
* Throw Error with fail msg
*/
static async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
if (notification.type === "telegram") {
try {
await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, {
params: {
chat_id: notification.telegramChatID,
text: msg,
}
})
return true;
} catch (error) {
console.log(error)
return false;
}
} else if (notification.type === "webhook") {
try {
let data = {
heartbeat: heartbeatJSON,
monitor: monitorJSON,
msg,
};
let finalData;
let config = {};
if (notification.webhookContentType === "form-data") {
finalData = new FormData();
finalData.append('data', JSON.stringify(data));
config = {
headers: finalData.getHeaders()
}
} else {
finalData = data;
}
let res = await axios.post(notification.webhookURL, finalData, config)
return true;
} catch (error) {
console.log(error)
return false;
}
} else if (notification.type === "smtp") {
return await Notification.smtp(notification, msg)
} else if (notification.type === "discord") {
return await Notification.discord(notification, msg)
if (this.providerList[notification.type]) {
return this.providerList[notification.type].send(notification, msg, monitorJSON, heartbeatJSON);
} else {
throw new Error("Notification type is not supported")
throw new Error("Notification type is not supported");
}
}
@@ -80,8 +94,15 @@ class Notification {
bean.name = notification.name;
bean.user_id = userID;
bean.config = JSON.stringify(notification)
bean.config = JSON.stringify(notification);
bean.is_default = notification.isDefault || false;
await R.store(bean)
if (notification.applyExisting) {
await applyNotificationEveryMonitor(bean.id, userID);
}
return bean;
}
static async delete(notificationID, userID) {
@@ -97,39 +118,31 @@ class Notification {
await R.trash(bean)
}
static async smtp(notification, msg) {
let transporter = nodemailer.createTransport({
host: notification.smtpHost,
port: notification.smtpPort,
secure: notification.smtpSecure,
auth: {
user: notification.smtpUsername,
pass: notification.smtpPassword,
},
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: `"Uptime Kuma" <${notification.smtpFrom}>`,
to: notification.smtpTo,
subject: msg,
text: msg,
});
return true;
static checkApprise() {
let commandExistsSync = require("command-exists").sync;
let exists = commandExistsSync("apprise");
return exists;
}
static async discord(notification, msg) {
const client = new Discord.Client();
await client.login(notification.discordToken)
}
const channel = await client.channels.fetch(notification.discordChannelID);
await channel.send(msg);
async function applyNotificationEveryMonitor(notificationID, userID) {
let monitors = await R.getAll("SELECT id FROM monitor WHERE user_id = ?", [
userID
]);
client.destroy()
for (let i = 0; i < monitors.length; i++) {
let checkNotification = await R.findOne("monitor_notification", " monitor_id = ? AND notification_id = ? ", [
monitors[i].id,
notificationID,
])
return true;
if (! checkNotification) {
let relation = R.dispense("monitor_notification");
relation.monitor_id = monitors[i].id;
relation.notification_id = notificationID;
await R.store(relation)
}
}
}

23
server/password-hash.js Normal file
View File

@@ -0,0 +1,23 @@
const passwordHashOld = require("password-hash");
const bcrypt = require("bcryptjs");
const saltRounds = 10;
exports.generate = function (password) {
return bcrypt.hashSync(password, saltRounds);
}
exports.verify = function (password, hash) {
if (isSHA1(hash)) {
return passwordHashOld.verify(password, hash)
}
return bcrypt.compareSync(password, hash);
}
function isSHA1(hash) {
return (typeof hash === "string" && hash.startsWith("sha1"))
}
exports.needRehash = function (hash) {
return isSHA1(hash);
}

View File

@@ -1,45 +1,75 @@
// https://github.com/ben-bradley/ping-lite/blob/master/ping-lite.js
// Fixed on Windows
var spawn = require('child_process').spawn,
events = require('events'),
fs = require('fs'),
WIN = /^win/.test(process.platform),
LIN = /^linux/.test(process.platform),
MAC = /^darwin/.test(process.platform);
const net = require("net");
const spawn = require("child_process").spawn;
const events = require("events");
const fs = require("fs");
const WIN = /^win/.test(process.platform);
const LIN = /^linux/.test(process.platform);
const MAC = /^darwin/.test(process.platform);
const FBSD = /^freebsd/.test(process.platform);
module.exports = Ping;
function Ping(host, options) {
if (!host)
throw new Error('You must specify a host to ping!');
if (!host) {
throw new Error("You must specify a host to ping!");
}
this._host = host;
this._options = options = (options || {});
events.EventEmitter.call(this);
const timeout = 10;
if (WIN) {
this._bin = 'c:/windows/system32/ping.exe';
this._args = (options.args) ? options.args : [ '-n', '1', '-w', '5000', host ];
this._bin = "c:/windows/system32/ping.exe";
this._args = (options.args) ? options.args : [ "-n", "1", "-w", timeout * 1000, host ];
this._regmatch = /[><=]([0-9.]+?)ms/;
}
else if (LIN) {
this._bin = '/bin/ping';
this._args = (options.args) ? options.args : [ '-n', '-w', '2', '-c', '1', host ];
this._regmatch = /=([0-9.]+?) ms/; // need to verify this
}
else if (MAC) {
this._bin = '/sbin/ping';
this._args = (options.args) ? options.args : [ '-n', '-t', '2', '-c', '1', host ];
} else if (LIN) {
this._bin = "/bin/ping";
const defaultArgs = [ "-n", "-w", timeout, "-c", "1", host ];
if (net.isIPv6(host) || options.ipv6) {
defaultArgs.unshift("-6");
}
this._args = (options.args) ? options.args : defaultArgs;
this._regmatch = /=([0-9.]+?) ms/;
}
else {
throw new Error('Could not detect your ping binary.');
} else if (MAC) {
if (net.isIPv6(host) || options.ipv6) {
this._bin = "/sbin/ping6";
} else {
this._bin = "/sbin/ping";
}
this._args = (options.args) ? options.args : [ "-n", "-t", timeout, "-c", "1", host ];
this._regmatch = /=([0-9.]+?) ms/;
} else if (FBSD) {
this._bin = "/sbin/ping";
const defaultArgs = [ "-n", "-t", timeout, "-c", "1", host ];
if (net.isIPv6(host) || options.ipv6) {
defaultArgs.unshift("-6");
}
this._args = (options.args) ? options.args : defaultArgs;
this._regmatch = /=([0-9.]+?) ms/;
} else {
throw new Error("Could not detect your ping binary.");
}
if (!fs.existsSync(this._bin))
throw new Error('Could not detect '+this._bin+' on your system');
if (!fs.existsSync(this._bin)) {
throw new Error("Could not detect " + this._bin + " on your system");
}
this._i = 0;
@@ -50,62 +80,73 @@ Ping.prototype.__proto__ = events.EventEmitter.prototype;
// SEND A PING
// ===========
Ping.prototype.send = function(callback) {
var self = this;
callback = callback || function(err, ms) {
if (err) return self.emit('error', err);
else return self.emit('result', ms);
Ping.prototype.send = function (callback) {
let self = this;
callback = callback || function (err, ms) {
if (err) {
return self.emit("error", err);
}
return self.emit("result", ms);
};
var _ended, _exited, _errored;
let _ended;
let _exited;
let _errored;
this._ping = spawn(this._bin, this._args); // spawn the binary
this._ping.on('error', function(err) { // handle binary errors
this._ping.on("error", function (err) { // handle binary errors
_errored = true;
callback(err);
});
this._ping.stdout.on('data', function(data) { // log stdout
this._stdout = (this._stdout || '') + data;
this._ping.stdout.on("data", function (data) { // log stdout
this._stdout = (this._stdout || "") + data;
});
this._ping.stdout.on('end', function() {
this._ping.stdout.on("end", function () {
_ended = true;
if (_exited && !_errored) onEnd.call(self._ping);
if (_exited && !_errored) {
onEnd.call(self._ping);
}
});
this._ping.stderr.on('data', function(data) { // log stderr
this._stderr = (this._stderr || '') + data;
this._ping.stderr.on("data", function (data) { // log stderr
this._stderr = (this._stderr || "") + data;
});
this._ping.on('exit', function(code) { // handle complete
this._ping.on("exit", function (code) { // handle complete
_exited = true;
if (_ended && !_errored) onEnd.call(self._ping);
if (_ended && !_errored) {
onEnd.call(self._ping);
}
});
function onEnd() {
var stdout = this.stdout._stdout,
stderr = this.stderr._stderr,
ms;
let stdout = this.stdout._stdout;
let stderr = this.stderr._stderr;
let ms;
if (stderr)
if (stderr) {
return callback(new Error(stderr));
else if (!stdout)
return callback(new Error('No stdout detected'));
}
if (!stdout) {
return callback(new Error("No stdout detected"));
}
ms = stdout.match(self._regmatch); // parse out the ##ms response
ms = (ms && ms[1]) ? Number(ms[1]) : ms;
callback(null, ms);
callback(null, ms, stdout);
}
};
// CALL Ping#send(callback) ON A TIMER
// ===================================
Ping.prototype.start = function(callback) {
var self = this;
this._i = setInterval(function() {
Ping.prototype.start = function (callback) {
let self = this;
this._i = setInterval(function () {
self.send(callback);
}, (self._options.interval || 5000));
self.send(callback);
@@ -113,6 +154,6 @@ Ping.prototype.start = function(callback) {
// STOP SENDING PINGS
// ==================
Ping.prototype.stop = function() {
Ping.prototype.stop = function () {
clearInterval(this._i);
};

90
server/prometheus.js Normal file
View File

@@ -0,0 +1,90 @@
const PrometheusClient = require("prom-client");
const commonLabels = [
"monitor_name",
"monitor_type",
"monitor_url",
"monitor_hostname",
"monitor_port",
]
const monitor_cert_days_remaining = new PrometheusClient.Gauge({
name: "monitor_cert_days_remaining",
help: "The number of days remaining until the certificate expires",
labelNames: commonLabels
});
const monitor_cert_is_valid = new PrometheusClient.Gauge({
name: "monitor_cert_is_valid",
help: "Is the certificate still valid? (1 = Yes, 0= No)",
labelNames: commonLabels
});
const monitor_response_time = new PrometheusClient.Gauge({
name: "monitor_response_time",
help: "Monitor Response Time (ms)",
labelNames: commonLabels
});
const monitor_status = new PrometheusClient.Gauge({
name: "monitor_status",
help: "Monitor Status (1 = UP, 0= DOWN)",
labelNames: commonLabels
});
class Prometheus {
monitorLabelValues = {}
constructor(monitor) {
this.monitorLabelValues = {
monitor_name: monitor.name,
monitor_type: monitor.type,
monitor_url: monitor.url,
monitor_hostname: monitor.hostname,
monitor_port: monitor.port
}
}
update(heartbeat, tlsInfo) {
if (typeof tlsInfo !== "undefined") {
try {
let is_valid = 0
if (tlsInfo.valid == true) {
is_valid = 1
} else {
is_valid = 0
}
monitor_cert_is_valid.set(this.monitorLabelValues, is_valid)
} catch (e) {
console.error(e)
}
try {
monitor_cert_days_remaining.set(this.monitorLabelValues, tlsInfo.daysRemaining)
} catch (e) {
console.error(e)
}
}
try {
monitor_status.set(this.monitorLabelValues, heartbeat.status)
} catch (e) {
console.error(e)
}
try {
if (typeof heartbeat.ping === "number") {
monitor_response_time.set(this.monitorLabelValues, heartbeat.ping)
} else {
// Is it good?
monitor_response_time.set(this.monitorLabelValues, -1)
}
} catch (e) {
console.error(e)
}
}
}
module.exports = {
Prometheus
}

Some files were not shown because too many files have changed in this diff Show More