Compare commits

...

1664 Commits

Author SHA1 Message Date
Ioma Taani daef238a70
Updated Italian Language (#911) 3 years ago
Louis Lam 5df34cd137
Merge pull request #885 from ZegertBoele/patch-1 3 years ago
Louis Lam bf64095cea update to 1.10.2 3 years ago
Louis Lam 2333d1c7a7 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 95bae8289d Fix setting page when disabled auth 3 years ago
Louis Lam 45f7c647a6
Update feature_request.yaml 3 years ago
Zegert Boele dff1056bb1
Update nl-NL.js 3 years ago
Zegert Boele 62222c0336
Update src/languages/nl-NL.js 3 years ago
Louis Lam 733d0af75f update to 1.10.1 3 years ago
Louis Lam b88e74fad8
Merge pull request #891 from ivanbratovic/croatian-language 3 years ago
Ivan Bratović 734762b773 Merge with `master` 3 years ago
Louis Lam 0275d7a42b minor 3 years ago
Louis Lam 41a6d1b701 Fix parseCertificateInfo possibly in dead loop 3 years ago
Louis Lam c92153c97e add more debug msg 3 years ago
Louis Lam ad82ab0305
Merge pull request #883 from andreasbrett/patch-7 3 years ago
Louis Lam f952d283c6
Merge pull request #815 from Fallstop/tags-on-status 3 years ago
Louis Lam e164fabf81
Merge pull request #849 from Minvinea/master 3 years ago
Louis Lam bc69a331ee eslint 3 years ago
Jasper Miller-Waugh e4506963d9
Merge branch 'louislam:master' into tags-on-status 3 years ago
Zegert Boele 222540898b
Some translations were not translated 3 years ago
Andreas Brett 8f44b9f618 24h tooltip on status page 3 years ago
Louis Lam 210566c7af remove prefix for issue title, so users need to input the title 3 years ago
Louis Lam c5e6628803
Merge pull request #870 from chakflying/patch-3 3 years ago
Louis Lam 3a1d8ddc11
Merge pull request #869 from MrEddX/bulgarian 3 years ago
Nelson Chan bc5f61b3ec
Chore: Add drag and drop 3 years ago
Nelson Chan 57389fab2c
Update PULL_REQUEST_TEMPLATE.md 3 years ago
MrEddX ee2c54cfd1
Update bg-BG.js 3 years ago
Louis Lam 82cde7c847
Merge pull request #854 from 634750802/patch-1 3 years ago
Louis Lam 1ba2034701 freeze bootstrap to 5.1.3 to prevent breaking changes 3 years ago
Louis Lam dee131c25d fix table hover color not working after updated bootstrap to 5.1.3 3 years ago
Jasper Miller-Waugh e5d6410caf
Apply formatting suggestions from code review 3 years ago
Louis Lam e496c3b3be update healthcheck.js 3 years ago
Louis Lam 69f5112b38 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam c094dc0c5b speed up redirect by using 302 redirect instead of vue redirect 3 years ago
Ivan Bratović 1fb9b25d13 Improve hr-HR translations 3 years ago
Ivan Bratović 9a135deac2 Add new translation for 'Uptime' 3 years ago
Your Name 8e6173c05e Fix and add new hr-HR translations 3 years ago
Louis Lam dec84282ed
Update bug_report.yaml 3 years ago
Louis Lam df80f413b5
Update feature_request.yaml 3 years ago
Louis Lam 17e59f1d8d
Update ask-for-help.yaml 3 years ago
Louis Lam 973c2bb429
Update ask-for-help.yaml 3 years ago
Louis Lam da0eaddeb8
Update SECURITY.md 3 years ago
Louis Lam b2bc8d9db9
Update bug_report.yaml 3 years ago
Louis Lam 541068ff3b
Update bug_report.yaml 3 years ago
Louis Lam 83ee46454a
Update bug_report.yaml 3 years ago
Louis Lam 75b21c905f
Merge pull request #847 from Saibamen/update_pl 3 years ago
Louis Lam 60e12f4bfa fix healthcheck.js with prefix UPTIME_KUMA_ 3 years ago
Jasper Miller-Waugh 191b81ee07
Fix grammer in comment 3 years ago
Jagger f3651a1219
Add a status prefix for feishu notification 3 years ago
Jasper Miller-Waugh 12ef9f39c5
Merged buttons, cleaned up SS tag retrieval and made tagsVisible a bool. 3 years ago
Jasper Miller-Waugh 4004926e64
Small formatting changes from code-review 3 years ago
Adam Stachowicz 4d3d6d6e25 Missing this... 3 years ago
Adam Stachowicz d06e5ef6fa More small letters 3 years ago
Adam Stachowicz b12b848d97 One more typo... 3 years ago
Adam Stachowicz bb96a577ca Fix typos + translate `wayToGetTeamsURL` 3 years ago
Adam Stachowicz 8840ca618b Update `pl.js` 3 years ago
Minvinea 8ec858fd14
Add missing translation 3 years ago
Louis Lam 124c98ce76 update to 1.10.0 3 years ago
Louis Lam 61135e8500 update package-lock.json 3 years ago
Louis Lam 08a58dec2b fix manifest.json path 3 years ago
Louis Lam 741ed548da Merge branch 'master' into use_hideCount_option 3 years ago
Louis Lam 52d80d3a5d Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 586c748d44 vite build on host machine, since it is very slow on armv7/arm64 build 3 years ago
Louis Lam b5d6e96b1d
Merge pull request #842 from gaby/issue-form-updates 3 years ago
Juan Calderon-Perez 68b74f07e4 Update wording of form field 3 years ago
Louis Lam bc615c2dd8
Merge pull request #832 from ivanbratovic/croatian-language 3 years ago
Louis Lam e7104737e7 prevent to show "New Update" when the Docker image is not ready yet 3 years ago
Louis Lam 1dbf1c3dea fix logout 3 years ago
Jasper Miller-Waugh 74688e69aa
Remove debug statement in server/routers/api-router.js 3 years ago
Jasper Miller-Waugh b32bfb3ff1
Added toggle for tag visibility 3 years ago
Jasper Miller-Waugh 24664cde2c
Smarter CSS to fix Mobile alignment 3 years ago
Jasper Miller-Waugh 348c5ec995
Match lint settings 3 years ago
Jasper Miller-Waugh 9143b73f84
Styling for tags 3 years ago
Jasper Miller-Waugh 5e6d945095
Most hacked in POC 3 years ago
Louis ba93129b18 Merge branch '1.9.X' 3 years ago
Louis cf548df15f update to 1.9.2 3 years ago
Louis caa2a34177 fix 2fa not working #833 3 years ago
Adam Stachowicz 69aa60d1fb Add missing i18n key + translate 2 keys for polish 3 years ago
Ivan Bratović eaecd6e571 Clarity and grammar fixes to hr_HR languange file 3 years ago
Adam Stachowicz f2a27a2cf1 Use `hideCount` option for pagination 3 years ago
Louis d4c9431142 catch createWriteStream error 3 years ago
Louis d7f7dba13f write some error logs to ./data/error.log 3 years ago
Louis 3e5ae00d25 update dependencies 3 years ago
Louis Lam 5311bef3eb
Merge pull request #809 from Saibamen/pagination_no_text 3 years ago
Louis Lam c400595f67
Merge pull request #825 from SiderealArt/patch-1 3 years ago
Louis Lam e84f7dac60
Merge pull request #821 from ivanbratovic/croatian-language 3 years ago
SiderealArt 67a22399bc
Update i18n.js 3 years ago
SiderealArt 947fc6001e
Update Settings.vue 3 years ago
SiderealArt c87e67ad1b
Add Traditional Chinese (Taiwan) translation 3 years ago
Ivan Bratović 6f92774a8f ESLint pass on hr-HR.js file 3 years ago
Ivan Bratović 6e76ab7426 Import hr-HR language in i18n.js 3 years ago
Ivan Bratović b2fbd7e263 Add confirmDisableAuth tranlation for hr-HR 3 years ago
Ivan Bratović 199e6ec82b Add initial version of Croatian language 3 years ago
Adam Stachowicz 18a99c2016 Revert deleting `records` and `"One record"` keys 3 years ago
Louis Lam e261a27ebe fix wrong call of rejectUnauthorized for smtp (#757) 3 years ago
Louis Lam de5cce9d90 Steam API Key to HiddenInput 3 years ago
Louis Lam b85c9186f9
Merge pull request #781 from louislam/cert-notification 3 years ago
Louis Lam eb22ad5ffe [certificate notification] error handling and better msg 3 years ago
Louis Lam f5f4835b74 [certificate notification] clear sent history if the cert is changed 3 years ago
Louis Lam 44c1b336dc send certificate notifications in 21, 14, 7 days 3 years ago
Louis Lam 110ec491ee Merge branch 'master' into cert-notification 3 years ago
Louis Lam 640b6e5b1c prevent monitor dead for unexpected error 3 years ago
Louis Lam 234fba3978
Update SECURITY.md 3 years ago
Louis Lam 1285ccb537
Merge pull request #784 from gaby/issue-forms 3 years ago
Juan Calderon-Perez 6c542edfc9 Add examples for version and image tag. 3 years ago
Juan Calderon-Perez 767807dd22 Added text placeholders for versions. 3 years ago
Juan Calderon-Perez 546402f3d2 Added docker-image-tag field. 3 years ago
Louis Lam 698a38e773 clear status page cache in a better place 3 years ago
Louis Lam 71884cf42a
Merge pull request #772 from andreasbrett/patch-6 3 years ago
Louis Lam d676c782bb
Update README.md 3 years ago
Juan Calderon-Perez dd773aa5a2 Updates based on PR comments. 3 years ago
Louis Lam 2852e59ffb
Merge pull request #812 from MrEddX/bulgarian 3 years ago
MrEddX cb3da50e7e
Update bg-BG.js 3 years ago
Louis Lam f25653d778
Update README.md 3 years ago
Adam Stachowicz 2e7ad1b7b2 Don't display "count" text for pagination 3 years ago
Louis Lam e0e1ab6fa6
Update CONTRIBUTING.md 3 years ago
Louis Lam 8d984881c9
Update CONTRIBUTING.md 3 years ago
Louis Lam 955f9ae20a
Merge pull request #794 from louislam/free-disk-space 3 years ago
Louis Lam a9e319517a add auto vacuum and shrink database button 3 years ago
Louis Lam 39ad8b4bb7 Merge branch 'master' into free-disk-space 3 years ago
Andreas Brett 8fb8cbdaf3 use auth0/jwt-decode 3 years ago
Andreas Brett 3f3d8b4eb3 fixes 3 years ago
Louis Lam 9123e9461f
Update CONTRIBUTING.md 3 years ago
Louis Lam 77addfebc8 Merge branch 'tarun7singh_master' 3 years ago
Louis Lam 16846c7c6d
Merge pull request #790 from Saibamen/pl_update+fixes 3 years ago
Louis Lam d1c4d13903
Merge pull request #782 from Co2333/dev-lakr233-bark_notification 3 years ago
Louis Lam 7cd4bfc11d
Merge pull request #806 from Saibamen/patch-1 3 years ago
Adam Stachowicz 1d5c0502ab
Add other 3 years ago
Adam Stachowicz a1cda93ad5
Update PULL_REQUEST_TEMPLATE.md 3 years ago
Louis Lam 3bd420f0e0
Merge pull request #752 from chakflying/feat/chart-period 3 years ago
Louis Lam 78424b4f2d add simple loading chart effect 3 years ago
Louis Lam f8055ed03d minor css 3 years ago
Louis Lam fe4724fc53 Merge branch 'master' into feat/chart-period 3 years ago
Louis Lam 7f0dda6a44
Update CONTRIBUTING.md 3 years ago
Lakr Aream 43791ee97e Merge branch 'master' into dev-lakr233-bark_notification 3 years ago
Tarun Singh 6362ef6a9c removed other langauge translation data 3 years ago
Adam Stachowicz 9d3a4e9d1e Remove dot from `needPushEvery` 3 years ago
Tarun Singh 6c60096f56
Merge branch 'louislam:master' into master 3 years ago
Tarun Singh ba1e025353 added click send to number 3 years ago
Louis Lam a41a081727 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam a5f15f2319 Fix #793, check dist-backup existing before delete 3 years ago
Louis Lam e69799f613
Update CONTRIBUTING.md 3 years ago
Louis Lam 3c795bebe3
Update CONTRIBUTING.md 3 years ago
Louis Lam 3a43fec666
add recommend pull request guideline 3 years ago
Louis Lam 24c645e437 [empty commit] pull request for free-disk-space 3 years ago
Louis Lam 9d31da1fe8
Merge pull request #792 from gaby/stalebot-fix 3 years ago
Juan Calderon-Perez 2e4c42941a
Rename stale-bot to stale-bot.yml 3 years ago
Andreas Brett 4fc2603818 Merge branch 'patch-6' of https://github.com/andreasbrett/uptime-kuma into patch-6 3 years ago
Andreas Brett 7bc38d4231 remove unused vars 3 years ago
Andreas Brett daad63d70b
Merge branch 'master' into patch-6 3 years ago
Andreas Brett 9ddd2c7365 use jwt 3 years ago
Adam Stachowicz fa5ba12e14 Missing this 3 years ago
Adam Stachowicz 85053f865e Fix typo 3 years ago
Adam Stachowicz 1239f6d1a2 PL update + fixes 3 years ago
Tarun Singh fed611d1b9 Merge branch 'master' of https://github.com/louislam/uptime-kuma 3 years ago
Tarun Singh bc68088350 Click send sms integration for notifications 3 years ago
Louis Lam 90200958cd
Merge pull request #780 from kry008/patch-4 3 years ago
Louis Lam aa13d74d7a
Merge pull request #788 from Ponkhy/german-language 3 years ago
Ponkhy d82f305f6e Updated german language file 3 years ago
Louis Lam 7c63cbfd84 add node.js 17 to auto test 3 years ago
Juan Calderon-Perez c7e1267779 More syntax changes. Change What to Which 3 years ago
Louis Lam 5d0b54c292
Merge pull request #785 from Saibamen/patch-1 3 years ago
Juan Calderon-Perez b50b390048 Changes based on PR requests 3 years ago
Adam Stachowicz 65158cb06b
Update PULL_REQUEST_TEMPLATE.md 3 years ago
Adam Stachowicz 8fe5e4e605
Fix lint 3 years ago
Adam Stachowicz ab5ddae2ee
Delete double new line 3 years ago
Adam Stachowicz 89c64f4ea2
Create PULL_REQUEST_TEMPLATE.md 3 years ago
Juan Calderon-Perez 40a1ebecc5
Update feature_request.yaml 3 years ago
Juan Calderon-Perez e1793596fe
Merge pull request #1 from gaby/issue-forms 3 years ago
Juan Calderon-Perez c489058a57 Update labels for each form 3 years ago
Juan Calderon-Perez 95342ec006 Update label for ask for help 3 years ago
Juan Calderon-Perez bdebbf8e40 Add Support for Issue Forms 3 years ago
Juan Calderon-Perez 9a9fca67d5 Migrate Bug Report to Github Issue Forms 3 years ago
Nelson Chan 665bae0806 UI: Simplify dropdown design 3 years ago
Nelson Chan e4be28a9e7 Fix: Validate beat time before appending 3 years ago
Nelson Chan 445674aacb Chore: Improve code formatting & comments 3 years ago
Nelson Chan 2f7b60f5e5 Feat: Use separate storage for custom chart period 3 years ago
Nelson Chan b83c59e308 WIP: Add options for chart period 3 years ago
Lakr Aream ce852dfa02 Support for Bark (APN) notifications 3 years ago
Louis Lam c9549c0de2 change body and header placeholders, less misleading. 3 years ago
Louis Lam 957c292307 add certificate-notification job 3 years ago
kry008 b5eb17ed93
Update pl.js 3 years ago
Louis Lam d578300104
Merge pull request #743 from andreasbrett/patch-4 3 years ago
Louis Lam b77b33e790 add login rate limiter 3 years ago
Andreas Brett 4becb97a5d
Update en.js 3 years ago
Andreas Brett 85e2b36424
Update en.js 3 years ago
Andreas Brett abdf1ae90a
Update en.js 3 years ago
Andreas Brett 606c967985
Merge branch 'master' into patch-6 3 years ago
Andreas Brett 93c231b4d9
Update server/server.js 3 years ago
Andreas Brett 9ad8e5f56a show logged in user 3 years ago
Louis Lam 8a481a1be0
Merge pull request #769 from andreasbrett/patch-5 3 years ago
Andreas Brett 657987a013 fix: show beat.msg only if available 3 years ago
Louis Lam d74577608b
Merge pull request #766 from DX37/translation-ru 3 years ago
Louis Lam 20a399c557
Merge pull request #767 from mrphuongbn/master 3 years ago
Phuong Nguyen Minh 060dde9827
Merge branch 'louislam:master' into master 3 years ago
DX37 1d1601cf24
Update notifications area in ru-RU.js 3 years ago
Louis Lam ff5f2e8dfb add limiter 3 years ago
Louis Lam 5451fb7672 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 56094a43d7 add passwordStrength 3 years ago
Louis Lam 68bbe8944a
Merge pull request #756 from DX37/translation-ru 3 years ago
Louis Lam 8f1da6aa22
Update CONTRIBUTING.md 3 years ago
Louis Lam c0d6fe0d76
Update CONTRIBUTING.md 3 years ago
DX37 29e4e41215
Update ru-RU.js 3 years ago
Louis Lam 7a1bb964e9
Update bug_report.md 3 years ago
Louis Lam 3fe0e9bf1e
Update ask-for-help.md 3 years ago
Louis Lam 9982887783
Update feature_request.md 3 years ago
Louis Lam c31efc0ef4
Merge pull request #748 from MrEddX/bulgarian 3 years ago
MrEddX 6463d4b209
Fix: Integration Link Text 3 years ago
Louis Lam acada8028a
Merge pull request #747 from MrEddX/bulgarian 3 years ago
MrEddX d0b0c64b81
Update bg-BG.js 3 years ago
Louis Lam cd04ac4557 "dist/index.html" is no longer needed for development environment 3 years ago
Louis Lam d7d2f7b7fc
Merge pull request #745 from dpatrongomez/patch-2 3 years ago
Daniel Patrón Gómez 5a05d135b8
Add steam translation in spanish 3 years ago
Louis Lam e03ee593e2
Merge pull request #716 from NeuralMiner/textchanges 3 years ago
Louis Lam 6c1ee70e15 fix 3 years ago
Louis Lam 5c3892313e add env var: UPTIME_KUMA_DISABLE_FRAME_SAMEORIGIN 3 years ago
Louis Lam c57c94642c Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 62f168a2a5 config response header 3 years ago
Louis Lam c808f78f09
Merge pull request #735 from gaby/stale-bot 3 years ago
Louis Lam 9c80e1c732
Merge pull request #641 from andreasbrett/patch-1 3 years ago
Andreas Brett acc2995d86 invalidate used token 3 years ago
Andreas Brett 7def9dcec7
Merge branch 'louislam:master' into patch-1 3 years ago
NeuralMiner a35569481d Updates 3 years ago
NeuralMiner 9ddffc0f7f Updates 3 years ago
NeuralMiner 76e7c8b276 Rebase 3 years ago
NeuralMiner 572a5300aa Recommended updates. 3 years ago
NeuralMiner e1f1d4a959
Merge branch 'louislam:master' into textchanges 3 years ago
Louis Lam c6fc385289 update to 1.9.1 3 years ago
Louis Lam c645658161 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 182597944d fix #721 3 years ago
Louis Lam 8eaa8116c3
update email 3 years ago
Louis Lam 3512faad14 move `kubernetes` folder to the `k8s-unofficial` branch 3 years ago
Louis Lam f11417e854 [upload artifacts] no idea why suddenly not working via env var, hardcode the VERSION instead 3 years ago
Juan Calderon-Perez b5857f7c0c
Fix syntax issue. 3 years ago
Juan Calderon-Perez 6277babf25
Migrate to actions/stale v4.0 3 years ago
Louis Lam 5f36d2acda fix upload artifacts 3 years ago
Louis Lam cc36ff5210 update to 1.9.0 3 years ago
Louis Lam c363d3374e fix "build-docker-nightly-alpine" wrong path 3 years ago
Louis Lam 65a8cb5307
Merge pull request #738 from NixNotCastey/promosms 3 years ago
Lukas f74b2662c5 Fixed values for sms type 3 years ago
Louis Lam 300a95d779 recompile util.js with tsconfig.json 3 years ago
Louis Lam 23714ab688 genSecret don't need `await` 3 years ago
Louis Lam 16b44001e7 Merge remote-tracking branch 'andreasbrett/patch-1' into andreasbrett_patch-1 3 years ago
Louis Lam f2f8f33b86 Merge branch 'master' into andreasbrett_patch-1 3 years ago
Louis Lam 6e18f39eb4 [steam] code cleanup 3 years ago
Louis Lam 68d44dd9b3 [steam] do not request if there is no steam api key 3 years ago
Louis Lam 20d59e5a13 fix and move the steam api key to settings page 3 years ago
Louis Lam ae31eb6ba9 Merge branch 'master' into Revyn112_master 3 years ago
Andreas Brett df4682d19b
Merge branch 'master' into patch-1 3 years ago
Andreas Brett 11a1f35cc5 independent csprng solution 3 years ago
Juan Calderon-Perez 2a3ce15328
Use default number of operations per day. Defaults to 30 3 years ago
Juan Calderon-Perez 7cb25255bf
Update stale-bot 3 years ago
Juan Calderon-Perez c622f7958f
Add support for closing stale Issues/PR 3 years ago
Louis Lam df5efcc71c
Merge pull request #730 from sargonas/sargonas-patch-1 3 years ago
J. Eckert 4cd66b20b1
Update README.md 3 years ago
J. Eckert 1276102c18
Update README.md 3 years ago
Louis Lam 6944b35ea7
Merge pull request #667 from zsxeee/i18n 3 years ago
Louis Lam 88757ebbbe
Merge pull request #722 from dpatrongomez/master 3 years ago
Daniel Patrón Gómez 0a73b84ae6 Add records translations and fix pause translation 3 years ago
Daniel Patrón Gómez 15f36f96c3 Add spanish translation for monitor history 3 years ago
Louis Lam edcaf93446
Merge pull request #721 from dpatrongomez/master 3 years ago
Louis Lam dec175d55f
Merge pull request #719 from bertyhell/bugfix/edit-monitor 3 years ago
Louis Lam 9a60f69f66
Merge pull request #720 from bertyhell/bugfix/fix-error-on-first-hearthbeat 3 years ago
Daniel Patrón Gómez 53a008ae2b Add Status Translation 3 years ago
Bert Verhelst 1d63dd9ddd fix(monitor): safely get status of previous beat if first beat 3 years ago
Bert Verhelst 61627545a5 fix(edit-monitor): no need to escape placeholder {} if not translated 3 years ago
Louis Lam 176fa6b60d merge package-lock.json 3 years ago
Louis Lam cb43ecb46e Merge branch 'master' into background-jobs 3 years ago
Louis Lam 2e24312f67 [test] jest please 3 years ago
Louis Lam 6ff3cb275e
Merge pull request #642 from andreasbrett/patch-2 3 years ago
Louis Lam 9d364b28b1
Merge pull request #715 from januridp/master 3 years ago
Louis Lam bc3e3f9118 [test] update 3 years ago
Louis Lam 0f3ab7b1d8 [test] increase the timeout for reset-password 3 years ago
NeuralMiner 8cb26d2b31 Text update 3 years ago
januridp d94fbede32 Fix(Language): Bahasa Indonesia (Indonesian) 3 years ago
januridp 76e619c066 Fix(Language): Bahasa Indonesia (Indonesian) 3 years ago
januridp 4e4f94ab98 Fix(Language): Bahasa Indonesia (Indonesian) 3 years ago
januridp ed3a558397 Fix(Language): Bahasa Indonesia (Indonesian) 3 years ago
Louis Lam a419aa527f Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 4d26825cbe [test] reset-password 3 years ago
Louis Lam 7276f34d90 fix reset-password 3 years ago
Louis Lam e1eeb44e7f
Update SECURITY.md 3 years ago
Louis Lam f4b8da0a5c Merge branch 'feature/add-support-for-method-body-and-headers' 3 years ago
Louis Lam 4178983df3 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 7ac0ab2e34 [http options] beautify the json format when clicked the save button 3 years ago
Louis Lam cd211a6be7 [http options] fine tune 3 years ago
Louis Lam 4e71ab7406 Merge branch 'master' into feature/add-support-for-method-body-and-headers 3 years ago
Louis Lam 76c68071f1
Merge pull request #709 from iooner/patch-1 3 years ago
Phuong Nguyen Minh bda481c61e
Update vi.js 3 years ago
iooner 8242a1586d
Update fr-FR.js 3 years ago
Louis Lam c593a962c2
Merge pull request #627 from NixNotCastey/smtp-subject 3 years ago
Louis Lam c9b4d2ae2a
Merge pull request #698 from erktime/master 3 years ago
Louis Lam 37105d720b
Merge pull request #706 from firattemel/master 3 years ago
Louis Lam 3b74b727f2 [Push Type] fix missing important flag and missing up notification 3 years ago
firattemel 2f0119bc3f Update tr-TR.js 3 years ago
Louis Lam a7d2a34dae fix ping bug 3 years ago
Louis Lam 60acb91fc8
Merge pull request #687 from xjoker/master 3 years ago
Louis Lam f51156f18e run eslint for #687 3 years ago
Louis Lam 8338881927 [SMTP] change {{HOSTNAME}} to {{HOSTNAME_OR_URL}}, support for http montior type, some UI improvements 3 years ago
Louis Lam 674b387c95 Merge branch 'master' into smtp-subject 3 years ago
Louis Lam 5ff9a64e5e [Push Type] Fix missing duration calculation (#685) 3 years ago
Louis Lam 4bee57ea7f Merge remote-tracking branch 'giacomo892/patch-1' 3 years ago
Louis Lam f75c9e4f0c add UPTIME_KUMA_HOST, UPTIME_KUMA_PORT and special handling for FreeBSD 3 years ago
xJoker 8ab4788f80
Update src/components/notifications/index.js 3 years ago
xJoker 4e4ab0577e
Update src/components/notifications/index.js 3 years ago
xJoker 6e04ec436e
Update server/notification-providers/dingding.js 3 years ago
xJoker 2d471a5e84
Update server/notification-providers/dingding.js 3 years ago
xJoker cae194f58f
Update server/notification-providers/dingding.js 3 years ago
Aaron Erkenswick 655ccc86b9 Add monitor name context to Slack fallback text. 3 years ago
Louis Lam e2dbacb383 Fix encoding problem of ping result for non-English Windows 3 years ago
Lukas 89b34b5748 Use double curly brackets and sanity check for customSubject 3 years ago
Andreas Brett 86dcc9bc8f import webcrypto lib 3 years ago
Louis Lam 9b05e86c25 set newLine to LF for ts compiler 3 years ago
Louis Lam 145b722aec Merge branch 'master' into andreasbrett_patch-1 3 years ago
Louis Lam 2ff7c4de5d [test] genSecret 3 years ago
Louis Lam 79c81395bc Merge branch 'master' into andreasbrett_patch-1 3 years ago
Louis Lam 178e5cd2c0
Merge pull request #689 from hrtkpf/master 3 years ago
hrtkpf 84507268ad fix translations (de-DE and en) 3 years ago
wuwenjing 843992c410 Add DingDing notification 3 years ago
zsxeee 33f773fcd0
Move param out of the translation file 3 years ago
zsxeee 26841a64f0
Update zh-CN.js 3 years ago
Phuong Nguyen Minh 89c0f8b734
Update i18n.js 3 years ago
wuwenjing 57a76e6129 remove `alicloud/pop-core` keep simple 3 years ago
Phuong Nguyen Minh dc805cff97
Add files via upload 3 years ago
giacomo892 3fe3450533
Prioritize port passed from args 3 years ago
Lukas 330cd6e058
Minor rehabilitanty impedyment 3 years ago
wuwenjing a2f2253221 Add aliyun sms notification 3 years ago
Louis Lam 1e5ce92917
Merge pull request #678 from wellart/master 3 years ago
Louis Lam 0d7c2960b0
Merge pull request #683 from Saibamen/fix_markdown 3 years ago
Louis Lam 82343de972
Merge pull request #682 from Saibamen/patch-1 3 years ago
Adam Stachowicz 521d57c483 Fix some of markdownlint warnings 3 years ago
Adam Stachowicz 281671b938
Fix build 3 years ago
Lukas 30d8aadf12 Slightly refactor 3 years ago
KangAlleW 2939bd4138 fix locale 3 years ago
KangAlleW dcf15c3eb7 edit i18n.js 3 years ago
KangAlleW 7c9ed98408 rename id.js to id-ID.js 3 years ago
KangAlleW 4b9f0a3fe6 add indonesian language and edit settings.vue 3 years ago
KangAlleW 5b67fec084 add indonesian language 3 years ago
Louis Lam 407581ee07 move jest config files to config dir 3 years ago
Louis Lam 11c3c636e0 move dockerfile, docker-compose.yml to docker folder 3 years ago
Louis Lam 911d4ea37b move vite.config.js to config folder 3 years ago
Louis Lam 4039c6549e Merge remote-tracking branch 'origin/master' 3 years ago
giacomo892 d733ec018e
Prioritize host arg 3 years ago
Nelson Chan 03b07730d3 Fix: Increase default kept period 3 years ago
Louis Lam dbc87d8ab3
Merge pull request #670 from dhfhfk/master 3 years ago
dhfhfk 05b691d4c9
Fix typo 3 years ago
Louis Lam 029d6412da
Merge pull request #669 from pemassi/patch-2 3 years ago
Louis Lam 9f12f95cce
Merge pull request #666 from Rohlik/patch-1 3 years ago
Kyungyoon Kim c1112a32df
Update ko-KR.js 3 years ago
Kyungyoon Kim efc78acfeb
Update ko-KR.js 3 years ago
zsxeee 9e01959d15
Update zh-CN.js 3 years ago
zsxeee 3fe91c52cb
Fix i18n 3 years ago
Tomas Rohrer 5269dcec60
Fix length 3 years ago
zsxeee a2cc7d1db9
Avoid directory not found error 3 years ago
Louis Lam 18c5a16783
Update README.md 3 years ago
Andreas Brett 2538bd04ce notp verification defaults 3 years ago
Louis Lam b7528b9a4e
Merge pull request #657 from thomasleveil/patch-2 3 years ago
Thomas LÉVEIL 9c058054b9 [i18n] minor update to french translations 3 years ago
Louis Lam c6683e2a9b
Merge pull request #648 from atlochowski/patch-1 3 years ago
Louis Lam b558708be2
Merge pull request #650 from xjoker/master 3 years ago
Louis Lam fd0dd2d284
Merge pull request #652 from GhostSlayer/patch-1 3 years ago
xJoker 1bc77a06e5
Update server/notification-providers/feishu.js 3 years ago
xJoker 69c623ac2b
Update server/notification-providers/feishu.js 3 years ago
Atlochowski 69ffee55dd
Update pl.js 3 years ago
Slayer d769c4426c
Create PM2 Config file 3 years ago
Atlochowski ebf0671fef
Update pl.js 3 years ago
Louis Lam 97af09fd50
Update README.md 3 years ago
Louis Lam 5b19e3f025
Update README.md 3 years ago
wuwenjing ce2df137e6 change text to using variable `msg` 3 years ago
wuwenjing 6d9b71c054 Add Feishu notification 3 years ago
Atlochowski a433de74e6
Update pl.js 3 years ago
LouisLam 8e3f43d60b Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 2a1fd93444
Merge pull request #643 from andreasbrett/patch-3 3 years ago
Andreas Brett dc1de50a02 fix for max-inclusive 3 years ago
Andreas Brett e223e826a3 linting 3 years ago
Andreas Brett 0e6d7694ce
Update util.js 3 years ago
Andreas Brett 503d1f0a91
translation fixes 3 years ago
Andreas Brett 11bcd1e2ed
const 3 years ago
Andreas Brett 06310423f4
typo 3 years ago
Andreas Brett e127e168b6
typed parameters 3 years ago
Andreas Brett b5b391c73b
avoid default values for token verification 3 years ago
Andreas Brett 075535ba46
Update util.ts 3 years ago
Andreas Brett 13cf6891ac
cryptographically strong secret generation 3 years ago
Louis Lam ad0cde6554
Merge pull request #633 from dhfhfk/master 3 years ago
Louis Lam 25d18f0da3
Merge pull request #636 from DanielRTRD/add-norwegian-lang 3 years ago
RisedSky e9445bb2e3
Merge pull request #1 from RisedSky/RisedSky-patch-FR-Lang 3 years ago
RisedSky ecc25ba596
Update fr-FR.js 3 years ago
LouisLam e5286b0973 eslint for ko-KR.js 3 years ago
LouisLam 4e94cb9aad fix upload dist path 3 years ago
Daniel S. Billing 037fdd73a3 Norsk 3 years ago
Daniel S. Billing bb9a936658 Translated some of the notifications services 3 years ago
Bert Verhelst 5445c2a2ff fix(monitor): revert unintentional change to comment 3 years ago
Bert Verhelst dc08510e72 Merge remote-tracking branch 'origin/master' into feature/add-support-for-method-body-and-headers 3 years ago
Daniel S. Billing 62805014df Update Settings.vue 3 years ago
Daniel S. Billing c79e80442a Update i18n.js 3 years ago
Daniel S. Billing f0ff96afd9 Create nb-NO.js 3 years ago
Louis Lam 8083368a81
Merge pull request #634 from RisedSky/patch-1 3 years ago
RisedSky afb75e07d5
Update fr-FR.js 3 years ago
RisedSky efd3822930
Update fr-FR.js 3 years ago
dhfhfk 2adac64c83
Update ko-KR.js 3 years ago
Louis cee225bcb2 no idea why npm prune --production suddenly not working, switch to npm ci --production 3 years ago
Louis 8958c21736 Merge remote-tracking branch 'origin/master' 3 years ago
Louis 2286f78f57 update to 1.8.0 3 years ago
Louis d9eab90a69 Merge branch 'no-need-build' 3 years ago
Louis Lam 4ba2025451
minor 3 years ago
LouisLam 272d4bde45 find promossms language key typo 3 years ago
LouisLam 0550ceb6d4 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 82131f4dd2 merge conflict 3 years ago
Louis Lam 0c88e4b2f6
Merge pull request #629 from NixNotCastey/pl-update 3 years ago
Louis Lam 5c6230da58
Merge pull request #630 from xinac721/master 3 years ago
Louis Lam d6753b8833
Update SECURITY.md 3 years ago
Louis Lam 93a021d027
Update SECURITY.md 3 years ago
新逸Cary 54f864a1bb Update Simplified Chinese Language(更新简体中文语言) 3 years ago
Lukas d6f7be9112 Translated all missing texts and updated few of previously translated. 3 years ago
Bert Verhelst 5137c80c07 fix(monitor): handle empty headers 3 years ago
Lukas 792f3c7c5c Add support for values of Name, Hostname and Status 3 years ago
Bert Verhelst 8a739af5ad Merge remote-tracking branch 'origin/master' into feature/add-support-for-method-body-and-headers 3 years ago
Lukas edb75808d8
Merge branch 'louislam:master' into smtp-subject 3 years ago
LouisLam 56ae6f6117 fix demoMode export 3 years ago
Lukas 5e3ea3293c Very basic email subject customization 3 years ago
LouisLam 5c89562650 not allow lower than 20s for demo mode 3 years ago
Louis Lam 1f7f20526f
Merge pull request #620 from MrEddX/bulgarian 3 years ago
Louis Lam 0f5b437015
Merge pull request #622 from robinschneider/patch-1 3 years ago
Nelson Chan ac80631bcd Fix: Run clear data at specific time 3 years ago
Nelson Chan 8caf47988c Fix: Allow setting settings type 3 years ago
Robin Schneider 6fe014fa5e
Fixed spelling for german language support 3 years ago
Nelson Chan 6cf2eb036d Fix: Improve settings layout and wording 3 years ago
MrEddX 9d7def93a5
Update bg-BG.js 3 years ago
Nelson Chan dca5a59dbc Feat: Implement data clearing logic & frontend 3 years ago
Nelson Chan 656a4d6270 WIP: Enable background jobs 3 years ago
Louis Lam 6dd0e082b4
Merge pull request #614 from pemassi/patch-1 3 years ago
Kyungyoon Kim 2e95e2016d
Translate to Korean 3 years ago
Louis Lam 4169127143
Update FUNDING.yml 3 years ago
LouisLam cac0a46bac fix error if tls info object is in old format 3 years ago
Bert Verhelst d71d27220b fix(edit-monitor): store headers as JSON 3 years ago
Bert Verhelst fba4f86552 Merge branch 'master' into feature/add-support-for-method-body-and-headers 3 years ago
LouisLam e023ddf1c2 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 23a2d33f8c [backup] restore pushToken 3 years ago
Bert Verhelst b8093e909b fix(edit-monitor): fix minification of translations containing { } 3 years ago
Bert Verhelst c3c273f9df fix(edit-monitor): fix regex to allow a single header 3 years ago
Bert Verhelst daab2a05f5 Merge remote-tracking branch 'louislam/master' into feature/add-support-for-method-body-and-headers 3 years ago
LouisLam a15e9077fc [status page] clear cache if it is an important beat 3 years ago
Louis Lam 8431a25a3a
Update README.md 3 years ago
Louis Lam e8cc7ff771
Merge pull request #609 from dpatrongomez/patch-1 3 years ago
新逸Cary 5d617012a3
Merge pull request #5 from louislam/master 3 years ago
Daniel Patrón Gómez d7eac1a413
Update es-ES.js 3 years ago
Louis Lam c589bd836d
[test] change to npm install for pull requests 3 years ago
LouisLam 5ce09953e2 use Segoe UI font for Windows among all languages 3 years ago
LouisLam fc8d1e78b6 [push type] hide upside down mode, apply primary base url 3 years ago
LouisLam 3f26327f95 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam efb3f2b19c
Merge pull request #605 from NixNotCastey/promosms 3 years ago
Lukas db791c880a
Don't use then with await. 3 years ago
新逸Cary cdda182311
Merge pull request #4 from louislam/master 3 years ago
LouisLam a1c2a1bc52 [test] auto test for node lts only 3 years ago
Louis Lam 432b156fce
Merge pull request #595 from kvpt/status-page-default-locale 3 years ago
LouisLam 01812cc446 [test] add test for i18n currentLocale 3 years ago
Lukas dfd63386ba
Make PromoSMS actually working 3 years ago
LouisLam 11abc1f1e0 [test] add test for i18n currentLocale 3 years ago
LouisLam 288e87bb3d Merge branch 'master' into status-page-default-locale 3 years ago
Louis Lam 79ee0e1ef4
Update ask-for-help.md 3 years ago
LouisLam 8ae79ab9bf improve #560 3 years ago
Lukas 12b5489eb5 PromoSMS as Notification Provider 3 years ago
LouisLam ddad2dcb4a Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam e96121f69a fix merging mistake 3 years ago
LouisLam 5b4af550fb Merge branch 'master' into DeeJayPee_master 3 years ago
Louis Lam dd183e2ec2
Merge pull request #567 from Empty2k12/feature/matrix-notifications 3 years ago
LouisLam 0fcb310b97 Merge remote-tracking branch 'Empty2k12/feature/matrix-notifications' into feature/matrix-notifications 3 years ago
LouisLam 3a0143ac46 [matrix] use encodeURIComponent to handle the url encode 3 years ago
LouisLam 2ce5c28ed4 Merge branch 'master' into feature/matrix-notifications 3 years ago
Bert Verhelst ec4b7e4064 Merge remote-tracking branch 'louislam/master' into feature/add-support-for-method-body-and-headers 3 years ago
Kevin Petit 5b758a4e98 Better locale default for status page. 3 years ago
LouisLam 7907c07034 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam adfe640f42 show fewer beat on mobile 3 years ago
Louis Lam 469f7a3e32
Update README.md 3 years ago
LouisLam 9f1e7b0a88 Revert "fix(heartbeat-bar): cleanup css styling and minor syntax issues" 3 years ago
LouisLam cdf81a36d3 fix broken animation caused by #521 3 years ago
LouisLam bf4ac0cf17 fix dockerfile issue on arm 3 years ago
LouisLam c0846124c2 update vite to 1.6.4, since it fixed the issue 3 years ago
LouisLam 3d30ed3d3b update security policy 3 years ago
LouisLam deec15c09e [test] better job name 3 years ago
LouisLam 3423cb5d8e [test] try to auto test Windows and MacOS 3 years ago
LouisLam 20af179a82 [test] try to auto test Windows and MacOS 3 years ago
LouisLam 3c60800eab [test] github action please ok🙏🏻🙏🏻🙏🏻 3 years ago
LouisLam 34586d7b8f [test] github action please ok 3 years ago
LouisLam 2c19aef4dc minor 3 years ago
LouisLam 67a623be18 e2e testing, it's hard 3 years ago
LouisLam e5f6d7f047 slack and rocket.chat use the primary base url 3 years ago
LouisLam b69550f5b9 Improve the test 3 years ago
LouisLam d08a71ab49 Set primary base url in settings page 3 years ago
LouisLam ed67803af8 improve minor style 3 years ago
Louis Lam a6c839709c
Merge pull request #589 from MrEddX/bulgarian 3 years ago
Louis Lam 5eb3c6b194
Merge branch 'master' into bulgarian 3 years ago
LouisLam 8233f3b875 try to standardize the language name list 3 years ago
Bert Verhelst 8be4bf0e16 Merge remote-tracking branch 'louislam/master' into feature/add-support-for-method-body-and-headers 3 years ago
LouisLam cccf393ee5 update zh-HK.js 3 years ago
MrEddX 9f5bf37a96
Update Settings.vue 3 years ago
LouisLam 18e4702375 ignore .env 3 years ago
MrEddX 1eb3f63a82
Update bg-BG.js 3 years ago
Louis Lam 8c63536eb8
Merge pull request #451 from zsxeee/notification_form_i18n 3 years ago
LouisLam 3e1788983e Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam a8badb027d update modded node-sqlite3 to 6.0.0 3 years ago
MrEddX 0c6b434d79
Moved Bulgarian to the Cyrillic family languages 3 years ago
Louis Lam b5bd92ce78
Merge pull request #578 from jtagcat/et5 3 years ago
Louis Lam 3f80cf5e54
Merge pull request #581 from chakflying/patch-2 3 years ago
Bert Verhelst 162ef04c41 Merge branch 'master' into feature/add-support-for-method-body-and-headers 3 years ago
Nelson Chan a87595a849
Fix: Allow underscore in hostname 3 years ago
jtagcat 7626e1f2e4 l10n: update et 3 years ago
zsxeee 7f1edb49bc
Fix i18n 3 years ago
Gero Gerke d184733af9 update text 3 years ago
Gero Gerke 704d63b49f
Merge branch 'master' into feature/matrix-notifications 3 years ago
zsxeee 7002a778f0
Rollback vue-i18n version to 9.1.7 3 years ago
zsxeee 54d2fbcc02
Fix i18n 3 years ago
Gero Gerke fbd4d54812
Update src/components/notifications/Matrix.vue 3 years ago
LouisLam c8706b9aa1 Merge branch 'master' into notification_form_i18n 3 years ago
Louis Lam 54d7830813
Update CONTRIBUTING.md 3 years ago
LouisLam fef26f3d5e Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam cb263f2a08 [test] wait for #language 3 years ago
Louis Lam 52102d72a0
Merge pull request #572 from Brainpitcher/patch-1 3 years ago
LouisLam 2b00e59c7a [test] update 3 years ago
Louis Lam 8ea7a693a1
Merge pull request #499 from Saibamen/fix_pl_i18n 3 years ago
LouisLam 4ded0c073a [test] fix timeout issue 3 years ago
Brainpitcher 7a8b6a03e0
Update ru-RU.js 3 years ago
Gero Gerke 6bebc623f9 UI polish 3 years ago
Gero Gerke 34b86352f2 remove double spaces 3 years ago
Gero Gerke 99e8a33118 escape room characters 3 years ago
Gero Gerke d7cc585101
Update server/notification-providers/matrix.js 3 years ago
Gero Gerke 8c357a04bf
Update src/components/notifications/index.js 3 years ago
DeeJayPee 044c78aa2d Typo \o/ 3 years ago
DeeJayPee 49eaa1a166 Typo fix 3 years ago
DeeJayPee 215cc07907 Rename versions 3 years ago
LouisLam 22227be408 update version in wiki too 3 years ago
Gero Gerke 5decfb9fad Matrix Notifications 3 years ago
DeeJayPee f9d7b99367 Add legacy version back on refactored master branch 3 years ago
DeeJayPee 359fe52c2e Merge branch 'louislam-master' 3 years ago
DeeJayPee bc4db6c692 Merge branch 'master' of https://github.com/louislam/uptime-kuma into louislam-master 3 years ago
DeeJayPee f14a798b2c Fix indentation + typo 3 years ago
Bert Verhelst a0ffa42b42 fix(translations): add translations for method body and headers to dutch 3 years ago
Bert Verhelst 550825927c Merge branch 'master' into feature/add-support-for-method-body-and-headers 3 years ago
LouisLam c1501742f5 test github secret 3 years ago
LouisLam 7c98fe603e test github secret 3 years ago
LouisLam b7ae49c644 update github action 3 years ago
LouisLam edad2caf8e return the correct exit code from jest 3 years ago
LouisLam 2bf6a04f81 fix preparing test 3 years ago
Louis Lam f0670dde20
Update auto-test.yml 3 years ago
Louis Lam 73068763c0
Create auto-test.yml 3 years ago
LouisLam 73bf1216d1 [wip] more test 3 years ago
LouisLam 98436f91b5 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 49720c709c improve the test with a single command only "npm test" 3 years ago
Louis Lam 842d359ad3
Update CONTRIBUTING.md 3 years ago
LouisLam e71f5bf314 update dependencies 3 years ago
LouisLam 79e0c9e1f1 setup unit test for setup 3 years ago
LouisLam e6ff957d9d Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 865b721b79
Merge pull request #519 from chakflying/improve-certInfo 3 years ago
LouisLam b5d987863d Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 911690bea8
Merge pull request #521 from bertyhell/bugfix/heartbeat-bar-cleanup 3 years ago
LouisLam d25603e629 update jest test 3 years ago
LouisLam 259bcf9426 [SMTP] "To Email" is not required if CC/BCC is set. (#461) 3 years ago
Bert Verhelst afeb424dc0 fix(edit-monitor): add translations to en.js 3 years ago
Bert Verhelst 6b44116245 Merge remote-tracking branch 'louislam/master' into feature/add-support-for-method-body-and-headers 3 years ago
Louis Lam aa478af286
Merge pull request #557 from Saibamen/patch-1 3 years ago
Adam Stachowicz 5f8d0faacd
Update CONTRIBUTING.md 3 years ago
Adam Stachowicz 707e05c330 Fix after merge 3 years ago
Adam Stachowicz 4da63c5fb8 Revert `silentTranslationWarn` change 3 years ago
Adam Stachowicz 8ae64843fc run update-language-files 3 years ago
Adam Stachowicz 23e64b8efd Merge branch 'master' into fix_pl_i18n 3 years ago
Louis Lam 8c55a8bf98
Update CONTRIBUTING.md 3 years ago
Louis Lam 387a8919f9
Merge pull request #542 from csabibela/master 3 years ago
Louis Lam a1edc23b1d
Merge pull request #540 from jtagcat/et4 3 years ago
Bert Verhelst 7ee89fab5c
fix(edit-monitor): Make json capitalised 3 years ago
Csábi Béla 980342546e Merge branch 'hu' 3 years ago
Csábi Béla 6b60dc9630 Initial Hungarian translation 3 years ago
Csábi Béla 8d22b43f24 Revert "Initial Hungarian translation" 3 years ago
Csábi Béla dad58341c6 Initial Hungarian translation 3 years ago
jtagcat 275902be38 update estonian translation 3 years ago
jtagcat 38213585f3 update style for et translation 3 years ago
LouisLam 37d1e50ff1 fix data path for test 3 years ago
LouisLam a2a4c70cf5 setup jest-puppeteer 3 years ago
Louis Lam 446fc1af0b
Update CONTRIBUTING.md 3 years ago
LouisLam 51acd107e3 Merge branch 'master' into notification_form_i18n 3 years ago
LouisLam d3517e76c1 change to npm ci 3 years ago
Bert Verhelst 3f0b85e5a8 feat(http-requests): add support for methods, body and headers for http 3 years ago
LouisLam 2625cbe0d2 add script for downloading the dist files from github 3 years ago
LouisLam c93f42794f upload prebuilt dist to github release 3 years ago
Nelson Chan 668fd58af3 Fix: Slightly improve validity styling 3 years ago
Nelson Chan b7568e9caa Fix: Update Certificate Icon 3 years ago
Bert Verhelst 1c2adf8723 fix(monitor-list): increase padding to keep same monitor item height 3 years ago
Bert Verhelst 96129921e9 Merge remote-tracking branch 'origin/master' into bugfix/heartbeat-bar-cleanup 3 years ago
Louis Lam 2b1fe815f9
Merge pull request #522 from bertyhell/bugfix/improve-setup-styles 3 years ago
Louis Lam fcf017d5c7
Merge pull request #523 from bertyhell/bugfix/hide-dashboard-and-settings-when-not-logged-in 3 years ago
Bert Verhelst 843830a38a fix(layout): hide dashboard and settings buttons when not logged in 3 years ago
Bert Verhelst ee830621dd fix(login): fix the same padding issues for the login screen 3 years ago
Bert Verhelst c2a560e2ed fix(setup): increase left padding input fields + avoid clipping 3 years ago
Nelson Chan 13bdfefa9d Feat: Improve Certificaet Info Display 3 years ago
Bert Verhelst 3d6c8b7f05 fix(heartbeat-bar): cleanup css styling and minor syntax issues 3 years ago
LouisLam 2aaed66b38 [docker: debian] reduce the image size dramatically! Compressed size from 240 MB~ to 100 MB~ 3 years ago
LouisLam 7b4c70860c split the base images in order to prevent recompile the base part 3 years ago
LouisLam 6513c3e75f allow update minor version only, to prevent the breaking change in the future like vite 2.6 3 years ago
LouisLam 7fa1cb83af [push type] add ping parameter 3 years ago
Louis Lam 9d079eeec0
Merge pull request #487 from cmandesign/feature/fa-lang-rtl 3 years ago
LouisLam 21dd5ad3dd Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 3394e1f148 fix undefined callback 3 years ago
Louis Lam ee22406301
Update README.md 3 years ago
LouisLam 8d5eaaf8a7 minor 3 years ago
LouisLam b246c8e0f2 Fix 2fa for iOS Google authenticator (#486) 3 years ago
LouisLam 1ed4ac9494 add Push-based monitoring (#279) 3 years ago
zsxeee 0f2059cde0
Use named slot translation when has multi-slot 3 years ago
zsxeee 138ddf5608
Move attribute `tag` to start of tag 3 years ago
zsxeee dcd68213b1
Merge remote-tracking branch 'upstream/master' into notification_form_i18n 3 years ago
Louis Lam 9e95d568c2
Merge pull request #501 from Saibamen/incident_use_local_timezone 3 years ago
Louis Lam fa3da819f8
Merge pull request #512 from chakflying/reduce-bundle-size 3 years ago
Louis Lam 9e1f1f006b
Merge pull request #511 from chakflying/fix-multiselect-css 3 years ago
Louis Lam 55cb497301
Merge pull request #427 from zsxeee/notification_component 3 years ago
LouisLam 8d8d5987e7 update to 1.7.3 3 years ago
LouisLam 1fa90bffaa freeze vite version to 2.5.* (2.6.* is broken when build the project) 3 years ago
LouisLam 67f221d3c7 update to 1.7.2 3 years ago
Nelson Chan 05f28fecb2 Build: Use async component for status and settings 3 years ago
Nelson Chan ba4a4aaf1c Chore: Move multiselect css to own file 3 years ago
LouisLam 6eceb4c744 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 3e4154dfb5 Fix retry interval affected bug 3 years ago
Louis Lam fbc8828ddc
Merge pull request #464 from chakflying/fix-delete-monitor 3 years ago
Soroosh f2c7308c96 Fixed Change Language Direction In Setting Page 3 years ago
LouisLam 3677aa639f update to 1.7.1 3 years ago
LouisLam aaddfa1786 update package-lock.json 3 years ago
LouisLam 6d65d248f4 Merge branch 'bulgarian' 3 years ago
LouisLam 87a4748b40 check back to root user for Debian, until problem has been found (#488) 3 years ago
Louis Lam 182bdf13a7
Merge pull request #500 from Saibamen/remove_timezone_console_log 3 years ago
MrEddX 0f66e5cfc5 Added Bulgarian Language 3 years ago
Louis Lam fe5ae46013
Merge pull request #480 from gaby/init-support 3 years ago
Denis Freund efbadd0737 only allow ip address for hostname when monitor type is steam 3 years ago
Adam Stachowicz f9d633e02b Display created and updated time in local timezone. Fixes #491 3 years ago
Adam Stachowicz 756f317f82 Remove "Skip Timezone" console log from frontend 3 years ago
Adam Stachowicz fa9d26416c `silentTranslationWarn` if not development 3 years ago
Adam Stachowicz 58aa83331e Fix Polish language, add missing `Status Page` i18n 3 years ago
Louis Lam cc9fe26584
Merge pull request #498 from kry008/patch-2 3 years ago
kry008 99818aa370
Update pl.js 3 years ago
Louis Lam 682265fe9c
Merge pull request #481 from DX37/translation-ru 3 years ago
Louis Lam 4406e51ab6
Merge pull request #496 from bertyhell/bugfix/remove-zero-width-spaces 3 years ago
Louis Lam c3d5be5a5e
Merge pull request #493 from iomataani/master 3 years ago
Louis Lam dfe12c99c1
Merge pull request #490 from Minvinea/master 3 years ago
Louis Lam bb69851160
Merge pull request #485 from Lrss/patch-1 3 years ago
Louis Lam 6c9323351d
Merge pull request #484 from xinac721/master 3 years ago
Bert Verhelst 8e9fa20e57 fix(nl-NL): remove ZWSP from translation 3 years ago
Ioma Taani da7c29f4b9 updated translation 3 years ago
Denis Freund b67b4d5afd add steam gameserver for monitoring 3 years ago
Soroosh 9f06d54688 Remove font import and update font-family for lang fa 3 years ago
Soroosh 1448de7b19 Update some translations 3 years ago
Minvinea e545d48583
Update fr-FR.js 3 years ago
Soroosh 47749ca58d Replace some hardcoded with translations 3 years ago
Soroosh 04b7a4a423 Merge Conflict Resolved 3 years ago
Soroosh 56d8f585fd Add postcss-rtlcss and postcss-scss 3 years ago
Soroosh 07c9d78829 Update Farsi translations 3 years ago
Soroosh 15c4a8fb02 Add RTL direction support to styles using postcss & rtlcss 3 years ago
Soroosh f41e95921f Enable localization for pagination 3 years ago
Soroosh 647184e5d1 Update Title to use translation files 3 years ago
Soroosh e60426bdcd Add Localization CSS & Persian Font 3 years ago
Lars Sørensen 8d84d8f891
Update da-DK.js with new strings 3 years ago
新逸Cary 74acc2cea7 Update Simplified Chinese Language(更新简体中文语言) 3 years ago
新逸Cary ba4a4089eb
Merge pull request #3 from louislam/master 3 years ago
Soroosh 251d42f1a6 Add localeDirection method to i18n.js 3 years ago
DX37 122631c91b
fix some ru-RU lines and add new ones 3 years ago
Juan Calderon-Perez 1e12f25c4b Add support for using init to start service 3 years ago
LouisLam 9e10296290 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 87e213085f add /status, alias of /status-page (#471) 3 years ago
Louis Lam d9038f1da2
Merge pull request #473 from Ponkhy/german-language 3 years ago
Louis Lam 3fb2d0ce68
Update README.md 3 years ago
Ponkhy 50a33e3b45 Added german translation for the status page 3 years ago
zsxeee f24abac7fc
Merge branch 'master' into notification_component 3 years ago
LouisLam ce9a97a107 update to 1.7.0 3 years ago
LouisLam 0afa3a2c21 Merge branch '1.6.X' 3 years ago
LouisLam 51512b6f5f update dependencies 3 years ago
Louis Lam 3d79e841c9
Merge pull request #466 from chakflying/public-dashboard 3 years ago
Nelson Chan d2af42e579
Fix: Add placeholder if no monitors to add 3 years ago
LouisLam d6e3bd2282 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 70fbe9a2d9 fix alpine nightly build 3 years ago
Louis Lam c669e7eaba
Merge pull request #469 from chakflying/patch-1 3 years ago
LouisLam 9a9fd41f62 Merge branch 'master' into patch-1 3 years ago
LouisLam 50b868e751 fix #465 3 years ago
LouisLam a856780066 fix the active link problem 3 years ago
LouisLam 266b03fbf7 language key from "Status Page Nothing" to "statusPageNothing" 3 years ago
Nelson Chan 662c97dcde
Fix: Fix importing tag if tag doesn't exist 3 years ago
Louis Lam 1ebf752f1a
Merge pull request #415 from Ponkhy/import-export 3 years ago
Mawoka 69bb6ef290 Removed empty selector if no monitor available 3 years ago
Ponkhy 720ea850e1 Added space between Dashboard and settings button 3 years ago
Ponkhy 7fb55b8875 Fixed issues 3 years ago
Ponkhy 4786514e9f
Merge branch 'louislam:master' into import-export 3 years ago
Nelson Chan 32c9dfbb31 Fix: clear important beats after deleteMonitor 3 years ago
Ponkhy d3d4363031 Used compare-version instead of replace 3 years ago
Louis Lam 6f352a6e3c
[guide] update how to start dev server 3 years ago
Louis Lam 3fb06a8ba4
Merge pull request #463 from CosmoAbdon/ptBR-Translation 3 years ago
Louis Lam b3a5a5b0ba
Merge pull request #462 from Saibamen/development_server 3 years ago
Cosmo Abdon a4cad3db65 add: BR Portuguese Language and new words 3 years ago
Adam Stachowicz 5fa9b33c79 Install `cross-env` as dev dependency for now 3 years ago
Adam Stachowicz f6a984b671 start-server-dev. Fixes #460 3 years ago
LouisLam 23a63213aa Merge branch 'master' into import-export 3 years ago
Louis Lam a9bb8ae6a1
Merge pull request #124 from chakflying/public-dashboard 3 years ago
LouisLam 27d4c3c194 [status page] improve mobile layout 3 years ago
LouisLam 439f45d91e [status page] improve the entry 3 years ago
Louis Lam 66598a81cc
Merge pull request #452 from chakflying/patch-8 3 years ago
Nelson Chan 45a6f364e1 Chore: Fix backslash in IP regex 3 years ago
Nelson Chan 95391be2ab
Revert Regex update 3 years ago
zsxeee 624f632a7a
Apprise status translation key 3 years ago
LouisLam 5f533b9091 [status page] fix wrong foreign key 3 years ago
LouisLam 29920f6b60 [status page] use normal link to status-page, due to data reset problem 3 years ago
zsxeee 6e9d12638c
Avoid space ending in translation key 3 years ago
zsxeee 6e55c44773
Chore 3 years ago
LouisLam ad1bb93730 [status page] fix logo url 3 years ago
LouisLam 0a5a6e6a4b [status page] fix monitor order 3 years ago
LouisLam fe0fc63843 [status page] send uptime 3 years ago
Nelson Chan 5b2e1f6086
Fix: Allow number ending TLD 3 years ago
LouisLam 8c7ee94769 add modified apicache library with disabling client cache 3 years ago
LouisLam 0834770509 [status page] also apply the title to <title> 3 years ago
LouisLam a71814c80b add util.ts comments 3 years ago
LouisLam 17073fd786 Merge branch 'master' into public-dashboard 3 years ago
LouisLam 15c00d9158 upload logo and expose ./data/upload to url 3 years ago
Nelson Chan d2b34f9285
Chore: make eslint happy 3 years ago
Nelson Chan a96a515087
Fix: Fix hostname with dash 3 years ago
Nelson Chan 2eab919ae0
Fix: Fix typo 3 years ago
Nelson Chan c09b67b94d
Fix: Fix TCP Ping hostname Regex 3 years ago
zsxeee 601204ae77
Default friendly name i18n and auto increase 3 years ago
LouisLam 61c737c53c fix alert text color in dark mode 3 years ago
Louis Lam 2820118eba
Merge pull request #446 from Saibamen/util 3 years ago
LouisLam 469e8f6fd6 Merge branch 'master' into public-dashboard 3 years ago
LouisLam 780cb0a145 install-legacy-peer-deps to install-legacy 3 years ago
zsxeee 8c941b1d56
Add i18n for notification form 3 years ago
LouisLam 1c8b3ce451 no need to build sqlite and add nightly for alpine 3 years ago
Adam Stachowicz e8ef63e0a3 `removeComments` to false 3 years ago
LouisLam 4591adc05e second attempt: prebuilt node-sqlite3 and update SQLite to 3.36 3 years ago
LouisLam 5f6aa32844 fix store/fetch status page config 3 years ago
LouisLam a8e170f6a8 Merge branch 'master' into public-dashboard 3 years ago
LouisLam 6aaf984f29 fix retryInterval = 0 if it is an old monitor. (#380 https://github.com/louislam/uptime-kuma/pull/380#issuecomment-922618356) 3 years ago
LouisLam 76a39f1388 update to 1.6.3 3 years ago
LouisLam 34c0fa59a8 fix reset-password (#448) 3 years ago
LouisLam 0664217a09 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam b0e9c5bcb4 fix reset-password (#448) 3 years ago
LouisLam 0b572df3d0 [status page] store config 3 years ago
zsxeee ad6fcc2f2e
Merge branch 'master' into notification_component 3 years ago
Adam Stachowicz bcc02c1680 Add formatting and comments from `util.ts` to `util.js` 3 years ago
Louis Lam 795d5f586f
Merge pull request #444 from Saibamen/avg-ping_avg-response 3 years ago
LouisLam 7ee98d989c [status page] implement rest api for heartbeat 3 years ago
Adam Stachowicz 7dc1e84e44 Avg. Ping and Avg. Response translation keys 3 years ago
LouisLam 6350c43cc3 fix newline? 3 years ago
LouisLam fd95d41d9f [status page] many update and save group list 3 years ago
zsxeee ffbc25722d
Move default setting to child component 3 years ago
Louis Lam 7665bae927
Merge pull request #441 from iomataani/master 3 years ago
Ioma Taani 09e38269c6
Merge branch 'louislam:master' into master 3 years ago
LouisLam 6681f49a58 Merge branch 'master' into public-dashboard 3 years ago
Louis Lam 3fc2ba3d76
Merge pull request #436 from nbvcxz/running_non-root_user 3 years ago
Louis Lam 78e12ab899
Merge pull request #439 from gaby/dockerignore 3 years ago
Juan Calderon-Perez 2b8c049e7b
Add missing entries to dockerignore 3 years ago
LouisLam f0ac3c82d2 add some comments 3 years ago
Louis Lam 803029a9e4
Merge pull request #429 from Ponkhy/main 3 years ago
Louis Lam c3f1cebeab
Merge pull request #435 from DX37/translation-ru 3 years ago
Louis Lam 5d9814559c
Merge pull request #424 from Saibamen/fix_PL 3 years ago
DX37 9ef45a9c7e
fresh translations to ru-RU.js and Settings.vue 3 years ago
Michal Ciania 7f78cc8d0f Substitute default values only once 3 years ago
Ioma Taani ca84044809
Merge branch 'louislam:master' into master 3 years ago
Michal Ciania 9eaa4ab846 Docker entrypoint for running the application as non-root user 3 years ago
Marcos Sigueros Fernández c3122a9807
Update es-ES.js (#430) 3 years ago
Ponkhy f6498caa9a Merge branch 'main' of https://github.com/Ponkhy/uptime-kuma into main 3 years ago
Ponkhy 3a0bc80016 Added regex to hostname input 3 years ago
zsxeee 2fb3c40307
Variable name and key binding 3 years ago
zsxeee 66e40d9fcb
Edit comment and remove unused variable 3 years ago
Ioma Taani cbbc503f8e
Merge branch 'louislam:master' into master 3 years ago
zsxeee de8b61ef2b
Remove unused imports 3 years ago
zsxeee 534ac4b720
Move Apprise check to child component 3 years ago
zsxeee e9735d239b
Convert notification form to separate component 3 years ago
Louis 5be51abd8f Merge remote-tracking branch 'origin/master' 3 years ago
Louis 6ec219908b test nodejs 16 3 years ago
Louis a6fdd272a6 [status page] minor 3 years ago
Ponkhy 1b5e723f60 Added descriptions to uploadBackup function 3 years ago
Ponkhy 4bdada36a9 Removed if includes version 3 years ago
Adam Stachowicz 250c2bdd6d Missing this 3 years ago
Adam Stachowicz 8e49d84050 Fix polish translation and translate new keys 3 years ago
Louis Lam 112d72da47
update discussion 3 years ago
LouisLam 9b8f01cfc6 since eslint can auto fix semicolon, standardize all end with semicolon 3 years ago
LouisLam 579e07ded4 Merge branch 'master' into public-dashboard 3 years ago
kry008 a04878fa84
Finishing the translation of PL (#422) 3 years ago
LouisLam 2955abb5d9 [status page] create incident 3 years ago
LouisLam 8230cfe13f use "next" tag to keep vue3 up-to-update 3 years ago
Ponkhy 8b463e70df
Apply suggestions from @Saibamen 3 years ago
LouisLam 392f8275b3 Merge branch 'master' into public-dashboard 3 years ago
Ioma Taani 783ec97004 updated translations 3 years ago
Siim Ots 4f4fe39c9b
Simple "Add to Homescreen" manifest (PWA) (#411) 3 years ago
LouisLam 611d214a32 [status page] checkpoint 3 years ago
Louis Lam 7a0cebf5bb
Merge pull request #414 from Saibamen/lang_fixes 3 years ago
Ponkhy 54aa68ec58 Added import/export compatibility for version 1.7 3 years ago
Adam Stachowicz 217637aa1f Add de-DE translation 3 years ago
Adam Stachowicz ab22961538 More info about `update-language-files` command 3 years ago
Adam Stachowicz 8ba8de07ae Missing this 3 years ago
Adam Stachowicz a34b2623c8 Remove double spaces in `console.log` output with multiple parameters 3 years ago
Adam Stachowicz 79920b5f2c Fix languages after 80322cbfe7 3 years ago
Louis Lam 72783fd94c
Merge pull request #380 from No0Vad/retry-heartbeat-interval 3 years ago
LouisLam 80322cbfe7 Merge branch 'import-export' 3 years ago
LouisLam 7e0272077b cleanup demo mode code 3 years ago
LouisLam b2ff6b6098 update ignore files and delete demo db 3 years ago
LouisLam 512ff09cca set entry page 3 years ago
LouisLam e8f4fabcd0 [status page] crop and resize logo 3 years ago
Ponkhy f679c1cbaf Export button align left 3 years ago
LouisLam 2ab06f87b8 Merge branch 'master' into public-dashboard 3 years ago
Louis Lam 76db55b657
Merge pull request #395 from WillianRod/feat/add-microsoft-teams-notification 3 years ago
LouisLam 1693873f4a [Teams] change handleTestNotification to GeneralNotification 3 years ago
Louis Lam 53bfdb7dad
Merge pull request #409 from iomataani/master 3 years ago
LouisLam db05b506f3 [status page] checkpoint 3 years ago
Ioma Taani 0752f810f1 updated 3 years ago
Louis Lam 200d233607
Merge pull request #407 from SametKUM/master 3 years ago
samet.kum 7274913686 Turkish Language added 3 years ago
No0Vad 1300448bed Adjustments to the retry interval 3 years ago
Louis Lam 3f67326fce
Merge pull request #404 from Ponkhy/main 3 years ago
Louis Lam 8b48f9bd22
Merge pull request #405 from zidingz/patch-1 3 years ago
Louis Lam 76348cae5d
Update SECURITY.md 3 years ago
Louis Lam 0b32adadb8
Update SECURITY.md 3 years ago
Ziding Zhang 3425a27a0e
Update SECURITY.md 3 years ago
Ponkhy fff5fd8e9e Added search key 3 years ago
LouisLam 1d6670ed9a Merge branch 'master' into public-dashboard 3 years ago
LouisLam 795411a11c Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 3234aec5b3 NODE_ENV if not set, change to production 3 years ago
LouisLam afe91078c4 [status page] checkpoint 3 years ago
Louis Lam 2009f7097d
Merge pull request #403 from Ponkhy/main 3 years ago
Ponkhy c14b71a4a7 Added german translation for tags manager 3 years ago
LouisLam 35fe9690e8 update to 1.6.2 3 years ago
LouisLam ad2062713c fix pi4 on docker 3 years ago
Louis Lam 379656335d
Merge pull request #402 from xoniq/lang-nl 3 years ago
LouisLam fc9b4617ca link interval and retryInterval 3 years ago
Jelle Posthuma 40d301457a Update new / updated translations to nl_NL 3 years ago
LouisLam 9902c181bc Merge branch 'master' into public-dashboard 3 years ago
Louis Lam 069c811af8
Merge pull request #278 from chakflying/tags 3 years ago
LouisLam f9311e4e7f [status page] 3 years ago
LouisLam 34abff4724 manual merge master 3 years ago
LouisLam d7a230ac15 Merge branch 'master' into public-dashboard 3 years ago
LouisLam 9da2a01a74 [status page] checkpoint 3 years ago
Nelson Chan 74da02da2c Fix: Prevent enter in modal from submitting form 3 years ago
LouisLam 97360dab26 add /.well-known/change-password 3 years ago
Louis Lam 56dad006b5
Merge pull request #401 from NeuralMiner/patch-1 3 years ago
NeuralMiner 47092258f8
Allow SMTP that doesnt require authentication. 3 years ago
Willian Rodrigues Barbosa a0838543b9 Merge branch 'feat/add-microsoft-teams-notification' of https://github.com/WillianRod/uptime-kuma into feat/add-microsoft-teams-notification 3 years ago
Willian Rodrigues Barbosa ccb8736b3d fix: send msg if heartbeat message is not set 3 years ago
LouisLam f351b423c5 link to the english version of microsoft link 3 years ago
LouisLam ab6b97d77a update dependencies, fix axios security problem 3 years ago
LouisLam 0e16e88fa8 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam c746923018 merge italian language file 3 years ago
LouisLam df8754827d Merge branch 'italian-language-update' 3 years ago
Louis Lam 2c02dad1f9
Merge pull request #393 from Revyn112/master 3 years ago
LouisLam 600ec6d171 Merge branch 'master' into i18n_router_own_files 3 years ago
LouisLam 728636de06 Merge branch 'feature/timezones-package' 3 years ago
LouisLam 8be7fd5c45 Merge remote-tracking branch 'bertyhell/feature/timezones-package' 3 years ago
LouisLam 59ff9fa293 update missing timezone console msg 3 years ago
LouisLam a654e409df Merge branch 'master' into feature/timezones-package 3 years ago
LouisLam 76f1f34a0a fix #397, incorrect encode function for export file 3 years ago
LouisLam 35aca46b68 [status page] checkpoint 3 years ago
DeeJayPee 29d0db805d Add legacy octopush (Octopush-DM from 2011 to 2020 accounts) version 3 years ago
Paride Barison 6a925c7ed4 sistemato l'ordine 3 years ago
Paride Barison 8b9b86b478 updated 3 years ago
Nelson Chan 7c4b5f189b Fix: Fix hiding form when reusing draft tags 3 years ago
Nelson Chan a6f9762c4d Feat: Split add tag to modal 3 years ago
Nelson Chan a0e4e96160 Fix: Fix tag removal, reuse and validation 3 years ago
Nelson Chan fcbeed55bf Fix: Allow removing and re-adding the same tag 3 years ago
Nelson Chan 9b5abf9bb1 Fix: reset editMonitor after save 3 years ago
Nelson Chan 73f4b8e177 Fix: Improve various tags validation logic 3 years ago
Nelson Chan e6669fbb9e Fix: Improve searchbar padding on mobile 3 years ago
Nelson Chan e66a2d362d Feat: Add monitorList search box 3 years ago
Nelson Chan c2148fc0f1 Fix: Slightly reduce tag opacity on light theme 3 years ago
Nelson Chan 6e3a904aaa WIP: Add tags functionality 3 years ago
Louis Lam 50175b733c
Merge pull request #396 from Ponkhy/2fa 3 years ago
No0Vad 2617e1f4d8 Update database.js 3 years ago
No0Vad 91ee39ec60
Merge branch 'master' into retry-heartbeat-interval 3 years ago
Ponkhy 4711aeb355
Merge branch 'master' into import-export 3 years ago
Ponkhy db9e97d859
Merge pull request #2 from Saibamen/import-export 3 years ago
Adam Stachowicz 7199bb5ead Remove unused i18n key 3 years ago
Ponkhy bb87972543 Hide 2FA section if disabled auth 3 years ago
Adam Stachowicz ea723c7595 Separate import and export. Fix ESLint 3 years ago
LouisLam e205adfd7b [status page] developing 3 years ago
Willian Rodrigues Barbosa 063d64eec8 feat: add microsoft teams notification provider 3 years ago
Adam Stachowicz 5abf2e7597 Missing this 3 years ago
Adam Stachowicz 7c83bed273 Remove double spaces in Dockerfiles 3 years ago
Adam Stachowicz 1cc788da68 Missing this 3 years ago
Adam Stachowicz 54ffef8b7a Own files for i18n and router + fix some of markdown warnings 3 years ago
Revyn112 44aa837a9d
Update NotificationDialog.vue 3 years ago
LouisLam f47f7758f9 Merge branch 'master' into public-dashboard 3 years ago
Bert Verhelst ddcd3c2a19 Merge remote-tracking branch 'origin/master' into feature/timezones-package 3 years ago
LouisLam 7df9698e5d eslint: comma-dangle for language files 3 years ago
Bert Verhelst 471333ad03 fix(util-frontend): revert typescript conversion 3 years ago
Ponkhy d313966d80
Merge branch 'master' into import-export 3 years ago
LouisLam 8205f90f3d update language files 3 years ago
LouisLam 02247c4174 Merge remote-tracking branch 'origin/master' 3 years ago
Denis Freund 8352d9abbe add posibility to have a prefixMessage before the embed 3 years ago
Louis Lam 2d7767c905
Merge pull request #392 from bertyhell/bugfix/button-margin-settings 3 years ago
Louis Lam c52b9b63d5
Merge pull request #389 from Ponkhy/default-notification 3 years ago
Louis Lam e55193270d
Merge pull request #377 from Lrss/master 3 years ago
Louis Lam 9d39071a91
Merge pull request #363 from Ponkhy/2fa 3 years ago
No0Vad 389d247463
Update server/database.js 3 years ago
Bert Verhelst a170694a83
fix(util-frontend): improve formatting timezoneList 3 years ago
Bert Verhelst 5969e913b5
fix(util-frontend): improve formatting 3 years ago
Louis Lam 0d280f5edb
Merge pull request #376 from chakflying/patch-7 3 years ago
Bert Verhelst 660b969178 fix(settings): switch custom styles to bootstrap class for bottom margin 3 years ago
Bert Verhelst c26622aa39 fix(settings): add some button bottom margin for narrow screens 3 years ago
Bert Verhelst a7674755ba Move timezones to npm package and convert util-frontend.js to typescript 3 years ago
Louis Lam 6d7cb44acc
Merge pull request #387 from jtagcat/et2 3 years ago
LouisLam 400fc13cf2 add npm install script for npm7 3 years ago
Ponkhy db14768229 Wording correction for notification modal 3 years ago
No0Vad 3d27561e5a Update en.js 3 years ago
jtagcat b80c88d9a0 i10n: update Estonian 3 years ago
Ponkhy 862672731f Minor typo fix 3 years ago
Ponkhy 7fee4a7ea7 Added import options 3 years ago
LouisLam c4f78d776e [2fa] "UptimeKuma" to "Uptime Kuma" 3 years ago
No0Vad f8f9f59464 Added support for a retry interval to monitors 3 years ago
LouisLam 934685637a [Status Page] WIP: Checkpoint 3 years ago
Ponkhy 295ccba44b Adjusted for new db patch management 3 years ago
Ponkhy 8cd5bad44c
Merge branch 'master' into 2fa 3 years ago
Ponkhy d003abcd60
Update src/languages/en.js 3 years ago
Ponkhy f6d1a82989
Update server/server.js 3 years ago
Ponkhy 651b525d06
Update server/server.js 3 years ago
Lars Sørensen 66769e1c79
Fixed inconsistent white-space for the "Avg."-Ping/Response title. 3 years ago
LouisLam 3e25f0e9d9 [Status Page] WIP: Checkpoint 3 years ago
Lars Sørensen 39c7b5e748
Added new Strings to Danish translation 3 years ago
Lars Sørensen b709857e19
Better wording for Danish language 3 years ago
Nelson Chan 9e10f7d35f
Fix: Fix events table width on mobile 3 years ago
Louis Lam 6caae725f9
Merge pull request #375 from Saibamen/format_backup_json 3 years ago
Adam Stachowicz c387fb264e Format JSON file before download 3 years ago
LouisLam 4b0a8087a2 do not connect to socket io for status page 3 years ago
LouisLam 08c7a37052 Merge branch 'master' into public-dashboard 3 years ago
LouisLam 0969be5981 Revert "WIP: Add login page, nav bar buttons" 3 years ago
LouisLam 2ed8f12dc0 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 2da77d8448 fix ipv6 connection problem 3 years ago
Louis Lam f8322de5da
Update bug_report.md 3 years ago
Louis Lam e21a18a593
Update ask-for-help.md 3 years ago
Ponkhy 14b7688b70 Added NOT NULL to twofa_status 3 years ago
LouisLam d953ba7c60 update to 1.6.1 3 years ago
LouisLam ef1604675b change to node:14-bullseye-slim, and reduce the docker image size 3 years ago
Louis Lam 83fc844e8e
Update deployment.yml 3 years ago
Louis Lam 22a7acbaf6
Update README.md 3 years ago
LouisLam 201bba63d7 add a healthcheck comment 3 years ago
Ioma Taani 0d6888c586
Merge branch 'louislam:master' into italian-language-update 3 years ago
Ioma Taani a06fc14213
Merge branch 'louislam:master' into italian-language-update 3 years ago
LouisLam 31b4a5c33e build-docker, debian first 3 years ago
Paride Barison 951ece8a65 updated 3 years ago
LouisLam a49df29a87 update to 1.6.0 3 years ago
LouisLam 08de0090dc add a better approach for patching db, change setting.value from varchar to TEXT, restore Database.close() to 1.2.0 3 years ago
Louis Lam 97df200d6c
Merge pull request #365 from Ponkhy/master 3 years ago
Louis Lam d5b17a3778
Merge pull request #367 from xinac721/master 3 years ago
新逸Cary 2f0d994c83 update Simplified Chinese language(更新简体中文语言) 3 years ago
新逸Cary e683033f4e
Merge pull request #2 from louislam/master 3 years ago
Ponkhy c3c576bd13 Added "Show URI" translation 3 years ago
Ponkhy c62732fa9c Minor translation fixes 3 years ago
Ponkhy d823493fad Added maxlengh to token verify input 3 years ago
Ponkhy 463c385cf1 Only show modal footer if uri was generated 3 years ago
Ponkhy 59cccf8c50 Fixed typo 3 years ago
Ponkhy 403202d4d4 Added simple TOTP Two Factor Authentication 3 years ago
Louis Lam 2583dbe0e0
Update README.md 3 years ago
LouisLam ca479673e7 avoid Chrome duplicate id warning 3 years ago
LouisLam 573c7faddd switch on the notification, if it is added in EditMonitor.vue 3 years ago
LouisLam 7a4432de1e better switch button color in dark mode 3 years ago
LouisLam 94a6c1a344 update language files 3 years ago
Louis Lam ee9e48fe53
Merge pull request #361 from iomataani/italian-translation-update 3 years ago
LouisLam a4aee49b03 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam e330875c80 fix restore fail if no isDefault 3 years ago
Paride Barison 44eba70b78 altri errorini sistemati 3 years ago
Paride Barison c6dab944d1 altra correzione 3 years ago
Ioma Taani 0f4bc5850b
Merge branch 'louislam:master' into italian-translation-update 3 years ago
Louis Lam f37190a73d
Update README.md 3 years ago
Louis Lam 29f96fae93
Update README.md 3 years ago
Louis Lam 331ae5ec20
Merge pull request #306 from Ponkhy/import-export 3 years ago
LouisLam 8ee34c7904 also handle the first beat problem in uptime 3 years ago
LouisLam 4f07c2ea9a uptime calculation fully sum in sql 3 years ago
LouisLam 0b1d0d22ff add indexes, improve queries 3 years ago
LouisLam 24facc79d7 sendHeartbeatList use raw data 3 years ago
LouisLam 9f9c1007d7 increase sqlite cache size from 2MB to 12MB 3 years ago
LouisLam 70a6f0313c update .dockerignore 3 years ago
LouisLam 1d05df6ec9 [docker healthcheck] use retries instead, longer start-period causes starting problem in Docker Swarm mode 3 years ago
Ioma Taani b54bbc302d migliorata la traduzione 3 years ago
LouisLam dd283423ab improve smtp with cc, bbc and ignore tls 3 years ago
LouisLam 6006038689 fix monitor.stop() in some cases 3 years ago
LouisLam a7b50c3630 Revert "add user-monitor-list" 3 years ago
LouisLam 0ddbac5109 Revert "move userMonitorList out of server.js" 3 years ago
LouisLam 0f440596c8 Revert "cache last heartbeat list in memory" 3 years ago
LouisLam 5a0fcebd6e update link style 3 years ago
LouisLam 87678ea92d cache last heartbeat list in memory 3 years ago
LouisLam 0bf0cfa104 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam a7cf14c663 move userMonitorList out of server.js 3 years ago
Louis Lam 325ce72a71
Merge pull request #352 from iomataani/italian-language 3 years ago
Louis Lam 9d00bd9029
Merge pull request #357 from Saibamen/nav_from_dashHome 3 years ago
Adam Stachowicz f6a168282e Route to monitor on `DashboardHome` 3 years ago
Ponkhy acf6f1883b Fixed missing spaces in backup file 3 years ago
Paride Barison f44f951e40 Tradotte le ultime cose come richiesto 3 years ago
Ioma Taani dea9b05d49
Merge branch 'louislam:master' into italian-language 3 years ago
LouisLam 230a9bfaf9 add user-monitor-list 3 years ago
Louis Lam d761d54d0e
Merge pull request #340 from Ponkhy/default-notification 3 years ago
LouisLam e37621853e Merge branch 'estonian' 3 years ago
LouisLam f2cec60481 minor 3 years ago
LouisLam 2212cf9c08 fix confirmDisableAuth no msg if not tranlated 3 years ago
LouisLam f7562e00c1 improve notification component, no double template 3 years ago
Ponkhy 678e248966 Added indicator while changing database records 3 years ago
Ponkhy c1aebef005 Fixed SQL error due notification setup 3 years ago
Ponkhy 1ef4562905 Paused monitors stay paused after import 3 years ago
Ponkhy 69a7c4dab4 Improved importBackup handling 3 years ago
jtagcat 2c3880a326 Added Estonian. 3 years ago
Ponkhy f4e885982d Added export/import description for de-DE 3 years ago
Ioma Taani dcf6dd8b32
Ultimi aggiustamenti 3 years ago
Ioma Taani 093cfec8dd
Typo. 3 years ago
Ioma Taani f13dcb3c5b
Update it-IT.js 3 years ago
LouisLam 1a5ffd4755 add description for export/import 3 years ago
Ioma Taani a2f9e9e9c4
Creata lingua italiana 3 years ago
LouisLam 62712f5cc4 Merge branch 'master' into import-export 3 years ago
LouisLam f0f1847ad8 update language files 3 years ago
LouisLam 0aeaf87f5b Merge branch 'master' into default-notification 3 years ago
LouisLam 5ca0dd628d remove debug msg 3 years ago
LouisLam 4a106431f3 convert Telegram into a vue components 3 years ago
LouisLam d164b6ccce prevent Chrome ask for saving password for notification settings (change to one-time-code to solve it) 3 years ago
LouisLam da74391c3e convert notifications into modules 3 years ago
Louis Lam 850563442a
Merge pull request #349 from Ponkhy/redirect-after-setup 3 years ago
Ponkhy 242e494cb5
Merge branch 'master' into import-export 3 years ago
Ponkhy 4faa409027
Merge branch 'master' into default-notification 3 years ago
Louis Lam f842fb409e
Update README.md 3 years ago
Louis Lam 72dd894856
Update README.md 3 years ago
LouisLam 0b0417e064 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam fe35d95441 merge language files 3 years ago
LouisLam da131a5156 Merge branch 'master' into clear-monitor-data 3 years ago
Louis Lam 926c15ea40
Update healthcheck.js 3 years ago
LouisLam 87e874406a Merge branch 'Ponkhy_master_hidden' 3 years ago
LouisLam 0e288ea92d disable chrome save password dialog for autocompelete = off only 3 years ago
LouisLam 8a4a87716f disable chrome save password dialog 3 years ago
Ponkhy d01fa9bcfc Auto login after setup 3 years ago
LouisLam ec8c1cad31 update healthcheck.js for changing ssl cert / hostname / port 3 years ago
LouisLam fb0fa2a843 add sqlite cli to docker 3 years ago
LouisLam f5c6d422d5 switch debian to be the main docker base 3 years ago
Louis Lam ea4240455f
Merge pull request #347 from gaby/refactor-docker 3 years ago
Juan Calderon-Perez ce30ee74e9
Revert changes breaking ARM releases 3 years ago
Juan Calderon-Perez 66b5f157eb
Update Dockerfile order to improve layer caching. 3 years ago
Juan Calderon-Perez 5fe8a0917a
Refactor Debian Dockerfile 3 years ago
Ponkhy 848296b77a Changed input for sensitive data to HiddenInput 3 years ago
Ponkhy edfaacbb5f Added component HiddenInput.vue 3 years ago
Ponkhy bb8385d690 Merge branch 'default-notification' of https://github.com/Ponkhy/uptime-kuma into default-notification 3 years ago
Ponkhy b95404b6e0 Fixed suggestions 3 years ago
Louis Lam cc351b2883
Merge pull request #339 from Minvinea/master 3 years ago
Louis Lam 3c06f249ca
Merge pull request #338 from Saibamen/pl_fixes 3 years ago
Minvinea 31648dc5e8
Update #2 3 years ago
Minvinea 1197cfa11e
Update file name 3 years ago
Ponkhy fd8c95d64e
Merge branch 'master' into default-notification 3 years ago
Ponkhy 58240aceef Added the option for default notifications 3 years ago
Adam Stachowicz e8b814733d Fix typo 3 years ago
Minvinea dcc7799108
Update few words and name of file 3 years ago
Adam Stachowicz 424f20f8e1 Better `upsideDownModeDescription` 3 years ago
Adam Stachowicz d4ff5d8b32 [LANG] `pl` fixes 3 years ago
LouisLam 899b33b3a9 add language missing keys 3 years ago
Ponkhy 1b8b33c4c3 Added set language to the Setup.vue 3 years ago
Louis Lam d34ed00841
Merge pull request #333 from Misly16/master 3 years ago
Louis Lam f9c177b150
Merge pull request #315 from tgxn/patch-1 3 years ago
Misly 9952463350 Add Polish Locale 3 years ago
LouisLam 5837c353b7 change the default theme to auto from light 3 years ago
LouisLam d5b32ffbb8 add language missing keys 3 years ago
LouisLam 61936ae5eb Merge remote-tracking branch 'Ponkhy/clear-monitor-data' into clear-monitor-data 3 years ago
LouisLam 299506ce45 reset the heartbeat list instead of reload the page after cleared events or heartbeats 3 years ago
LouisLam ca8d4ab61b Merge branch 'master' into clear-monitor-data 3 years ago
LouisLam ffbdf97478 improve heartbeat bar rendering in different dpi 3 years ago
LouisLam cc25787878 improve heartbeat bar rendering in different dpi 3 years ago
Louis Lam 17453a8812
Merge pull request #332 from LeviSnoot/master 3 years ago
Levi f1a151b4a1
Update & Improve Swedish Translation 3 years ago
Levi d35b205fcc
Update & Improve Swedish Translation 3 years ago
Levi 2a34e41d8c
Improved Swedish translation 3 years ago
Domenic Horner 41d32bb9dd Undo parm changes 3 years ago
Ponkhy 0b9e410ea5 Added i18n key to en.js 3 years ago
Ponkhy 904ed326ca
Merge branch 'louislam:master' into clear-monitor-data 3 years ago
LouisLam 778995a4fb add dockerfile-debian 3 years ago
LouisLam ee60d74910 fix dockerfile path 3 years ago
LouisLam 6a603203cc update to 1.5.3 3 years ago
LouisLam 4b8e7fcffc update "build-docker" to build both platforms 3 years ago
LouisLam 7fd12f5485 rename nl_NL.js to nl-NL.js 3 years ago
LouisLam 0d87a6dfea update vue to 3.2.8 3 years ago
Domenic Horner b0acda52f9 Add time to smtp body content 3 years ago
Domenic Horner e9cd9be03a Use constants for UP/DOWN through notifications class 3 years ago
Domenic Horner 6ae279c7f3 Move title generation to notification class 3 years ago
Domenic Horner 9c32adfb55
Update pushbullet down body 3 years ago
Domenic Horner d346afd33b
Update pushbullet up body 3 years ago
Domenic Horner 3bf380c684
Update lunasea "up" body content 3 years ago
Domenic Horner dca5c59982
Update lunasea body content 3 years ago
Ponkhy 8f9a973ede
Merge branch 'master' into import-export 3 years ago
Ponkhy b98ec0c3d4 Added i18n keys if necessary for some languages 3 years ago
Louis Lam 2082c3f68a
Merge pull request #313 from xoniq/lang-nl 3 years ago
Louis Lam ea9f434553
Merge pull request #328 from Ponkhy/german-language 3 years ago
Louis Lam fa1216c198
Merge pull request #329 from dhfhfk/New-string 3 years ago
dhfhfk 6d8aa20fc6
Add missing string for Korean 3 years ago
Ponkhy 5430da955a Small german language adjustments 3 years ago
J Posthuma e6e2b0ebf8
Update nl_NL.js 3 years ago
J Posthuma 445dc486be
Merge branch 'master' into lang-nl 3 years ago
Louis Lam d2151737c1
Update README.md 3 years ago
Louis Lam 78fc6de542
Merge pull request #325 from Saibamen/patch-1 3 years ago
Adam Stachowicz c15e6631ae
Update README.md 3 years ago
LouisLam ebf362754c Merge branch 'master' into clear-monitor-data 3 years ago
Louis Lam f84135ca67
Merge pull request #322 from chakflying/patch-6 3 years ago
LouisLam 80eca886ce Merge branch 'add-serbian-latin' 3 years ago
Louis Lam 274a9050c0
Merge pull request #321 from dusansimic/add-serbian-cyrillic 3 years ago
Louis Lam 1f4ad938b1
Merge pull request #323 from xinac721/master 3 years ago
新逸Cary 312aedf391 Update Chinese Translation(更新简体中文语言翻译) 3 years ago
Louis Lam 4f28bfbde3
Merge pull request #309 from Saibamen/updateDependencies 3 years ago
Louis Lam ee76ab4ec2
Merge pull request #317 from AtaxyaNetwork/master 3 years ago
Nelson Chan 18616ee590
Fix: Fix Notification "Test" btn styling 3 years ago
Dušan Simić 19a4d570ec Fix word capitalization 3 years ago
Dušan Simić 79fda8f442 Add Serbian Latin locale 3 years ago
Dušan Simić 53a14cf4f5 Add Serbian Cyrilic locale 3 years ago
cecile 2241d8817f change translation FR 3 years ago
Louis Lam 3831dfe0b9
Update README.md 3 years ago
Louis Lam fdde862549
Merge pull request #316 from aictur/feature/es-ES 3 years ago
LouisLam e31be8caf5 demo mode 3 years ago
LouisLam 60f2f08cea add demo db 3 years ago
LouisLam b1647a310e add demo db 3 years ago
Victor M. Vicente Cuevas 23f1a73fc8 Add language to src/main and update README 3 years ago
Victor M. Vicente Cuevas d2bf2a551d Add spanish language and update Readme 3 years ago
Ponkhy 7d70c4d8cd Code optimizations 3 years ago
Domenic Horner 532ad3044c
Add space to pushbullet and lunasea notifications 3 years ago
LouisLam f23ecef636 add missing cert parameters 3 years ago
LouisLam 51cf2ff6f9 add missing cert parameters 3 years ago
LouisLam b30b1d3a52 create data dir before copy 3 years ago
LouisLam 582e14098d create data dir before copy 3 years ago
LouisLam 6e3e2fc85c fix db path 3 years ago
LouisLam b604807cfe create data dir if not exists 3 years ago
LouisLam 3ee13bddd1 dash style for args 3 years ago
LouisLam c74986647e allow changing data dir 3 years ago
LouisLam dac410c850 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam b88b357b55 add support for https 3 years ago
Louis Lam 9a5cd5172b
Merge pull request #314 from xinac721/master 3 years ago
新逸Cary 941788db49 Chinese Translation (from zh-CN.js) 3 years ago
Jelle Posthuma 99725aabe7 Add Dutch/Nederlands language (nl_NL) 3 years ago
Ponkhy 2dd392e609 Added uptime kuma version to backup file 3 years ago
Louis Lam 9d41da4aa2
Merge pull request #311 from xinac721/master 3 years ago
新逸Cary a0f372e946 Chinese Translation (from zh-CN.js) 3 years ago
新逸Cary 877ad1438f
Merge branch 'louislam:master' into master 3 years ago
LouisLam 9116654a33 update language files and run eslint on these 3 years ago
新逸Cary dbc70bc5ed
Merge pull request #1 from louislam/master 3 years ago
Louis Lam a29b65e801
Merge pull request #308 from DX37/translation-ru 3 years ago
Louis Lam bd9568ce5b
Merge pull request #310 from Saibamen/more_i18n 3 years ago
Ponkhy c13cc62d3d
Update server/server.js 3 years ago
Adam Stachowicz 7a109689d9 Make `Resp. Time (ms)` and `N/A` i18n 3 years ago
Adam Stachowicz e7929f461d Update dependencies 3 years ago
DX37 a2cf7f394e
Add Russian translation 3 years ago
Louis Lam e1f378ee6c
Update README.md 3 years ago
LouisLam eeb00a5511 fix data type 3 years ago
LouisLam 8e1e4b9204 override file-selector-button hover color 3 years ago
LouisLam 66f9ad5754 Merge branch 'master' into import-export 3 years ago
Louis Lam 129dc3324b
Merge pull request #307 from dhfhfk/master 3 years ago
Louis Lam 268d2e2353
Merge branch 'master' into master 3 years ago
Louis Lam 7d2cf0ee57
Merge pull request #304 from LeviSnoot/master 3 years ago
오로라 2d408732db
Update main.js 3 years ago
dhfhfk 0cc5053f14
Update ko-KR.js 3 years ago
dhfhfk 1c4e5b79be
Create ko-KR.js 3 years ago
dhfhfk 4aae402b36
Update main.js 3 years ago
Ponkhy b604910bbb
Merge branch 'master' into clear-monitor-data 3 years ago
Ponkhy 2f6c5963c5 Added import and export function 3 years ago
Levi dce2ba8f9f
Update sv-SE.js 3 years ago
Levi ed5c75282c
Update main.js 3 years ago
Levi 00ac560bd6
Create sv-SE.js 3 years ago
Louis Lam 8ea4dec5a0
Merge pull request #303 from Saibamen/patch-1 3 years ago
Adam Stachowicz 3006d13aee
Update translation docs 3 years ago
LouisLam c7e6cb9f37 update language files 3 years ago
LouisLam 9b82bb248e Merge branch 'master' into kometchtech_patch-1 3 years ago
Louis Lam e55cf65f28
Merge pull request #291 from Ponkhy/master 3 years ago
Louis Lam f24002838c
Merge branch 'master' into master 3 years ago
Louis Lam b4fd4f7d90
Merge pull request #301 from Lrss/master 3 years ago
kometchtech 3a3f1762ac
Update ja.js 3 years ago
Lars Sørensen 6376d4eb92
Translated to Danish 3 years ago
LouisLam e37cf9b1a7 add missing and add Japanese to the list 3 years ago
LouisLam 3b0191210b Merge branch 'master' into kometchtech_patch-1 3 years ago
LouisLam 923d325b44 add language file preparation script 3 years ago
LouisLam ad38e61c26 add language file preparation script 3 years ago
LouisLam 22095c09b1 add translation guide 3 years ago
LouisLam a5e62141d5 update to 1.5.2 3 years ago
LouisLam e4b76717be revert back to node-sqlite3 3 years ago
LouisLam bc70ecfba7 fix install script 3 years ago
LouisLam f1238ab762 update to 1.5.1 3 years ago
LouisLam cd1a3a2fb9 revert back to node-sqlite3, as better-sqlite3 causes a lot of installation problems 3 years ago
kometchtech 25db162721
Create ja.js 3 years ago
Ponkhy 7b92166d18 Added clear all db statistics function 3 years ago
Ponkhy 1341d220ed
Merge branch 'louislam:master' into clear-monitor-data 3 years ago
LouisLam 3e7bb355fd update to 1.5.0 3 years ago
LouisLam 697fa6bdfd fix discord notification appended port unexpectedly 3 years ago
LouisLam 527e0c3444 raise the ping timeout from 2s to 10s (avoid #294) 3 years ago
LouisLam a41534ca60 no declare vars with comma, one line only one statement 3 years ago
LouisLam fa549cb80e fix npm7 broken dependencies 3 years ago
LouisLam 0127d5102e Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam ec731d174d Merge branch 'MichelBaie_master' 3 years ago
LouisLam 0d65918a6a change bcrypt to bcryptjs, use my own prebuilt better-sqlite3, supports more prebuilt 3 years ago
Louis Lam 21db31bb30
Update README.md 3 years ago
Louis Lam 3ee0addb1f
Merge pull request #281 from MichelBaie/master 3 years ago
LouisLam 8c5d1945be add fr to the list 3 years ago
Tristan bb799163e8
French Translation (from zh-HK.js) 3 years ago
LouisLam bf29f28726 send stats only if there is at least one client in the room 3 years ago
LouisLam 22db9c9b8a Merge remote-tracking branch 'origin/master' into scroll-into-view 3 years ago
LouisLam 96ff70faaa reduce shifting when click the monitor list item (still shift in some cases, but acceptable) 3 years ago
henrygd 2776f942ab fix monitor list jumping to top on route change 3 years ago
Ponkhy 14b9afb400 Added translation to Setup.vue 3 years ago
LouisLam 3ad736692f improve monitor list 3 years ago
Ponkhy 1952e34110 Added the possibility to clear monitor data 3 years ago
LouisLam e644a1e36f Merge branch 'master' into scroll-into-view 3 years ago
Louis Lam 78b7e36a38
Update domain name 3 years ago
Louis Lam f30232c35d Create CNAME 3 years ago
Louis Lam 257a4ee994
Update patch7.sql 3 years ago
Louis Lam fd1ba46d3d
Merge pull request #287 from Ponkhy/dns-monitor 3 years ago
LouisLam ada6606217 move the new sql to patch8.sql 3 years ago
Ponkhy dd877cfc70 Added translation to pause monitor confirmation 3 years ago
Ponkhy 93edb8817d More uniform look 3 years ago
Ponkhy 858affa808 Removed useless database query 3 years ago
Louis Lam 2bb182b2b4
Create FUNDING.yml 3 years ago
Ponkhy 303adbf9b1 Show latest dns result in Details.vue 3 years ago
Louis Lam 712da02324
Merge pull request #286 from arnishb/fix-readme 3 years ago
Arnish Baruah 27a4dbb722
fix-readme 3 years ago
Louis Lam 0e676060f2
Update CONTRIBUTING.md 3 years ago
Louis Lam a14c40f9bb
move k8s to advanced installation section 3 years ago
Louis Lam 309fbfa094
Update README.md 3 years ago
Louis Lam 46dcd31142
Update README.md 3 years ago
LouisLam 59e9315647 show dns type and hostname in Details.vue 3 years ago
LouisLam 91e82bd12c set default value for dns resolve type and code refactor 3 years ago
LouisLam d4dd650bfe translate for zh-hk 3 years ago
Louis Lam 354ee1a58c
Merge pull request #283 from Ponkhy/german-language 3 years ago
henrygd 2901a38628 add position: sticky to monitor details 3 years ago
Ponkhy 6464207f4b Added German language for DNS Monitor 3 years ago
Louis Lam 7652b4849a
Merge pull request #238 from Ponkhy/dns-monitor 3 years ago
LouisLam 03b4086372 add CAA test and remove some files added by mistake 3 years ago
Ponkhy acd5cf63fd Removed wrong PTR answer 3 years ago
Ponkhy 177af2d588 Added more dns types to simple-dns-server 3 years ago
Tristan b46b214175
Traduction pour le language France (FR Translation) 3 years ago
Louis Lam d2f0a15076
Merge pull request #264 from antiseptikk/master 3 years ago
LouisLam 2d50d24276 more translation for zh-HK 3 years ago
Louis Lam 34b6976a03
Merge pull request #269 from Ponkhy/german-language 3 years ago
Louis Lam d60c11e845
Merge pull request #260 from Thiesjoo/discord-notification 3 years ago
LouisLam 890aea8756 Merge branch 'duzun_patch-1' 3 years ago
LouisLam c55f2b93f7 change to pm2 start server/server.js directly due to (#273) 3 years ago
Louis Lam d4cf838af7
Merge pull request #273 from duzun/patch-1 3 years ago
LouisLam 508586fcfd add codesandbox config for demo 3 years ago
Dumitru Uzun feb0feda76
Dockerfile: Avoid keeping npm in RAM 3 years ago
Ponkhy 34ca5c5c15 Merge branch 'master' of https://github.com/louislam/uptime-kuma 3 years ago
Ponkhy 2b8c5e2e65 Added German Language 3 years ago
Thomas Ferney 44d9967cfb
feat: add rocket.chat notification 3 years ago
LouisLam 8318c2e8ff add a simple dns server for testing, and disable ipRegex for dev only (need to input port) 3 years ago
LouisLam 46ac753c46 Merge branch 'master' into dns-monitor 3 years ago
Thies 72740ba477
Update the styling to better match existing styles 3 years ago
Thies Nieborg 5d438ca2b6
Discord notification URL now also represents non http services 3 years ago
Ponkhy 02a12e68b8 Used ALTER TABLE instead of rebuilding the table 3 years ago
Louis Lam a7cd70f7de
Merge pull request #253 from chakflying/chart-fix 3 years ago
Louis Lam 26db0471da
Merge pull request #254 from RasHas/master 3 years ago
Ponkhy d313a06d5c Optimizations for output handling 3 years ago
LouisLam 4c1f2f85f8 manual fix stylelint 3 years ago
Rashad 23851ef539 added mattermost notification support 3 years ago
LouisLam 397fd12081 remove unused import 3 years ago
LouisLam 564bc96735 eslint: camelcase rule do not check properties, because it could be database field name 3 years ago
LouisLam 682e4d45e2 eslint for notification.js 3 years ago
LouisLam f96d792fa1 fix patch database using better-sqlite3 3 years ago
Nelson Chan 2d20634738 Chore: Add comments, improve performance & styling 3 years ago
Nelson Chan 9442c3fa05 Fix: Fix chart bars to be full width 3 years ago
LouisLam 302d2665d2 run stylelint for the project 3 years ago
LouisLam 2b68be52b0 Merge branch 'clean-mobile-table' 3 years ago
LouisLam 393c4fb1a7 update stylelint 3 years ago
Louis Lam 13f6c79e79
Merge pull request #236 from Ponkhy/clean-mobile-table 3 years ago
LouisLam ca69d06e0d update border color 3 years ago
LouisLam d8d428907e Merge branch 'master' into clean-mobile-table 3 years ago
Ponkhy a17c14ea1c Centered title, badge and datetime 3 years ago
LouisLam 28a51d806b translate to Traditional Chinese (Hong Kong) 3 years ago
Ponkhy 6eead46fa6 Merge branch 'dns-monitor' of https://github.com/Ponkhy/uptime-kuma into dns-monitor 3 years ago
Ponkhy 44d9fa63f0 Adjusted the output for A and AAAA records 3 years ago
LouisLam dd4c00eed3 add vue i18n 3 years ago
LouisLam 752ac05149 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 14652c9b5f Remove unused variables 3 years ago
Louis Lam 054186370e
add source of ipRegex 3 years ago
Louis Lam 40d80dfdfd
clarify pull request rule 3 years ago
Louis Lam b9684e32d3
Update CONTRIBUTING.md 3 years ago
LouisLam 8e726da82a eslint: add camelcase rule 3 years ago
Louis Lam df41c40cc2
add mit license badge in readme 3 years ago
Ponkhy 5dc834794c Row spacing reduced and badge centered 3 years ago
LouisLam 36ace3e56c naming convention and wrap all styles inside .table-shadow-box to avoid unexpected style in the future 3 years ago
LouisLam 3f12afce28 Merge branch 'master' into clean-mobile-table 3 years ago
Louis Lam 833b4733a8
Merge pull request #246 from chakflying/patch-4 3 years ago
Nelson Chan 066b67dfce
Proj: Add lint commands 3 years ago
Ponkhy b2041cb36b Fixed ESLint Errors 3 years ago
LouisLam aa2233eb2d log notification error 3 years ago
Ponkhy e5981b10ce Replaced var with let and removed re-declaration 3 years ago
LouisLam 46cb955172 afterLogin change to non blocking 3 years ago
LouisLam 50f300dd28 heartbeat interval change to use setTimeout() 3 years ago
LouisLam 2f50fc4c00 plan to switch to better-sqlite3, drop node-sqlite3 3 years ago
LouisLam a02edf1b4f fix detail page empty if the monitor list is not yet ready 3 years ago
LouisLam a61a65e5ae Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam ffaaeae794
Merge pull request #239 from chakflying/fix-ts 3 years ago
Nelson Chan ee3bf2961c Fix: fix typescript errors 3 years ago
Ponkhy ce79f8bfc7 CSS optimizations 3 years ago
Ponkhy c79be19ec3 Added DNS Monitor Type 3 years ago
LouisLam b892a92fc8 retry if acquire error 3 years ago
Louis Lam 2912ca1248
Merge pull request #237 from Ponkhy/master 3 years ago
LouisLam 2bff1ebe0f update to 1.3.2 3 years ago
LouisLam ec0dbf3cbe probably still memory leak over time, not sure what happen, change back to singal pool. 3 years ago
LouisLam 210a0d414c fix check update interval too short 3 years ago
Ponkhy ca38cc91e9 Use bootstrap integraded class instead of new ones 3 years ago
Ponkhy c90d17bd66 Added animation for list page change 3 years ago
Ponkhy dbd3f48f68 Added clean monitor table for smaller screens 3 years ago
LouisLam 49ba5fb1b2 update to 1.3.1 3 years ago
LouisLam d27789a8ae Revert "update to 1.3.1" 3 years ago
LouisLam b53582a812 update to 1.3.1 3 years ago
LouisLam 05680472a7 fix high memory usage 3 years ago
LouisLam ca3b0a0f19 fix setInterval 3 years ago
LouisLam 4571a9b8c1 check update 3 years ago
LouisLam 362eabab8d allow empty block for catch 3 years ago
Louis Lam a22d0f6951
Merge pull request #231 from ClemontX/master 3 years ago
LouisLam b1168d4cdb update to 1.3.0 3 years ago
Carl Sander 6fcc2253ec changed domain names to example.com 3 years ago
LouisLam f21937b197 add animation for page change 3 years ago
Louis Lam 1e7623c459
Update README.md 3 years ago
Carl Sander 22047fe932 removed doubled names of ressources 3 years ago
LouisLam 209e44c2e1 prevent all monitors making requests at the same moment when start the server 3 years ago
LouisLam 30b8d3d0ab prevent all monitors making requests at the same moment when start the server 3 years ago
LouisLam 64498163e1 add /list for mobile 3 years ago
LouisLam 4f70a70dda splite the left monitor list into a component 3 years ago
Carl Sander 5b5a32967c fixed README 3 years ago
Carl Sander ae8b5eea5a
Merge branch 'master' into master 3 years ago
LouisLam b761aaffdf Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 7ffdb2eb80 also backup sqlite shm, val file 3 years ago
Louis Lam 2d36f4cd4a
Create SECURITY.md 3 years ago
Louis Lam 2339405f90
Update README.md 3 years ago
LouisLam 8f5e5ad944 install.sh - check docker is running 3 years ago
LouisLam 575c3ee182 install.sh - check docker is running 3 years ago
LouisLam c9aa110f6c install.sh - check docker is running 3 years ago
LouisLam bb0af35d47 wip: implementing install script 3 years ago
LouisLam 61944d642e wip: implementing install script 3 years ago
Carl Dominik Sander 21640e1bbe changed to tag 1 3 years ago
Louis Lam de4515ea6e
Merge pull request #230 from chakflying/patch-3 3 years ago
Carl Dominik Sander b41799f801 reolved suggestions from @srgvg and @louislam 3 years ago
Nelson Chan d8bcfcaaa2 Fix: Reduce chart padding on mobile 3 years ago
Nelson Chan cf5168a4e6 Fix: Resize chart on screen breakpoints 3 years ago
Carl Sander 60b0ee2959 added K8s-Deployment and edited README 3 years ago
LouisLam f1e5e53e8f Merge branch 'patch-2' 3 years ago
LouisLam 432388a905 Merge branch 'Ponkhy_master' 3 years ago
LouisLam 746c1b6acc Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 269ac2410b install.sh add supports for CentOS 3 years ago
Nelson Chan f72cdcc663
Feat: Add time to beat tooltip, misc. fixes 3 years ago
Louis Lam 6b3fbcd1e7
Merge pull request #228 from Ismaaa/patch-1 3 years ago
Ismail D 8a48f5dd71
Fix typo in README.md 3 years ago
LouisLam d218661f3d wip: implementing install script 3 years ago
Ponkhy 77369bd002 Fixed invisible heartbeat bar after page switch 3 years ago
Louis Lam 29a89df524
Merge pull request #227 from Ponkhy/line-messenger 3 years ago
Louis Lam e257fa7b2d
Merge pull request #221 from chakflying/patch-1 3 years ago
LouisLam 6980c38a6c fix #226 a workaround fix similar to https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 3 years ago
LouisLam 8d57df7256 fix #226 a workaround fix similar to https://github.com/jvandemo/generator-angular2-library/issues/221#issuecomment-355945207 3 years ago
Ponkhy 64501bf065 Added Line Messenger Notification Service 3 years ago
LouisLam 440c178403 change sqlite to WAL mode 3 years ago
LouisLam c9c51e47e1 add some comments 3 years ago
LouisLam 5e52f230b1 create datetime mixin 3 years ago
LouisLam 61e758d872 disable pool for sqlite, re-use a connection to improve the performance. 3 years ago
LouisLam 86826fb826 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 7a32e5e6ff catch rejection error globally 3 years ago
Louis Lam 610f2f9c47
Merge pull request #225 from AverageHumanoid/master 3 years ago
AverageHumanoid 01e9c76a6f
Use ping in FreeBSD 3 years ago
Ponkhy 5927c2703f
Merge branch 'louislam:master' into master 3 years ago
LouisLam 316db89b9a Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam eed6d3e847 add more query log for dev env 3 years ago
Louis Lam 2a62f6daae
Update ask-for-help.md 3 years ago
Louis Lam e09c296410
Update bug_report.md 3 years ago
Louis Lam d7f660ec57
Update bug_report.md 3 years ago
LouisLam 798f39acf0 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 31d5b4fd3d do not pass smtp user/pass to nodemailer if both are empty 3 years ago
LouisLam fc76c2836b increase the query timeout 3 years ago
Nelson Chan 0b30bfff87
Fix: Improve Chart axis, use 24Hr format 3 years ago
Ponkhy 72f0724b9a
Update src/mixins/theme.js 3 years ago
Ponkhy 35176a614f
Update src/mixins/theme.js 3 years ago
Ponkhy 8e883c9c6a
Update src/mixins/theme.js 3 years ago
Louis Lam 2f89ee4937
Update README.md 3 years ago
LouisLam 5d0b6190c3 update to 1.2.0 3 years ago
LouisLam cb85905c33 minor 3 years ago
Ponkhy 233c5661af Added user choice heartbeat bar 3 years ago
Ponkhy 91d4c15b4d
Merge branch 'louislam:master' into master 3 years ago
LouisLam 981ed5f29f Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 0b45694f2f update all dependencies 3 years ago
Louis Lam 60531d0b15
Update README.md 3 years ago
Louis Lam a3de63ac3c
Update README.md 3 years ago
Louis Lam 80eadcb236
Merge pull request #214 from ChrisTheBaron/pushbullet 3 years ago
LouisLam 7e5a8c896b Merge remote-tracking branch 'chakflying/ping-graph' 3 years ago
Chris Taylor efe75bde75 Add Pushbullet notification service 3 years ago
Louis Lam af34e861c5
Merge pull request #200 from proffalken/feature/187_add_cert_checks_to_prometheus 3 years ago
Louis Lam 2ae2022e62
Merge pull request #211 from AlexandreGagner/master 3 years ago
LouisLam 37f1d60f82 also change meta tag theme-color 3 years ago
LouisLam d39b43dacc fix require problem 3 years ago
Louis Lam 7ca80fc086
fix auto theme 3 years ago
Alexandre Gagner eb34dc6cc2 Update notification.js 3 years ago
Alexandre Gagner ed93aae1c2 add octopush notification service 3 years ago
Ponkhy e1a38f64f8
Merge branch 'louislam:master' into master 3 years ago
LouisLam 6a8ccf627a add version to user agent 3 years ago
Nelson Chan 8f150aaeb9 Feat: Use Async Component 3 years ago
Nelson Chan 6ed1d8cb2f Feat: Use selective import, improve tooltip UI 3 years ago
Nelson Chan 71bec74081 Feat: Add down-ed bars, improve UI 3 years ago
Nelson Chan 2bd735035c Misc: Show graph by default 3 years ago
Nelson Chan 48c6d8f19f Feat: Display recent ping chart 3 years ago
LouisLam 2d176a38af Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam b14f63491d timeout change to 80% of its interval 3 years ago
LouisLam 24b87fcd5a update vue to 3.2.1 3 years ago
Ponkhy 45c162583b Added more space over the badge on mobile screens 3 years ago
LouisLam 365ea0a189 add batsh 3 years ago
Louis Lam 2461f5084e
Merge pull request #205 from Ponkhy/master 3 years ago
Ponkhy 1d0b332b42 Fixed function buttons for smaller screens 3 years ago
LouisLam d5149f90b4 fix ping 3 years ago
LouisLam e0ae9a9e73 improve space-before-function-paren 3 years ago
LouisLam 3227a2660b log undefined ping 3 years ago
LouisLam 764160f38c add eslint: space-before-function-paren 3 years ago
LouisLam 70e7945a66 fix possible race condition 3 years ago
LouisLam b413427a37 graceful shutdown when listen error 3 years ago
LouisLam debcac4924 run eslint 3 years ago
Matthew Macdonald-Wallace 268dd33792 Add TLS Info to Prometheus metric output 3 years ago
LouisLam 692a11e51e pass tls info to prometheus.update 3 years ago
Matthew Macdonald-Wallace 5eb4f55dfd Add the new gauges to the prometheus handler 3 years ago
LouisLam e7cc5340e5 ping ipv6 for macos 3 years ago
LouisLam 4d4d504d6e retry ping domain with ipv6, if domain is not found 3 years ago
LouisLam 2a4695a774 add -6 to ping cmd if ipv6 address 3 years ago
LouisLam f089bf73c3 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam f099e4270d change to Accept: */* to better support all websites 3 years ago
Louis Lam 81636c7b44
Delete reviewdog.yml 3 years ago
Louis Lam 98fa995d3f
Update reviewdog.yml 3 years ago
Louis Lam 42d24258cf
Delete app.json 3 years ago
Louis Lam 3f56167198
Update reviewdog.yml 3 years ago
Louis Lam 5163e16482
Update reviewdog.yml 3 years ago
LouisLam d93f6e2716 server.listen bind to ipv6 too 3 years ago
LouisLam d6fad7f1ef server.listen bind to ipv6 too 3 years ago
LouisLam 5512b15162 add better token for github-pr-review for reviewdog 3 years ago
LouisLam 8979311653 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 4f058c5b47 do not fix height for h1 3 years ago
LouisLam 9ba1743900 split mobile mixin from socket mixin 3 years ago
Louis Lam 1e4f9c7e15
Update README.md 3 years ago
Louis Lam 974672f7c1
Delete deploy.template.yaml 3 years ago
Louis Lam 01ac6d54be
Merge pull request #199 from chakflying/patch-1 3 years ago
Nelson Chan 113899e278
Fix: unify styling of theme switch with UI 3 years ago
LouisLam d1d000bd74 remove red circle around the btn-close while focus 3 years ago
Louis Lam ef4677a640
Merge pull request #194 from Ponkhy/master 3 years ago
Ponkhy e39c46ff9b Fixed Close Button Color in Dark Mode 3 years ago
Louis Lam 0e46ce42d1
Update README.md 3 years ago
LouisLam efc9a254f4 update to 1.1.0 3 years ago
LouisLam 116d803592 minor 3 years ago
LouisLam ba1d271afa fix jwt error 3 years ago
LouisLam 12910b23ed cache more layers for docker build 3 years ago
LouisLam 550c9703a6 fix radio button not checked 3 years ago
LouisLam b69185ee9e control search engine visibility 3 years ago
LouisLam ddcfa558f7 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 478d2c4e8c add more favicon 3 years ago
Louis Lam 1352a0a162
Update bug_report.md 3 years ago
Louis Lam 7274b82143
Update ask-for-help.md 3 years ago
Louis Lam 69b1454cf5
Update feature_request.md 3 years ago
LouisLam 8f2a9fe883 chnage sqlite3 package in dockerfile 3 years ago
Louis Lam 1b8476417d
Update README.md 3 years ago
Louis Lam 2a65402ad8
fix update command 3 years ago
LouisLam 59ef1f13db set longer timeout for axios request 3 years ago
LouisLam bf33f97c9e code re-use and eslint 3 years ago
LouisLam d0aad3400c add reset password in cli 3 years ago
LouisLam 6f489e7e0f Accepted Status Codes / Max Redirects for http/keyword only 3 years ago
LouisLam f9cb8293f3 improve a bit ux 3 years ago
LouisLam 11b8c61079 wip: add search engine control in setting 3 years ago
Louis Lam f69ba12c10
update reviewdog, add vue,ts ext 3 years ago
Louis Lam e78cfaa492
Merge pull request #189 from Saibamen/save_maxredirects 3 years ago
Adam Stachowicz 9c17f59fe8 Fix few markdown lint warnings 3 years ago
Adam Stachowicz 519add4fab ESLint `vite.config.js` 3 years ago
Adam Stachowicz 46c7e5d058 Save `maxredirects` on edit 3 years ago
LouisLam 6291b7b8bb update reviewdog 3 years ago
LouisLam 3fb515e871 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 8e440f7dff add a bot for eslint on github 3 years ago
Louis Lam 6d58c98b24
Update README.md 3 years ago
LouisLam 6ca7ca4e7e improve alignment and font size 3 years ago
Louis Lam 44391117ab
Merge pull request #173 from chakflying/redirects&status 3 years ago
LouisLam 9fa8d5c1fa improve multiselect 3 years ago
LouisLam 3265c3cbc3 improve multiselect 3 years ago
Louis Lam b3721e03a8
Merge pull request #186 from chakflying/patch-3 3 years ago
Nelson Chan 4ff68238c4
Chore: Improve logging during db development 3 years ago
LouisLam 7b1000d995 Merge remote-tracking branch 'chakflying/redirects&status' into redirects&status 3 years ago
LouisLam a79e6aa338 dark theme for multiselect 3 years ago
LouisLam 3005585c0f Merge branch 'master' into redirects&status 3 years ago
Philipp Dormann 123fca43a1
FEAT: darkmode (#155) 3 years ago
LouisLam d5b40dfebf better code reuse and "Username" to "Bot Display Name" 3 years ago
LouisLam c990edc87d allowElseIf for else return, since its auto fix removes "else" but without newline 3 years ago
LouisLam 2677f5dd87 run eslint for discord enhancement 3 years ago
Niyas 4469b3a19b
Added discord username field 3 years ago
Niyas ebf207c2f5
Custom embed username 3 years ago
Nelson Chan a50aa93e84 Fix: Fix monitor creation json parsing 3 years ago
Niyas 91fce75a93
Removed UptimeKuma url field 3 years ago
Niyas 3a7414125a
Updated discord embeds 3 years ago
LouisLam 5a6e5b7948 change multiselect color 3 years ago
LouisLam adcd251076 Merge branch 'master' into redirects&status 3 years ago
LouisLam dadc270876 Merge branch 'master' into discord-enhancements 3 years ago
LouisLam a98ba41c8e minor 3 years ago
LouisLam a40816b948 fix high severity vulnerabilities by using my fork sqlite3 package 3 years ago
LouisLam d3e24df225 fix high severity vulnerabilities by using my fork sqlite3 package 3 years ago
Niyas 908176c910
Discord enhancements 3 years ago
Niyas 9ade9af1e2
Discord enhancements 3 years ago
LouisLam 8350bff629 update dependencies 3 years ago
Nelson Chan 93ea2c277a
Update src/pages/EditMonitor.vue 3 years ago
LouisLam 6251f47050 fix the min height of monitor list 3 years ago
Nelson Chan 8f7885e58a Feat: Implement MaxRedirects & StatusCodes 3 years ago
LouisLam dffe3cf8f2 Revert "try to support subdirectory reverse proxy" 3 years ago
LouisLam d411143f3c Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam a03dd91e40 try to support subdirectory reverse proxy 3 years ago
Louis Lam 2c2ac9dc59
Delete dependabot.yml 3 years ago
Louis Lam d06711a1a7
Update README.md 3 years ago
Louis Lam 94f2219715
Create dependabot.yml 3 years ago
LouisLam d315e8306b update to 1.0.10 3 years ago
LouisLam 8cd0e7a058 a better script for version update 3 years ago
LouisLam 8fce62632d a better script for version update 3 years ago
LouisLam 38c0c170e7 add some comments 3 years ago
Nelson Chan 655536e457
Fix: use send() instead of end() (#161) 3 years ago
LouisLam 807db8a2d8 update to 1.0.9 3 years ago
LouisLam d707eba046 fix disable auth 3 years ago
Philipp Dormann e34a8e2e4a
FEAT: PUSHY Notifier (#154) 3 years ago
Louis Lam 6bd9d85a9a
Merge pull request #150 from chakflying/created_date 3 years ago
LouisLam f2de6299f6 update .dockerignore 3 years ago
LouisLam a28d6eafae remove apprise --version from dockerfile 3 years ago
LouisLam fce0edebc9 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 48a4ced9a5 update to 1.0.8 3 years ago
Nelson Chan 221aad55de Chore: Add new line at EOF 3 years ago
Nelson Chan 377d475e05 Fix: Add now columns 3 years ago
Nelson Chan 0c3c59df4e Fix: [DB] Add default for created_date in monitor 3 years ago
Louis Lam eba996b0f2
Delete codeql-analysis.yml 3 years ago
LouisLam 4d71e03039 improve #39 3 years ago
LouisLam 2740f096c0 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 8ebaca4c5c improve disableAuth handling 3 years ago
Louis Lam fceb594442
Merge pull request #145 from chakflying/patch-3 3 years ago
Nelson Chan 5b9d3357aa
Fix: Increase width of status pill 3 years ago
LouisLam 5689b30985 Merge remote-tracking branch 'origin/master' 3 years ago
LouisLam 44c8ca9da8 requires empty username/password if set disableAuth for basic auth 3 years ago
Louis Lam 6f044de6e6
Update README.md 3 years ago
Louis Lam 7877adf7a3
Merge pull request #137 from louislam/add-code-of-conduct-1 3 years ago
Louis Lam f0e5e9f463
Create CODE_OF_CONDUCT.md 3 years ago
Louis Lam 0263cfa7e4
Create CONTRIBUTING.md 3 years ago
Louis Lam 8b733592cb
Update README.md 3 years ago
Louis Lam 71fa55c218
Update README.md 3 years ago
Louis Lam ee071e41f5
Update README.md 3 years ago
LouisLam 6f868c9ec3 implement no auth 3 years ago
LouisLam 33d7f8645a json format for setting value 3 years ago
LouisLam c6a66fad79 add setting for disable auth 3 years ago
LouisLam 9f0be5f531 improve the connection error msg 3 years ago
LouisLam 7f42888546 fix eslint for vue (https://github.com/louislam/uptime-kuma/pull/121#issuecomment-889729900) 3 years ago
LouisLam 642a711bcd Confirm Dialog: allow changing the button text 3 years ago
LouisLam 659d83b13c turn off vue/html-self-closing, empty div should be allowed 3 years ago
LouisLam 4b93900866 fix eslint for vue (https://github.com/louislam/uptime-kuma/pull/121#issuecomment-889729900) 3 years ago
Louis Lam 204624bfe9
Merge pull request #133 from NiNiyas/lunasea-support 3 years ago
LouisLam b7fbc2c0e6 add LinaSea option in select box 3 years ago
LouisLam 2ebd79d037 run eslint for lunasea change 3 years ago
Niyas 3f84e5e8ab
Update notification.js 3 years ago
Niyas ab1fe2e2d1
LunaSea Support 3 years ago
Niyas 67a4e949a2
LunaSea Support 3 years ago
Louis Lam 15ee853fac
Merge pull request #132 from sashkab/dockerfile-fix 3 years ago
LouisLam d58be56cb9 remove "pip3 cache purge" that causes error 3 years ago
Aleks Bunin 00cc140acd Simplify apprise instalation 3 years ago
LouisLam 63f0a36811 implement upside down mode and ignore tls error 3 years ago
LouisLam 06377af7e5 turn off object-curly-newline, it makes const { a, b, c, d } = require(...) ugly 3 years ago
LouisLam 60aa67892d store ignoreTls and upsideDown into db 3 years ago
LouisLam 17b58eac9a Merge remote-tracking branch 'origin/master' 3 years ago
Nelson Chan b9a6088f50 WIP: Add login page, nav bar buttons 3 years ago
Louis Lam 2b3a48995b
Merge pull request #121 from chakflying/patch-1 3 years ago
LouisLam e032072900 eslint: allow while (true) 3 years ago
LouisLam bcf2a319c2 update readme 3 years ago
Nelson Chan cdaa0a54a4 Fix: use new version of babel-eslint-parser 3 years ago
Nelson Chan 47b19ea2f2 ESLint: fix file 3 years ago
Nelson Chan 1006b37a67 Fix: Add fix for babel-eslist 3 years ago
Nelson Chan b91e9ddb7a Fix: Add babel-eslint 3 years ago
Nelson Chan be22fcb87d Fix: Bump ES version in ESlint config 3 years ago
LouisLam 5a053e5875 parse the port to int 3 years ago
LouisLam 081abcb6a1 add util.ts for sharing common functions between frontend and backend 3 years ago
LouisLam 71af902a4e add fields to EditMonitor.vue 3 years ago
LouisLam 4b86c84c36 fix icon for "Resume" 3 years ago
LouisLam f9a10d1672 add back maxretries field 3 years ago
LouisLam e6915d8964 unexpected space add to router-link due vue/singleline-html-element-content-newline, set it to off 3 years ago
LouisLam 063697c20a set the port by env.PORT, specific node version in package.json 3 years ago
LouisLam 435e4faef3 test heroku deployment 3 years ago
LouisLam 1425d0e91a test heroku deployment 3 years ago
LouisLam 7dbec90c95 cache index.html and fix basic auth applied to all routes 3 years ago
LouisLam 53a90347ca update database schema, add upside_down and ignore_tls 3 years ago
LouisLam 133c7230bc fix resize problem 3 years ago
LouisLam 3666ebb931 change no-unused-vars from error to warn 3 years ago
LouisLam 6bce270f42 cleanup code 3 years ago
LouisLam 4a9690437f Merge branch 'eslint_stylelint' 3 years ago
Louis Lam c8c2300483
Merge pull request #120 from chakflying/patch-1 3 years ago
Nelson Chan ac0f418294
Fix: passwordHash is not imported 3 years ago
Adam Stachowicz d54bc866b4 Fix block-no-empty error from Stylelint 3 years ago
Adam Stachowicz be1fc0c2b6 Missing this part 2 3 years ago
Adam Stachowicz d97091af51 Missing this 3 years ago
Adam Stachowicz 4c8fdd07d9 Manual fixes 3 years ago
Adam Stachowicz 9648d700d7 Autofix on save 3 years ago
Adam Stachowicz 8331e795e7 Merge branch 'master' into eslint_stylelint 3 years ago
Adam Stachowicz 3c6af6d3f4 Add ESLint and StyleLint 3 years ago
LouisLam 209fa83cff Add Basic Auth for /metrics 3 years ago
LouisLam cc6f1d7487 Merge branch 'feature/add_prometheus_metrics' 3 years ago
LouisLam 36436ed4ef Move all Prometheus guides to wiki 3 years ago
LouisLam 934b797623 Merge branch 'master' into feature/add_prometheus_metrics 3 years ago
Louis Lam 0f0a6299c0
Create codeql-analysis.yml 3 years ago
Louis Lam e6ca105600
Update ask-for-help.md 3 years ago
Louis Lam ef45aedda5
Delete help.md 3 years ago
Louis Lam 7edd79a74d Update issue templates 3 years ago
Louis Lam fade240c7f
Delete --please-go-to--discussion--tab-if-you-want-to-ask-or-share-something.md 3 years ago
Louis Lam 46337ec348 Update issue templates 3 years ago
LouisLam cafd2c7388 add vue-fontawesone 3 years ago
LouisLam 4d7c2d329b Update to 1.0.7 3 years ago
Louis Lam 1982e2f8b8
Update README.md 3 years ago
LouisLam 2819094377 improve the page load performance 3 years ago
LouisLam 06c4523ce3 update the latest db version to 3 3 years ago
LouisLam ac3732f6cc Merge remote-tracking branch 'chakflying/tls-expiry' into tls-expiry 3 years ago
LouisLam bf3e9dccd2 improve the ui of cert info 3 years ago
LouisLam 5b18a6a518 Merge branch 'master' into tls-expiry 3 years ago
LouisLam caec933186 prevent unexpected error throw from checkCertificate interrupt the beat 3 years ago
Nelson Chan 51ac7a58dc Fix: Fix incorrect error handling 3 years ago
Nelson Chan db26b7d123 Fix: Fix no certificate caused by session reuse 3 years ago
Nelson Chan 7b8459c73a Fix: use Optional chaining 3 years ago
Nelson Chan d0c63ebe3e Feat: Add database storage for TLS info 3 years ago
Nelson Chan 803f0d6219 Feat: Add Barebones certificate info display 3 years ago
LouisLam d556509d07 戈mprove the readibility of important condition 3 years ago
Louis Lam 3cc4955cad
Merge pull request #105 from rezzorix/master 3 years ago
LouisLam 48f82b55f8 prevent unexpected error throw from checkCertificate interrupt the beat 3 years ago
rezzorix 280ba84aca
Apple touch icon 192px with preserved transparency 3 years ago
Louis Lam 0dbecca10f
Merge pull request #102 from NiNiyas/pushover-enhancements 3 years ago
Louis Lam 8279368b4d
Merge pull request #104 from rezzorix/patch-1 3 years ago
rezzorix 2450b3d082
Small grammar updates to Settings.vue 3 years ago
Nelson Chan 6b72d5033a Fix: Fix incorrect error handling 3 years ago
Nelson Chan 4d262bbb6a Fix: Fix no certificate caused by session reuse 3 years ago
Louis Lam d1370a62bd
Merge pull request #103 from Spiritreader/master 3 years ago
Sam 063fd6ef43 Merge branch 'master' of https://github.com/Spiritreader/uptime-kuma 3 years ago
Sam 1d4d7fa9c4 fix parenthesis mistake 3 years ago
Louis Lam 248b5292dc
Merge pull request #86 from Spiritreader/master 3 years ago
Matthew Macdonald-Wallace 47d830db1f Remove examples so they can go on the wiki instead 3 years ago
Matthew Macdonald-Wallace 3a8fbff514 Change casing in README, apply DRY to label values 3 years ago
Matthew Macdonald-Wallace a93fd274fd Update README to include examples for Prometheus 3 years ago
Niyas 77fbfc23be
Pushover enhancements 3 years ago
Matthew Macdonald-Wallace 3b45006567 Move common labels into dedicated const 3 years ago
Niyas b7a32d4ab6
Pushover enhancements 3 years ago
LouisLam 5a219554b3 grammar 3 years ago
LouisLam 70b1f197c1 rename "Retry Pings" to "Retries" 3 years ago
Matthew Macdonald-Wallace 720051a351 Typo in monitor status name 3 years ago
LouisLam 32a5e838ba add patch3.sql and fix duplicate id in EditMonitor.vue 3 years ago
LouisLam 86e18ac11d Merge branch 'master' into Spiritreader_master 3 years ago
Matthew Macdonald-Wallace 3dcbae0889 Add labels to metrics for querying 3 years ago
Matthew Macdonald-Wallace 96242dce0d Expose check status and response time to Prometheus 3 years ago
Nelson Chan f20ab4b0e3 Fix: use Optional chaining 3 years ago
Nelson Chan 96c60dd94a Feat: Add database storage for TLS info 3 years ago
Matthew Macdonald-Wallace 7acb265559 Remove bcryptjs and node-gyp, they should not be here... 3 years ago
Matthew Macdonald-Wallace 582fb2fe29 Export general metrics via the /metrics endpoint 3 years ago
Matthew Macdonald-Wallace e3d4a896b1 Fix up some formatting 3 years ago
Matthew Macdonald-Wallace 9a1bf6006a Add initial package import and config 3 years ago
Matthew Macdonald-Wallace ef41a32353
Merge pull request #1 from louislam/master 3 years ago
Nelson Chan ccda6f05f5 Feat: Add Barebones certificate info display 3 years ago
LouisLam 03b3bb5b30 fix if notification throw exception, the heartbeat is not stored in to the db. 3 years ago
LouisLam 7e4a1ad279 remove used vars 3 years ago
LouisLam 916b9da0dc Merge branch 'master' into something 3 years ago
LouisLam a64ce81457 update package-lock.json 3 years ago
LouisLam c575afc8e0 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam 1e42343aee
Update patch1.sql 3 years ago
LouisLam afd4cf2425 Merge branch 'master' into simple_pagination 3 years ago
LouisLam e02eb72863 add db migration 3 years ago
LouisLam 1c0dc18d72 Merge remote-tracking branch 'origin/master' 3 years ago
Louis Lam c00612c1a9
Update --please-go-to--discussion--tab-if-you-want-to-ask-or-share-something.md 3 years ago
Louis Lam 32345fcbe9 Update issue templates 3 years ago
Louis Lam fd90458e77 Update issue templates 3 years ago
Louis Lam d89e6f4649
Merge pull request #89 from Saibamen/more_info_in_server_logs 3 years ago
Adam Stachowicz c4ca8e2acb More info in server logs 3 years ago
LouisLam 94b5a557bf Merge remote-tracking branch 'origin/master' 3 years ago
Sam 14e1d1f105
add .vscode directory to dockerignore 3 years ago
Sam 8b905b6b12
Indentation fix in editor 3 years ago
Louis Lam fa57d40c3c
Update README.md 3 years ago
Louis Lam 62e231e92b
Update README.md 3 years ago
LouisLam 02b4dfc100 prevent the telegram getUpdates URL go out of box 3 years ago
Sam 054269ecf0 fix notification when changing from pending -> up 3 years ago
Sam 02230930c5 Merge branch 'master' of https://github.com/Spiritreader/uptime-kuma 3 years ago
Sam a8b102ad4a add retries for pinging function 3 years ago
Adam Stachowicz 9928ea8c30 Merge branch 'master' into simple_pagination 3 years ago
Adam Stachowicz 2d943620c7 Merge branch 'master' into simple_pagination 3 years ago
Adam Stachowicz 16f363ac38 Merge branch 'master' into simple_pagination 3 years ago
Adam Stachowicz ce6841eae7 Merge branch 'master' into simple_pagination 3 years ago
Adam Stachowicz 7c94c3b502
Update server/notification.js 3 years ago
Adam Stachowicz 268c8e50f5
Merge branch 'master' into something 3 years ago
Adam Stachowicz d94894b7e0 Fix `require-v-for-key`, remove unused declarations and double spaces 3 years ago
Adam Stachowicz a173700cd4 Add pagination 3 years ago
  1. 11
      .do/deploy.template.yaml
  2. 38
      .dockerignore
  3. 3
      .editorconfig
  4. 113
      .eslintrc.js
  5. 12
      .github/FUNDING.yml
  6. 68
      .github/ISSUE_TEMPLATE/ask-for-help.yaml
  7. 99
      .github/ISSUE_TEMPLATE/bug_report.yaml
  8. 59
      .github/ISSUE_TEMPLATE/feature_request.yaml
  9. 28
      .github/PULL_REQUEST_TEMPLATE.md
  10. 35
      .github/workflows/auto-test.yml
  11. 22
      .github/workflows/stale-bot.yml
  12. 6
      .gitignore
  13. 9
      .stylelintrc
  14. 1
      CNAME
  15. 128
      CODE_OF_CONDUCT.md
  16. 255
      CONTRIBUTING.md
  17. 130
      README.md
  18. 31
      SECURITY.md
  19. 11
      babel.config.js
  20. 5
      config/jest-backend.config.js
  21. 5
      config/jest-frontend.config.js
  22. 6
      config/jest-puppeteer.config.js
  23. 11
      config/jest.config.js
  24. 24
      config/vite.config.js
  25. BIN
      db/kuma.db
  26. 7
      db/patch-2fa-invalidate-used-token.sql
  27. 10
      db/patch-2fa.sql
  28. 7
      db/patch-add-retry-interval-monitor.sql
  29. 30
      db/patch-group-table.sql
  30. 13
      db/patch-http-monitor-method-body-and-headers.sql
  31. 10
      db/patch-improve-performance.sql
  32. 18
      db/patch-incident-table.sql
  33. 7
      db/patch-monitor-push_token.sql
  34. 18
      db/patch-notification_sent_history.sql
  35. 22
      db/patch-setting-value-type.sql
  36. 37
      db/patch1.sql
  37. 19
      db/patch10.sql
  38. 9
      db/patch2.sql
  39. 37
      db/patch3.sql
  40. 40
      db/patch4.sql
  41. 70
      db/patch5.sql
  42. 74
      db/patch6.sql
  43. 10
      db/patch7.sql
  44. 7
      db/patch8.sql
  45. 7
      db/patch9.sql
  46. 8
      docker/alpine-base.dockerfile
  47. 12
      docker/debian-base.dockerfile
  48. 0
      docker/docker-compose.yml
  49. 52
      docker/dockerfile
  50. 25
      docker/dockerfile-alpine
  51. 41
      dockerfile
  52. 6
      ecosystem.config.js
  53. 2
      extra/compile-install-script.ps1
  54. 59
      extra/download-dist.js
  55. 21
      extra/entrypoint.sh
  56. 59
      extra/healthcheck.js
  57. 245
      extra/install.batsh
  58. 26
      extra/mark-as-nightly.js
  59. 70
      extra/reset-password.js
  60. 144
      extra/simple-dns-server.js
  61. 3
      extra/update-language-files/.gitignore
  62. 86
      extra/update-language-files/index.js
  63. 12
      extra/update-language-files/package.json
  64. 100
      extra/update-version.js
  65. 64
      extra/upload-github-release-asset.sh
  66. 39
      extra/version-global-replace.js
  67. 19
      index.html
  68. 203
      install.sh
  69. 29690
      package-lock.json
  70. 155
      package.json
  71. BIN
      public/apple-touch-icon-precomposed.png
  72. BIN
      public/apple-touch-icon.png
  73. BIN
      public/favicon.ico
  74. BIN
      public/icon-192x192.png
  75. BIN
      public/icon-512x512.png
  76. 19
      public/manifest.json
  77. 3
      public/robots.txt
  78. 61
      server/auth.js
  79. 41
      server/check-version.js
  80. 100
      server/client.js
  81. 7
      server/config.js
  82. 392
      server/database.js
  83. 57
      server/image-data-uri.js
  84. 31
      server/jobs.js
  85. 40
      server/jobs/clear-old-data.js
  86. 39
      server/jobs/util-worker.js
  87. 34
      server/model/group.js
  88. 23
      server/model/heartbeat.js
  89. 18
      server/model/incident.js
  90. 687
      server/model/monitor.js
  91. 13
      server/model/tag.js
  92. 21
      server/model/user.js
  93. 749
      server/modules/apicache/apicache.js
  94. 14
      server/modules/apicache/index.js
  95. 59
      server/modules/apicache/memory-cache.js
  96. 108
      server/notification-providers/aliyun-sms.js
  97. 26
      server/notification-providers/apprise.js
  98. 89
      server/notification-providers/bark.js
  99. 42
      server/notification-providers/clicksendsms.js
  100. 79
      server/notification-providers/dingding.js

11
.do/deploy.template.yaml

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

38
.dockerignore

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

3
.editorconfig

@ -16,3 +16,6 @@ indent_size = 2
[*.yml]
indent_size = 2
[*.vue]
trim_trailing_whitespace = false

113
.eslintrc.js

@ -0,0 +1,113 @@
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"],
}
},
// Override for jest puppeteer
{
"files": [
"**/*.spec.js",
"**/*.spec.jsx"
],
env: {
jest: true,
},
globals: {
page: true,
browser: true,
context: true,
jestPuppeteer: true,
},
}
]
};

12
.github/FUNDING.yml

@ -0,0 +1,12 @@
# These are supported funding model platforms
github: louislam # 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']

68
.github/ISSUE_TEMPLATE/ask-for-help.yaml

@ -0,0 +1,68 @@
name: "❓ Ask for help"
description: "Submit any question related to Uptime Kuma"
#title: "[Help] "
labels: [help]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this bug has NOT been raised before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar issue"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/uptime-kuma/security/policy)
required: true
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "📝 Describe your problem"
description: "Please walk us through it step by step."
placeholder: "Describe what are you asking for..."
- type: input
id: uptime-kuma-version
attributes:
label: "🐻 Uptime-Kuma Version"
description: "Which version of Uptime-Kuma are you running? Please do NOT provide the docker tag such as latest or 1"
placeholder: "Ex. 1.10.0"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System and Arch"
description: "Which OS is your server/device running on?"
placeholder: "Ex. Ubuntu 20.04 x86"
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on?"
placeholder: "Ex. Google Chrome 95.0.4638.69"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker Version"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. Docker 20.10.9 / K8S / Podman"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "Ex. 14.18.0"
validations:
required: false

99
.github/ISSUE_TEMPLATE/bug_report.yaml

@ -0,0 +1,99 @@
name: "🐛 Bug Report"
description: "Submit a bug report to help us improve"
#title: "[Bug] "
labels: [bug]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this bug has NOT been raised before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar issue"
required: true
- type: checkboxes
attributes:
label: "🛡️ Security Policy"
description: Please review the security policy before reporting security related issues/bugs.
options:
- label: I agree to have read this project [Security Policy](https://github.com/louislam/uptime-kuma/security/policy)
required: true
- type: textarea
id: description
validations:
required: false
attributes:
label: "Description"
description: "You could also upload screenshots"
- type: textarea
id: steps-to-reproduce
validations:
required: true
attributes:
label: "👟 Reproduction steps"
description: "How do you trigger this bug? Please walk us through it step by step."
placeholder: "..."
- type: textarea
id: expected-behavior
validations:
required: true
attributes:
label: "👀 Expected behavior"
description: "What did you think would happen?"
placeholder: "..."
- type: textarea
id: actual-behavior
validations:
required: true
attributes:
label: "😓 Actual Behavior"
description: "What actually happen?"
placeholder: "..."
- type: input
id: uptime-kuma-version
attributes:
label: "🐻 Uptime-Kuma Version"
description: "Which version of Uptime-Kuma are you running? Please do NOT provide the docker tag such as latest or 1"
placeholder: "Ex. 1.10.0"
validations:
required: true
- type: input
id: operating-system
attributes:
label: "💻 Operating System and Arch"
description: "Which OS is your server/device running on?"
placeholder: "Ex. Ubuntu 20.04 x86"
validations:
required: true
- type: input
id: browser-vendor
attributes:
label: "🌐 Browser"
description: "Which browser are you running on?"
placeholder: "Ex. Google Chrome 95.0.4638.69"
validations:
required: true
- type: input
id: docker-version
attributes:
label: "🐋 Docker Version"
description: "If running with Docker, which version are you running?"
placeholder: "Ex. Docker 20.10.9 / K8S / Podman"
validations:
required: false
- type: input
id: nodejs-version
attributes:
label: "🟩 NodeJS Version"
description: "If running with Node.js? which version are you running?"
placeholder: "Ex. 14.18.0"
validations:
required: false
- type: textarea
id: logs
attributes:
label: "📝 Relevant log output"
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
render: shell
validations:
required: false

59
.github/ISSUE_TEMPLATE/feature_request.yaml

@ -0,0 +1,59 @@
name: 🚀 Feature Request
description: "Submit a proposal for a new feature"
#title: "[Feature] "
labels: [feature-request]
body:
- type: checkboxes
id: no-duplicate-issues
attributes:
label: "⚠️ Please verify that this feature request has NOT been suggested before."
description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)"
options:
- label: "I checked and didn't find similar feature request"
required: true
- type: dropdown
id: feature-area
attributes:
label: "🏷️ Feature Request Type"
description: "What kind of feature request is this?"
multiple: true
options:
- API
- New Notification
- New Monitor
- UI Feature
- Other
validations:
required: true
- type: textarea
id: feature-description
validations:
required: true
attributes:
label: "🔖 Feature description"
description: "A clear and concise description of what the feature request is."
placeholder: "You should add ..."
- type: textarea
id: solution
validations:
required: true
attributes:
label: "✔️ Solution"
description: "A clear and concise description of what you want to happen."
placeholder: "In my use-case, ..."
- type: textarea
id: alternatives
validations:
required: false
attributes:
label: "❓ Alternatives"
description: "A clear and concise description of any alternative solutions or features you've considered."
placeholder: "I have considered ..."
- type: textarea
id: additional-context
validations:
required: false
attributes:
label: "📝 Additional Context"
description: "Add any other context or screenshots about the feature request here."
placeholder: "..."

28
.github/PULL_REQUEST_TEMPLATE.md

@ -0,0 +1,28 @@
# Description
Fixes #(issue)
## Type of change
Please delete options that are not relevant.
- Bug fix (non-breaking change which fixes an issue)
- User Interface
- New feature (non-breaking change which adds functionality)
- Breaking change (fix or feature that would cause existing functionality to not work as expected)
- Translation update
- Other
- This change requires a documentation update
## Checklist
- [ ] My code follows the style guidelines of this project
- [ ] I ran ESLint and other linters for modified files
- [ ] I have performed a self-review of my own code and test it
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] My changes generate no new warnings
- [ ] My code needed automated testing. I have added them (this is optional task)
## Screenshots (if any)
Please do not use any external image service. Instead, just paste in or drag and drop the image here and it will be uploaded automatically.

35
.github/workflows/auto-test.yml

@ -0,0 +1,35 @@
# This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: Auto Test
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
auto-test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
node-version: [14.x, 16.x, 17.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- run: npm run install-legacy
- run: npm run build
- run: npm test
env:
HEADLESS_TEST: 1
JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }}

22
.github/workflows/stale-bot.yml

@ -0,0 +1,22 @@
name: 'Automatically close stale issues and PRs'
on:
schedule:
- cron: '0 0 * * *'
#Run once a day at midnight
jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v4
with:
stale-issue-message: 'We are clearing up our old issues and your ticket has been open for 6 months with no activity. Remove stale label or comment or this will be closed in 7 days.'
stale-pr-message: 'We are clearing up our old Pull Requests and yours has been open for 6 months with no activity. Remove stale label or comment or this will be closed in 7 days.'
close-issue-message: 'This issue was closed because it has been stalled for 7 days with no activity.'
close-pr-message: 'This PR was closed because it has been stalled for 7 days with no activity.'
days-before-stale: 180
days-before-close: 7
exempt-issue-labels: 'News,Medium,High,discussion,bug,doc,'
exempt-pr-labels: 'awaiting-approval,work-in-progress,enhancement,'
exempt-issue-assignees: 'louislam'
exempt-pr-assignees: 'louislam'

6
.gitignore

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

9
.stylelintrc

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

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

128
CODE_OF_CONDUCT.md

@ -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
uptime@kuma.pet.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
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.

255
CONTRIBUTING.md

@ -0,0 +1,255 @@
# 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 (express.js) exposes the "dist" directory as root of the endpoint. This is how production is working.
## Key Technical Skills
- Node.js (You should know what are promise, async/await and arrow function etc.)
- Socket.io
- SCSS
- Vue.js
- Bootstrap
- SQLite
## Directories
- data (App data)
- dist (Frontend build)
- extra (Extra useful scripts)
- public (Frontend resources for dev only)
- server (Server source code)
- src (Frontend source code)
- test (unit test)
## 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 into the master branch once it is tested.
If you are not sure whether I will accept your pull request, feel free to create an empty pull request draft first.
### Recommended Pull Request Guideline
1. Fork the project
1. Clone your fork repo to local
1. Create a new branch
1. Create an empty commit
`git commit -m "[empty commit] pull request for <YOUR TASK NAME>" --allow-empty`
1. Push to your fork repo
1. Create a pull request: https://github.com/louislam/uptime-kuma/compare
1. Write a proper description
1. Click "Change to draft"
### Pull Request Examples
Here are some example situations in the past.
#### ✅ High - Medium Priority
Easy to review, no breaking change and not touching the existing code
- Add a new notification
- Add a chart
- Fix a bug
- Translations
- Add a independent new feature
#### *️⃣ Requires one more reviewer
I do not have such knowledge to test it.
- Add k8s supports
#### ⚠ Low Priority - Harsh Mode
Some pull requests are required to modifiy the core. To be honest, I do not want anyone to try to do that, because it would spend a lot of your time. I will review your pull request harshly. Also you may need to write a lot of unit tests to ensure that there is no breaking change.
- Touch large parts of code of any very important features
- Touch monitoring logic
- Drop a table or drop a column for any reason
- Touch the entry point of Docker or Node.js
- Modifiy auth
#### *️⃣ Low Priority
It changed my current workflow and require further studies.
- Change my release approach
#### ❌ Won't Merge
- Any breaking changes
- 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.
- 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-compose file. Just map the volume and expose the port, then good to go
- Settings should be configurable in the frontend. Env var is not encouraged.
- Easy to use
## Coding Styles
- 4 spaces indentation
- Follow `.editorconfig`
- Follow ESLint
## Name convention
- Javascript/Typescript: camelCaseType
- SQLite: underscore_type
- CSS/SCSS: dash-type
## Tools
- Node.js >= 14
- Git
- IDE that supports ESLint and EditorConfig (I am using Intellji Idea)
- A SQLite tool (SQLite Expert Personal is suggested)
## Install dependencies
```bash
npm ci
```
## How to start the Backend Dev Server
(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.)
- model/ (Object model, auto mapping to the database table name)
- modules/ (Modified 3rd-party modules)
- notification-providers/ (indivdual notification logic)
- routers/ (Express Routers)
- scoket-handler (Socket.io Handlers)
- server.js (Server main logic)
## How to start the Frontend Dev Server
1. Set the env var `NODE_ENV` to "development".
2. Start the frontend dev server by the following command.
```bash
npm run dev
```
It binds to `0.0.0.0:3000` by default.
You can use Vue.js devtools Chrome extension for debugging.
### 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-{name}.sql` in `./db/`
2. Add your patch filename in the `patchList` list in `./server/database.js`
## Unit Test
It is an end-to-end testing. It is using Jest and Puppeteer.
```bash
npm run build
npm test
```
By default, the Chromium window will be shown up during the test. Specifying `HEADLESS_TEST=1` for terminal environments.
## Update Dependencies
Install `ncu`
https://github.com/raineorshine/npm-check-updates
```bash
ncu -u -t patch
npm install
```
Since previously updating vite 2.5.10 to 2.6.0 broke the application completely, from now on, it should update patch release version only.
Patch release = the third digit ([Semantic Versioning](https://semver.org/))
## Translations
Please read: https://github.com/louislam/uptime-kuma/tree/master/src/languages
## Wiki
Since there is no way to make a pull request to wiki's repo, I have setup another repo to do that.
https://github.com/louislam/uptime-kuma-wiki
## Maintainer
Check the latest issues and pull requests:
https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc
### Release Procedures
1. Draft a release note
1. Make sure the repo is cleared
1. `npm run update-version 1.X.X`
1. `npm run build`
1. `npm run build-docker`
1. `git push`
1. Publish the release note as 1.X.X
1. `npm run upload-artifacts`
1. SSH to demo site server and update to 1.X.X
Checking:
- Check all tags is fine on https://hub.docker.com/r/louislam/uptime-kuma/tags
- Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64 / armv7)
- Try clean install with Node.js
### Release Wiki
#### Setup Repo
```
git clone https://github.com/louislam/uptime-kuma-wiki.git
cd uptime-kuma-wiki
git remote add production https://github.com/louislam/uptime-kuma.wiki.git
```
#### Push to Production Wiki
```
git pull
git push production master
```

130
README.md

@ -1,7 +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>
<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> <a target="_blank" href="https://opencollective.com/uptime-kuma"><img src="https://opencollective.com/uptime-kuma/total/badge.svg?label=Open%20Collective%20Backers&color=brightgreen" /></a>
[![GitHub Sponsors](https://img.shields.io/github/sponsors/louislam?label=GitHub%20Sponsors)](https://github.com/sponsors/louislam)
<div align="center" width="100%">
<img src="./public/icon.svg" width="128" alt="" />
@ -9,84 +9,93 @@
It is a self-hosted monitoring tool like "Uptime Robot".
<img src="https://louislam.net/uptimekuma/1.jpg" width="512" alt="" />
<img src="https://uptime.kuma.pet/img/dark.jpg" width="700" alt="" />
# Features
## 🥔 Live Demo
* Monitoring uptime for HTTP(s) / TCP / Ping.
* Fancy, Reactive, Fast UI/UX.
* Notifications via Webhook, Telegram, Discord and email (SMTP).
* 20 seconds interval.
Try it!
# How to Use
https://demo.uptime.kuma.pet
### Docker
It is a temporary live demo, all data will be deleted after 10 minutes. The server is located at Tokyo, so if you live far from there it may affect your experience. I suggest that you should install and try it out for the best demo experience.
```bash
# Create a volume
docker volume create uptime-kuma
VPS is sponsored by Uptime Kuma sponsors on [Open Collective](https://opencollective.com/uptime-kuma)! Thank you so much!
# Start the container
docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1
```
## ⭐ Features
* Monitoring uptime for HTTP(s) / TCP / Ping / DNS Record / Push.
* Fancy, Reactive, Fast UI/UX.
* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [70+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications).
* 20 second intervals.
* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/languages)
* Simple Status Page
* Ping Chart
* Certificate Info
Browse to http://localhost:3001 after started.
## 🔧 How to Install
Change Port and Volume
### 🐳 Docker
```bash
docker run -d --restart=always -p <YOUR_PORT>:3001 -v <YOUR_DIR OR VOLUME>:/app/data --name uptime-kuma louislam/uptime-kuma:1
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
```
### Without Docker
Browse to http://localhost:3001 after starting.
### 💪🏻 Non-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
# (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
# (Recommended) Option 2. Run in background using PM2
# Install PM2 if you don't have it: npm install pm2 -g
pm2 start server/server.js --name uptime-kuma
```
# Listen to different port or hostname
pm2 start npm --name uptime-kuma -- run start-server -- --port=80 --hostname=0.0.0.0
Browse to http://localhost:3001 after starting.
```
### Advanced Installation
Browse to http://localhost:3001 after started.
If you need more options or need to browse via a reserve proxy, please read:
### One-click Deploy to DigitalOcean
https://github.com/louislam/uptime-kuma/wiki/%F0%9F%94%A7-How-to-Install
[![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)
## 🆙 How to Update
Choose Cheapest Plan is enough. (US$ 5)
Please read:
# How to Update
https://github.com/louislam/uptime-kuma/wiki/%F0%9F%86%99-How-to-Update
### Docker
## 🆕 What's Next?
Re-pull the latest docker image and create another container with the same volume.
I will mark requests/issues to the next milestone.
PS: For every new release, it takes some time to build the docker image, please be patient if it is not available yet.
https://github.com/louislam/uptime-kuma/milestones
### Without Docker
Project Plan:
```bash
git fetch --all
git checkout 1.0.6 --force
npm install
npm run build
pm2 restart uptime-kuma
```
https://github.com/louislam/uptime-kuma/projects/1
## 🖼 More Screenshots
Light Mode:
# More Screenshots
<img src="https://uptime.kuma.pet/img/light.jpg" width="512" alt="" />
Status Page:
<img src="https://user-images.githubusercontent.com/1336778/134628766-a3fe0981-0926-4285-ab46-891a21c3e4cb.png" width="512" alt="" />
Settings Page:
@ -96,24 +105,35 @@ 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 a question on Reddit.
https://www.reddit.com/r/UptimeKuma/
## Contribute
# 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 report a bug or request a new feature. Free feel to open a new issue.
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 maybe useful for you: https://github.com/louislam/uptime-kuma/wiki/%5BDev%5D-Setup-Development-Environment
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.
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.

31
SECURITY.md

@ -0,0 +1,31 @@
# Security Policy
## 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.
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
### Uptime Kuma Versions
| Version | Supported |
| ------- | ------------------ |
| 1.9.X | :white_check_mark: |
| <= 1.8.X | ❌ |
### Upgradable Docker Tags
| Tag | Supported |
| ------- | ------------------ |
| 1 | :white_check_mark: |
| 1-debian | :white_check_mark: |
| 1-alpine | :white_check_mark: |
| latest | :white_check_mark: |
| debian | :white_check_mark: |
| alpine | :white_check_mark: |
| All other tags | ❌ |

11
babel.config.js

@ -0,0 +1,11 @@
const config = {};
if (process.env.TEST_FRONTEND) {
config.presets = ["@babel/preset-env"];
}
if (process.env.TEST_BACKEND) {
config.plugins = ["babel-plugin-rewire"];
}
module.exports = config;

5
config/jest-backend.config.js

@ -0,0 +1,5 @@
module.exports = {
"rootDir": "..",
"testRegex": "./test/backend.spec.js",
};

5
config/jest-frontend.config.js

@ -0,0 +1,5 @@
module.exports = {
"rootDir": "..",
"testRegex": "./test/frontend.spec.js",
};

6
config/jest-puppeteer.config.js

@ -0,0 +1,6 @@
module.exports = {
"launch": {
"headless": process.env.HEADLESS_TEST || false,
"userDataDir": "./data/test-chrome-profile",
}
};

11
config/jest.config.js

@ -0,0 +1,11 @@
module.exports = {
"verbose": true,
"preset": "jest-puppeteer",
"globals": {
"__DEV__": true
},
"testRegex": "./test/e2e.spec.js",
"rootDir": "..",
"testTimeout": 30000,
};

24
config/vite.config.js

@ -0,0 +1,24 @@
import legacy from "@vitejs/plugin-legacy";
import vue from "@vitejs/plugin-vue";
import { defineConfig } from "vite";
const postCssScss = require("postcss-scss");
const postcssRTLCSS = require("postcss-rtlcss");
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue(),
legacy({
targets: ["ie > 11"],
additionalLegacyPolyfills: ["regenerator-runtime/runtime"]
})
],
css: {
postcss: {
"parser": postCssScss,
"map": false,
"plugins": [postcssRTLCSS]
}
},
});

BIN
db/kuma.db

Binary file not shown.

7
db/patch-2fa-invalidate-used-token.sql

@ -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 user
ADD twofa_last_token VARCHAR(6);
COMMIT;

10
db/patch-2fa.sql

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

7
db/patch-add-retry-interval-monitor.sql

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

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

13
db/patch-http-monitor-method-body-and-headers.sql

@ -0,0 +1,13 @@
-- You should not modify if this have pushed to Github, unless it does serious wrong with the db.
BEGIN TRANSACTION;
ALTER TABLE monitor
ADD method TEXT default 'GET' not null;
ALTER TABLE monitor
ADD body TEXT default null;
ALTER TABLE monitor
ADD headers TEXT default null;
COMMIT;

10
db/patch-improve-performance.sql

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

18
db/patch-incident-table.sql

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

7
db/patch-monitor-push_token.sql

@ -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 push_token VARCHAR(20) DEFAULT NULL;
COMMIT;

18
db/patch-notification_sent_history.sql

@ -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 [notification_sent_history] (
[id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
[type] VARCHAR(50) NOT NULL,
[monitor_id] INTEGER NOT NULL,
[days] INTEGER NOT NULL,
UNIQUE([type], [monitor_id], [days])
);
CREATE INDEX [good_index] ON [notification_sent_history] (
[type],
[monitor_id],
[days]
);
COMMIT;

22
db/patch-setting-value-type.sql

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

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

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

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

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

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

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

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

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

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

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

8
docker/alpine-base.dockerfile

@ -0,0 +1,8 @@
# DON'T UPDATE TO alpine3.13, 1.14, see #41.
FROM node:14-alpine3.12
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

12
docker/debian-base.dockerfile

@ -0,0 +1,12 @@
# 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
WORKDIR /app
# Install Apprise, add sqlite3 cli for debugging in the future, iputils-ping for ping, util-linux for setpriv
# Stupid python3 and python3-pip actually install a lot of useless things into Debian, specific --no-install-recommends to skip them, make the base even smaller than alpine!
RUN apt update && \
apt --yes --no-install-recommends 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/*

0
docker-compose.yml → docker/docker-compose.yml

52
docker/dockerfile

@ -0,0 +1,52 @@
FROM louislam/uptime-kuma:base-debian AS build
WORKDIR /app
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
COPY . .
RUN npm ci --production && \
chmod +x /app/extra/entrypoint.sh
FROM louislam/uptime-kuma:base-debian AS release
WORKDIR /app
# 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
# Upload the artifact to Github
FROM louislam/uptime-kuma:base-debian AS upload-artifact
WORKDIR /
RUN apt update && \
apt --yes install curl file
COPY --from=build /app /app
ARG VERSION=1.9.1
ARG GITHUB_TOKEN
ARG TARGETARCH
ARG PLATFORM=debian
ARG FILE=$PLATFORM-$TARGETARCH-$VERSION.tar.gz
ARG DIST=dist.tar.gz
RUN chmod +x /app/extra/upload-github-release-asset.sh
# Full Build
# RUN tar -zcvf $FILE app
# RUN /app/extra/upload-github-release-asset.sh github_api_token=$GITHUB_TOKEN owner=louislam repo=uptime-kuma tag=$VERSION filename=$FILE
# Dist only
RUN cd /app && tar -zcvf $DIST dist
RUN /app/extra/upload-github-release-asset.sh github_api_token=$GITHUB_TOKEN owner=louislam repo=uptime-kuma tag=$VERSION filename=/app/$DIST

25
docker/dockerfile-alpine

@ -0,0 +1,25 @@
FROM louislam/uptime-kuma:base-alpine AS build
WORKDIR /app
ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
COPY . .
RUN npm ci --production && \
chmod +x /app/extra/entrypoint.sh
FROM louislam/uptime-kuma:base-alpine AS release
WORKDIR /app
# 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

41
dockerfile

@ -1,41 +0,0 @@
# DON'T UPDATE TO alpine3.13, 1.14, see #41.
FROM node:14-alpine3.12 AS release
WORKDIR /app
# split the sqlite install here, so that it can caches the arm prebuilt
RUN apk add --no-cache --virtual .build-deps make g++ python3 python3-dev && \
ln -s /usr/bin/python3 /usr/bin/python && \
npm install sqlite3@5.0.2 bcrypt@5.0.1 && \
apk del .build-deps
# Touching above code may causes sqlite3 re-compile again, painful slow.
# Install apprise
# Hate pip!!! I never run pip install successfully in first run for anything in my life without Google :/
# Compilation Fail 1 => Google Search "alpine ffi.h" => Add libffi-dev
# Compilation Fail 2 => Google Search "alpine cargo" => Add cargo
# Compilation Fail 3 => Google Search "alpine opensslv.h" => Add openssl-dev
# Compilation Fail 4 => Google Search "alpine opensslv.h" again => Change to libressl-dev musl-dev
# Compilation Fail 5 => Google Search "ERROR: libressl3.3-libtls-3.3.3-r0: trying to overwrite usr/lib/libtls.so.20 owned by libretls-3.3.3-r0." again => Change back to openssl-dev with musl-dev
# Runtime Error => ModuleNotFoundError: No module named 'six' => pip3 install six
# Runtime Error 2 => ModuleNotFoundError: No module named 'six' => apk add py3-six
ENV CRYPTOGRAPHY_DONT_BUILD_RUST=1
RUN apk add --no-cache python3 py3-pip py3-six cargo
RUN apk add --no-cache --virtual .build-deps libffi-dev musl-dev openssl-dev python3-dev && \
pip3 install apprise && \
apk del .build-deps
RUN apprise --version
# New things add here
COPY . .
RUN npm install
RUN npm run build
EXPOSE 3001
VOLUME ["/app/data"]
HEALTHCHECK --interval=60s --timeout=30s --start-period=300s CMD node extra/healthcheck.js
CMD ["npm", "run", "start-server"]
FROM release AS nightly
RUN npm run mark-as-nightly

6
ecosystem.config.js

@ -0,0 +1,6 @@
module.exports = {
apps: [{
name: "uptime-kuma",
script: "./server/server.js",
}]
}

2
extra/compile-install-script.ps1

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

59
extra/download-dist.js

@ -0,0 +1,59 @@
console.log("Downloading dist");
const https = require("https");
const tar = require("tar");
const packageJSON = require("../package.json");
const fs = require("fs");
const version = packageJSON.version;
const filename = "dist.tar.gz";
const url = `https://github.com/louislam/uptime-kuma/releases/download/${version}/${filename}`;
download(url);
function download(url) {
console.log(url);
https.get(url, (response) => {
if (response.statusCode === 200) {
console.log("Extracting dist...");
if (fs.existsSync("./dist")) {
if (fs.existsSync("./dist-backup")) {
fs.rmdirSync("./dist-backup", {
recursive: true
});
}
fs.renameSync("./dist", "./dist-backup");
}
const tarStream = tar.x({
cwd: "./",
});
tarStream.on("close", () => {
if (fs.existsSync("./dist-backup")) {
fs.rmdirSync("./dist-backup", {
recursive: true
});
}
console.log("Done");
});
tarStream.on("error", () => {
if (fs.existsSync("./dist-backup")) {
fs.renameSync("./dist-backup", "./dist");
}
console.error("Error from tarStream");
});
response.pipe(tarStream);
} else if (response.statusCode === 302) {
download(response.headers.location);
} else {
console.log("dist not found");
}
});
}

21
extra/entrypoint.sh

@ -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 "$@"

59
extra/healthcheck.js

@ -1,19 +1,50 @@
var http = require("http");
var options = {
host: "localhost",
port: "3001",
timeout: 2000,
/*
* This script should be run after a period of time (180s), because the server may need some time to prepare.
*/
const { FBSD } = require("../server/util-server");
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
let client;
const sslKey = process.env.UPTIME_KUMA_SSL_KEY || process.env.SSL_KEY || undefined;
const sslCert = process.env.UPTIME_KUMA_SSL_CERT || process.env.SSL_CERT || undefined;
if (sslKey && sslCert) {
client = require("https");
} else {
client = require("http");
}
// If host is omitted, the server will accept connections on the unspecified IPv6 address (::) when IPv6 is available and the unspecified IPv4 address (0.0.0.0) otherwise.
// Dual-stack support for (::)
let hostname = process.env.UPTIME_KUMA_HOST;
// Also read HOST if not FreeBSD, as HOST is a system environment variable in FreeBSD
if (!hostname && !FBSD) {
hostname = process.env.HOST;
}
const port = parseInt(process.env.UPTIME_KUMA_PORT || process.env.PORT || 3001);
let options = {
host: hostname || "127.0.0.1",
port: port,
timeout: 28 * 1000,
};
var request = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
if (res.statusCode == 200) {
process.exit(0);
} else {
process.exit(1);
}
let request = client.request(options, (res) => {
console.log(`Health Check OK [Res Code: ${res.statusCode}]`);
if (res.statusCode === 302) {
process.exit(0);
} else {
process.exit(1);
}
});
request.on("error", function (err) {
console.log("ERROR");
process.exit(1);
console.error("Health Check ERROR");
process.exit(1);
});
request.end();

245
extra/install.batsh

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

26
extra/mark-as-nightly.js

@ -1,25 +1,9 @@
/**
* String.prototype.replaceAll() polyfill
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
* @author Chris Ferdinandi
* @license MIT
*/
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(str, newStr){
// If a regex pattern
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
return this.replace(str, newStr);
}
const pkg = require("../package.json");
const fs = require("fs");
const util = require("../src/util");
// If a string
return this.replace(new RegExp(str, 'g'), newStr);
util.polyfill();
};
}
const pkg = require('../package.json');
const fs = require("fs");
const oldVersion = pkg.version
const newVersion = oldVersion + "-nightly"
@ -35,6 +19,6 @@ if (newVersion) {
// Process README.md
if (fs.existsSync("README.md")) {
fs.writeFileSync("README.md", fs.readFileSync("README.md", 'utf8').replaceAll(oldVersion, newVersion))
fs.writeFileSync("README.md", fs.readFileSync("README.md", "utf8").replaceAll(oldVersion, newVersion))
}
}

70
extra/reset-password.js

@ -0,0 +1,70 @@
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
});
const main = async () => {
Database.init(args);
await Database.connect();
try {
// No need to actually reset the password for testing, just make sure no connection problem. It is ok for now.
if (!process.env.TEST_BACKEND) {
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();
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();
rl.close();
console.log("Finished.");
};
function question(question) {
return new Promise((resolve) => {
rl.question(question, (answer) => {
resolve(answer);
});
});
}
if (!process.env.TEST_BACKEND) {
main();
}
module.exports = {
main,
};

144
extra/simple-dns-server.js

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

3
extra/update-language-files/.gitignore

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

86
extra/update-language-files/index.js

@ -0,0 +1,86 @@
// 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);
if (fs.existsSync("./languages")) {
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...");

12
extra/update-language-files/package.json

@ -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"
}

100
extra/update-version.js

@ -0,0 +1,100 @@
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);
updateWiki(oldVersion, 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;
}
function updateWiki(oldVersion, newVersion) {
const wikiDir = "./tmp/wiki";
const howToUpdateFilename = "./tmp/wiki/🆙-How-to-Update.md";
safeDelete(wikiDir);
child_process.spawnSync("git", ["clone", "https://github.com/louislam/uptime-kuma.wiki.git", wikiDir]);
let content = fs.readFileSync(howToUpdateFilename).toString();
content = content.replaceAll(`git checkout ${oldVersion}`, `git checkout ${newVersion}`);
fs.writeFileSync(howToUpdateFilename, content);
child_process.spawnSync("git", ["add", "-A"], {
cwd: wikiDir,
});
child_process.spawnSync("git", ["commit", "-m", `Update to ${newVersion} from ${oldVersion}`], {
cwd: wikiDir,
});
console.log("Pushing to Github");
child_process.spawnSync("git", ["push"], {
cwd: wikiDir,
});
safeDelete(wikiDir);
}
function safeDelete(dir) {
if (fs.existsSync(dir)) {
fs.rmdirSync(dir, {
recursive: true,
});
}
}

64
extra/upload-github-release-asset.sh

@ -0,0 +1,64 @@
#!/usr/bin/env bash
#
# Author: Stefan Buck
# License: MIT
# https://gist.github.com/stefanbuck/ce788fee19ab6eb0b4447a85fc99f447
#
#
# This script accepts the following parameters:
#
# * owner
# * repo
# * tag
# * filename
# * github_api_token
#
# Script to upload a release asset using the GitHub API v3.
#
# Example:
#
# upload-github-release-asset.sh github_api_token=TOKEN owner=stefanbuck repo=playground tag=v0.1.0 filename=./build.zip
#
# Check dependencies.
set -e
xargs=$(which gxargs || which xargs)
# Validate settings.
[ "$TRACE" ] && set -x
CONFIG=$@
for line in $CONFIG; do
eval "$line"
done
# Define variables.
GH_API="https://api.github.com"
GH_REPO="$GH_API/repos/$owner/$repo"
GH_TAGS="$GH_REPO/releases/tags/$tag"
AUTH="Authorization: token $github_api_token"
WGET_ARGS="--content-disposition --auth-no-challenge --no-cookie"
CURL_ARGS="-LJO#"
if [[ "$tag" == 'LATEST' ]]; then
GH_TAGS="$GH_REPO/releases/latest"
fi
# Validate token.
curl -o /dev/null -sH "$AUTH" $GH_REPO || { echo "Error: Invalid repo, token or network issue!"; exit 1; }
# Read asset tags.
response=$(curl -sH "$AUTH" $GH_TAGS)
# Get ID of the asset based on given filename.
eval $(echo "$response" | grep -m 1 "id.:" | grep -w id | tr : = | tr -cd '[[:alnum:]]=')
[ "$id" ] || { echo "Error: Failed to get release id for tag: $tag"; echo "$response" | awk 'length($0)<100' >&2; exit 1; }
# Upload asset
echo "Uploading asset... "
# Construct url
GH_ASSET="https://uploads.github.com/repos/$owner/$repo/releases/$id/assets?name=$(basename $filename)"
curl "$GITHUB_OAUTH_BASIC" --data-binary @"$filename" -H "Authorization: token $github_api_token" -H "Content-Type: application/octet-stream" $GH_ASSET

39
extra/version-global-replace.js

@ -1,39 +0,0 @@
/**
* String.prototype.replaceAll() polyfill
* https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/
* @author Chris Ferdinandi
* @license MIT
*/
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function(str, newStr){
// If a regex pattern
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
return this.replace(str, newStr);
}
// If a string
return this.replace(new RegExp(str, 'g'), newStr);
};
}
const pkg = require('../package.json');
const fs = require("fs");
const oldVersion = pkg.version
const newVersion = process.argv[2]
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
fs.writeFileSync("README.md", fs.readFileSync("README.md", 'utf8').replaceAll(oldVersion, newVersion))
}

19
index.html

@ -1,16 +1,17 @@
<!DOCTYPE html>
<html lang="en">
<head>
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/icon.svg" />
<link rel="apple-touch-icon" href="/apple-touch-icon.png">
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="theme-color" content="#5cdd8b" />
<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

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

29690
package-lock.json

File diff suppressed because it is too large

155
package.json

@ -1,54 +1,131 @@
{
"name": "uptime-kuma",
"version": "1.0.6",
"version": "1.10.2",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/louislam/uptime-kuma.git"
},
"engines": {
"node": "14.*"
},
"scripts": {
"dev": "vite --host",
"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 --config ./config/vite.config.js",
"start": "npm run start-server",
"start-server": "node server/server.js",
"update": "",
"build": "vite build",
"vite-preview-dist": "vite preview --host",
"build-docker": "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.0.6 --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-amd64": "docker buildx build --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push",
"setup": "git checkout 1.0.6 && npm install && npm run build",
"version-global-replace": "node extra/version-global-replace.js",
"mark-as-nightly": "node extra/mark-as-nightly.js"
"start-server-dev": "cross-env NODE_ENV=development node server/server.js",
"build": "vite build --config ./config/vite.config.js",
"test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --test",
"test-with-build": "npm run build && npm test",
"jest": "node test/prepare-jest.js && npm run jest-frontend && npm run jest-backend && jest --config=./config/jest.config.js",
"jest-frontend": "cross-env TEST_FRONTEND=1 jest --config=./config/jest-frontend.config.js",
"jest-backend": "cross-env TEST_BACKEND=1 jest --config=./config/jest-backend.config.js",
"tsc": "tsc",
"vite-preview-dist": "vite preview --host --config ./config/vite.config.js",
"build-docker": "npm run build-docker-debian && npm run build-docker-alpine",
"build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push",
"build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push",
"build-docker-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:1.10.2-alpine --target release . --push",
"build-docker-debian": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:1.10.2 -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:1.10.2-debian --target release . --push",
"build-docker-nightly": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push",
"build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push",
"build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain",
"upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain",
"setup": "git checkout 1.10.2 && npm ci --production && npm run download-dist",
"download-dist": "node extra/download-dist.js",
"update-version": "node extra/update-version.js",
"mark-as-nightly": "node extra/mark-as-nightly.js",
"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",
"args-parser": "^1.3.0",
"axios": "^0.21.1",
"bcrypt": "^5.0.1",
"bootstrap": "^5.0.2",
"command-exists": "^1.2.9",
"dayjs": "^1.10.6",
"express": "^4.17.1",
"form-data": "^4.0.0",
"http-graceful-shutdown": "^3.1.2",
"jsonwebtoken": "^8.5.1",
"nodemailer": "^6.6.3",
"password-hash": "^1.2.2",
"redbean-node": "0.0.20",
"socket.io": "^4.1.3",
"socket.io-client": "^4.1.3",
"sqlite3": "^5.0.2",
"tcp-ping": "^0.1.1",
"vue": "^3.0.5",
"vue-confirm-dialog": "^1.0.2",
"vue-router": "^4.0.10",
"vue-toastification": "^2.0.0-rc.1"
"@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": "~6.0.0",
"@popperjs/core": "~2.10.2",
"args-parser": "~1.3.0",
"axios": "~0.21.4",
"bcryptjs": "~2.4.3",
"bootstrap": "5.1.3",
"bree": "~6.3.1",
"chardet": "^1.3.0",
"chart.js": "~3.6.0",
"chartjs-adapter-dayjs": "~1.0.0",
"check-password-strength": "^2.0.3",
"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",
"iconv-lite": "^0.6.3",
"jsonwebtoken": "~8.5.1",
"jwt-decode": "^3.1.2",
"limiter": "^2.1.0",
"nodemailer": "~6.6.5",
"notp": "~2.0.3",
"password-hash": "~1.2.2",
"postcss-rtlcss": "~3.4.1",
"postcss-scss": "~4.0.1",
"prom-client": "~13.2.0",
"prometheus-api-metrics": "~3.2.0",
"qrcode": "~1.4.4",
"redbean-node": "0.1.3",
"socket.io": "~4.2.0",
"socket.io-client": "~4.2.0",
"tar": "^6.1.11",
"tcp-ping": "~0.1.1",
"thirty-two": "~1.0.2",
"timezones-list": "~3.0.1",
"v-pagination-3": "~0.1.7",
"vue": "next",
"vue-chart-3": "~0.5.11",
"vue-confirm-dialog": "~1.0.2",
"vue-contenteditable": "~3.0.4",
"vue-i18n": "~9.1.9",
"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.4",
"@vitejs/plugin-vue": "^1.2.5",
"@vue/compiler-sfc": "^3.1.5",
"core-js": "^3.15.2",
"sass": "^1.35.2",
"vite": "^2.4.2"
"@babel/eslint-parser": "~7.15.7",
"@babel/preset-env": "^7.15.8",
"@types/bootstrap": "~5.1.6",
"@vitejs/plugin-legacy": "~1.6.2",
"@vitejs/plugin-vue": "~1.9.4",
"@vue/compiler-sfc": "~3.2.20",
"babel-plugin-rewire": "~1.2.0",
"core-js": "~3.18.1",
"cross-env": "~7.0.3",
"dns2": "~2.0.1",
"eslint": "~7.32.0",
"eslint-plugin-vue": "~7.18.0",
"jest": "~27.2.4",
"jest-puppeteer": "~6.0.0",
"puppeteer": "~10.4.0",
"sass": "~1.42.1",
"stylelint": "~13.13.1",
"stylelint-config-standard": "~22.0.0",
"typescript": "~4.4.3",
"vite": "~2.6.13"
}
}

BIN
public/apple-touch-icon-precomposed.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
public/apple-touch-icon.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

BIN
public/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
public/icon-192x192.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

BIN
public/icon-512x512.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

19
public/manifest.json

@ -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"
}
]
}

3
public/robots.txt

@ -1,3 +0,0 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

61
server/auth.js

@ -0,0 +1,61 @@
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");
const { loginRateLimiter } = require("./rate-limiter");
/**
*
* @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 {
// Login Rate Limit
loginRateLimiter.pass(null, 0).then((pass) => {
if (pass) {
exports.login(username, password).then((user) => {
callback(null, user != null);
if (user == null) {
loginRateLimiter.removeTokens(1);
}
});
} else {
callback(null, false);
}
});
}
});
}
exports.basicAuth = basicAuth({
authorizer: myAuthorizer,
authorizeAsync: true,
challenge: true,
});

41
server/check-version.js

@ -0,0 +1,41 @@
const { setSetting } = require("./util-server");
const axios = require("axios");
exports.version = require("../package.json").version;
exports.latestVersion = null;
let interval;
exports.startInterval = () => {
let check = async () => {
try {
const res = await axios.get("https://uptime.kuma.pet/version");
// For debug
if (process.env.TEST_CHECK_VERSION === "1") {
res.data.slow = "1000.0.0";
}
if (res.data.slow) {
exports.latestVersion = res.data.slow;
}
} 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;

100
server/client.js

@ -0,0 +1,100 @@
/*
* For Client Socket
*/
const { TimeLogger } = require("../src/util");
const { R } = require("redbean-node");
const { io } = require("./server");
const { setting } = require("./util-server");
const checkVersion = require("./check-version");
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);
}
}
async function sendInfo(socket) {
socket.emit("info", {
version: checkVersion.version,
latestVersion: checkVersion.latestVersion,
primaryBaseURL: await setting("primaryBaseURL")
});
}
module.exports = {
sendNotificationList,
sendImportantHeartbeatList,
sendHeartbeatList,
sendInfo
};

7
server/config.js

@ -0,0 +1,7 @@
const args = require("args-parser")(process.argv);
const demoMode = args["demo"] || false;
module.exports = {
args,
demoMode
};

392
server/database.js

@ -0,0 +1,392 @@
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,
"patch-monitor-push_token.sql": true,
"patch-http-monitor-method-body-and-headers.sql": true,
"patch-2fa-invalidate-used-token.sql": true,
"patch-notification_sent_history.sql": true,
}
/**
* The final 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");
await R.exec("PRAGMA auto_vacuum = FULL");
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 patch not needed");
} 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 issue patching the database");
console.error("Please submit a bug report if you still encounter the problem after restart: https://github.com/louislam/uptime-kuma/issues");
this.restore();
process.exit(1);
}
}
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 issue patching the database");
console.error("Please submit the bug report if you still encounter the problem after restart: https://github.com/louislam/uptime-kuma/issues");
this.restore();
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 + " was 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 the database");
while (true) {
Database.noReject = true;
await R.close();
await sleep(2000);
if (Database.noReject) {
break;
} else {
console.log("Waiting to close the database");
}
}
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("Backing up the database");
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("Patching the database 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");
}
}
static getSize() {
debug("Database.getSize()");
let stats = fs.statSync(Database.path);
debug(stats);
return stats.size;
}
static async shrink() {
await R.exec("VACUUM");
}
}
module.exports = Database;

57
server/image-data-uri.js

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

31
server/jobs.js

@ -0,0 +1,31 @@
const path = require("path");
const Bree = require("bree");
const { SHARE_ENV } = require("worker_threads");
const jobs = [
{
name: "clear-old-data",
interval: "at 03:14",
},
];
const initBackgroundJobs = function (args) {
const bree = new Bree({
root: path.resolve("server", "jobs"),
jobs,
worker: {
env: SHARE_ENV,
workerData: args,
},
workerMessageHandler: (message) => {
console.log("[Background Job]:", message);
}
});
bree.start();
return bree;
};
module.exports = {
initBackgroundJobs
};

40
server/jobs/clear-old-data.js

@ -0,0 +1,40 @@
const { log, exit, connectDb } = require("./util-worker");
const { R } = require("redbean-node");
const { setSetting, setting } = require("../util-server");
const DEFAULT_KEEP_PERIOD = 180;
(async () => {
await connectDb();
let period = await setting("keepDataPeriodDays");
// Set Default Period
if (period == null) {
await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
period = DEFAULT_KEEP_PERIOD;
}
// Try parse setting
let parsedPeriod;
try {
parsedPeriod = parseInt(period);
} catch (_) {
log("Failed to parse setting, resetting to default..");
await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general");
parsedPeriod = DEFAULT_KEEP_PERIOD;
}
log(`Clearing Data older than ${parsedPeriod} days...`);
try {
await R.exec(
"DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ",
[parsedPeriod]
);
} catch (e) {
log(`Failed to clear old data: ${e.message}`);
}
exit();
})();

39
server/jobs/util-worker.js

@ -0,0 +1,39 @@
const { parentPort, workerData } = require("worker_threads");
const Database = require("../database");
const path = require("path");
const log = function (any) {
if (parentPort) {
parentPort.postMessage(any);
}
};
const exit = function (error) {
if (error && error != 0) {
process.exit(error);
} else {
if (parentPort) {
parentPort.postMessage("done");
} else {
process.exit(0);
}
}
};
const connectDb = async function () {
const dbPath = path.join(
process.env.DATA_DIR || workerData["data-dir"] || "./data/"
);
Database.init({
"data-dir": dbPath,
});
await Database.connect();
};
module.exports = {
log,
exit,
connectDb,
};

34
server/model/group.js

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

23
server/model/heartbeat.js

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

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

687
server/model/monitor.js

@ -1,170 +1,519 @@
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, setting, errorLog } = require("../util-server");
const { R } = require("redbean-node");
const { BeanModel } = require("redbean-node/dist/bean-model");
const { Notification } = require("../notification");
const { demoMode } = require("../config");
const version = require("../../package.json").version;
const apicache = require("../modules/apicache");
/**
* 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,
method: this.method,
body: this.body,
headers: this.headers,
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,
pushToken: this.pushToken,
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, {
headers: { 'User-Agent':'Uptime-Kuma' }
})
bean.msg = `${res.status} - ${res.statusText}`
debug(`[${this.name}] Prepare Options for axios`);
const options = {
url: this.url,
method: (this.method || "get").toLowerCase(),
...(this.body ? { data: JSON.parse(this.body) } : {}),
timeout: this.interval * 1000 * 0.8,
headers: {
"Accept": "*/*",
"User-Agent": "Uptime-Kuma/" + version,
...(this.headers ? JSON.parse(this.headers) : {}),
},
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());
},
};
debug(`[${this.name}] Axios Request`);
let res = await axios.request(options);
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:") {
debug(`[${this.name}] Check cert`);
try {
let tlsInfoObject = checkCertificate(res);
tlsInfo = await this.updateTlsInfo(tlsInfoObject);
if (!this.getIgnoreTls()) {
debug(`[${this.name}] call sendCertNotification`);
await this.sendCertNotification(tlsInfoObject);
}
} catch (e) {
if (e.message !== "No TLS certificate in response") {
console.error(e.message);
}
}
}
if (process.env.TIMELOGGER === "1") {
debug("Cert Info Query Time: " + (dayjs().valueOf() - certInfoStartTime) + "ms");
}
if (process.env.UPTIME_KUMA_LOG_RESPONSE_BODY_MONITOR_ID == this.id) {
console.log(res.data);
}
if (this.type === "http") {
bean.status = 1;
bean.status = UP;
} else {
let data = res.data;
// Convert to string for object/array
if (typeof data !== "string") {
data = JSON.stringify(data)
data = JSON.stringify(data);
}
if (data.includes(this.keyword)) {
bean.msg += ", keyword is found"
bean.status = 1;
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 = "";
} catch (error) {
bean.msg = error.message;
}
let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.dns_resolve_type);
bean.ping = dayjs().valueOf() - startTime;
// Mark as important if status changed
if (! previousBeat || previousBeat.status !== bean.status) {
bean.important = true;
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);
}
// 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
])
if (this.dnsLastResult !== dnsMessage) {
R.exec("UPDATE `monitor` SET dns_last_result = ? WHERE id = ? ", [
dnsMessage,
this.id
]);
}
bean.msg = dnsMessage;
bean.status = UP;
} else if (this.type === "push") { // Type: Push
const time = R.isoDateTime(dayjs.utc().subtract(this.interval, "second"));
let heartbeatCount = await R.count("heartbeat", " monitor_id = ? AND time > ? ", [
this.id,
time
]);
debug("heartbeatCount" + heartbeatCount + " " + time);
if (heartbeatCount <= 0) {
throw new Error("No heartbeat in the time window");
} else {
// No need to insert successful heartbeat for push type, so end here
retries = 0;
this.heartbeatInterval = setTimeout(beat, this.interval * 1000);
return;
}
} else if (this.type === "steam") {
const steamApiUrl = "https://api.steampowered.com/IGameServersService/GetServerList/v1/";
const steamAPIKey = await setting("steamAPIKey");
const filter = `addr\\${this.hostname}:${this.port}`;
if (!steamAPIKey) {
throw new Error("Steam API Key not found");
}
let res = await axios.get(steamApiUrl, {
timeout: this.interval * 1000 * 0.8,
headers: {
"Accept": "*/*",
"User-Agent": "Uptime-Kuma/" + version,
},
httpsAgent: new https.Agent({
maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940)
rejectUnauthorized: ! this.getIgnoreTls(),
}),
maxRedirects: this.maxredirects,
validateStatus: (status) => {
return checkStatusCode(status, this.getAcceptedStatuscodes());
},
params: {
filter: filter,
key: steamAPIKey,
}
});
let promiseList = [];
if (res.data.response && res.data.response.servers && res.data.response.servers.length > 0) {
bean.status = UP;
bean.msg = res.data.response.servers[0].name;
let text;
if (bean.status === 1) {
text = "✅ Up"
try {
bean.ping = await ping(this.hostname);
} catch (_) { }
} else {
text = "🔴 Down"
throw new Error("Server not found on Steam");
}
let msg = `[${this.name}] [${text}] ${bean.msg}`;
} else {
bean.msg = "Unknown Monitor Type";
bean.status = PENDING;
}
if (this.isUpsideDown()) {
bean.status = flipStatus(bean.status);
for(let notification of notificationList) {
promiseList.push(Notification.send(JSON.parse(notification.config), msg, await this.toJSON(), bean.toJSON()));
if (bean.status === DOWN) {
throw new Error("Flip UP to DOWN");
}
}
retries = 0;
await Promise.all(promiseList);
} 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;
}
}
let beatInterval = this.interval;
debug(`[${this.name}] Check isImportant`);
let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat?.status, bean.status);
// Mark as important if status changed, ignore pending pings,
// Don't notify if disrupted changes to up
if (isImportant) {
bean.important = true;
debug(`[${this.name}] sendNotification`);
await Monitor.sendNotification(isFirstBeat, this, bean);
// Clear Status Page Cache
debug(`[${this.name}] apicache clear`);
apicache.clear();
} else {
bean.important = false;
}
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}`);
}
debug(`[${this.name}] Send to socket`);
io.to(this.user_id).emit("heartbeat", bean.toJSON());
Monitor.sendStats(io, this.id, this.user_id);
debug(`[${this.name}] Store`);
await R.store(bean);
await R.store(bean)
Monitor.sendStats(io, this.id, this.user_id)
debug(`[${this.name}] prometheus.update`);
prometheus.update(bean, tlsInfo);
previousBeat = bean;
}
beat();
this.heartbeatInterval = setInterval(beat, this.interval * 1000);
if (! this.isStop) {
if (demoMode) {
if (beatInterval < 20) {
console.log("beat interval too low, reset to 20s");
beatInterval = 20;
}
}
debug(`[${this.name}] SetTimeout for next check.`);
this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000);
} else {
console.log(`[${this.name}] isStop = true, no next check.`);
}
};
const safeBeat = async () => {
try {
await beat();
} catch (e) {
console.trace(e);
errorLog(e, false);
console.error("Please report to https://github.com/louislam/uptime-kuma/issues");
if (! this.isStop) {
console.log("Try to restart the monitor");
this.heartbeatInterval = setTimeout(safeBeat, this.interval * 1000);
}
}
};
// Delay Push Type
if (this.type === "push") {
setTimeout(() => {
safeBeat();
}, this.interval * 1000);
} else {
safeBeat();
}
}
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;
} else {
// Clear sent history if the cert changed.
try {
let oldCertInfo = JSON.parse(tls_info_bean.info_json);
let isValidObjects = oldCertInfo && oldCertInfo.certInfo && checkCertificateResult && checkCertificateResult.certInfo;
if (isValidObjects) {
if (oldCertInfo.certInfo.fingerprint256 !== checkCertificateResult.certInfo.fingerprint256) {
debug("Resetting sent_history");
await R.exec("DELETE FROM notification_sent_history WHERE type = 'certificate' AND monitor_id = ?", [
this.id
]);
} else {
debug("No need to reset sent_history");
debug(oldCertInfo.certInfo.fingerprint256);
debug(checkCertificateResult.certInfo.fingerprint256);
}
} else {
debug("Not valid object");
}
} catch (e) { }
}
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");
}
}
/**
@ -172,6 +521,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
@ -179,75 +530,205 @@ 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;
let heartbeatList = await R.getAll(`
SELECT duration, time, status
static async calcUptime(duration, monitorID) {
const timeLogger = new TimeLogger();
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 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;
}
}
// 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 ]));
total += value;
if (row.status === 0) {
downtime += value;
}
if (status === UP) {
uptime = 1;
}
}
uptime = (total - downtime) / total;
return uptime;
}
if (uptime < 0) {
uptime = 0;
/**
* 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);
}
static isImportantBeat(isFirstBeat, previousBeatStatus, currentBeatStatus) {
// * ? -> 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 ||
(previousBeatStatus === UP && currentBeatStatus === DOWN) ||
(previousBeatStatus === DOWN && currentBeatStatus === UP) ||
(previousBeatStatus === PENDING && currentBeatStatus === DOWN);
return isImportant;
}
static async sendNotification(isFirstBeat, monitor, bean) {
if (!isFirstBeat || bean.status === DOWN) {
const notificationList = await Monitor.getNotificationList(monitor);
let text;
if (bean.status === UP) {
text = "✅ Up";
} else {
text = "🔴 Down";
}
let msg = `[${monitor.name}] [${text}] ${bean.msg}`;
for (let notification of notificationList) {
try {
await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(), bean.toJSON());
} catch (e) {
console.error("Cannot send notification to " + notification.name);
console.log(e);
}
}
}
}
static async getNotificationList(monitor) {
let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [
monitor.id,
]);
return notificationList;
}
async sendCertNotification(tlsInfoObject) {
if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) {
const notificationList = await Monitor.getNotificationList(this);
io.to(userID).emit("uptime", monitorID, duration, uptime);
debug("call sendCertNotificationByTargetDays");
await this.sendCertNotificationByTargetDays(tlsInfoObject.certInfo.daysRemaining, 21, notificationList);
await this.sendCertNotificationByTargetDays(tlsInfoObject.certInfo.daysRemaining, 14, notificationList);
await this.sendCertNotificationByTargetDays(tlsInfoObject.certInfo.daysRemaining, 7, notificationList);
}
}
async sendCertNotificationByTargetDays(daysRemaining, targetDays, notificationList) {
if (daysRemaining > targetDays) {
debug(`No need to send cert notification. ${daysRemaining} > ${targetDays}`);
return;
}
if (notificationList.length > 0) {
let row = await R.getRow("SELECT * FROM notification_sent_history WHERE type = ? AND monitor_id = ? AND days = ?", [
"certificate",
this.id,
targetDays,
]);
// Sent already, no need to send again
if (row) {
debug("Sent already, no need to send again");
return;
}
let sent = false;
debug("Send certificate notification");
for (let notification of notificationList) {
try {
debug("Sending to " + notification.name);
await Notification.send(JSON.parse(notification.config), `[${this.name}][${this.url}] Certificate will be expired in ${daysRemaining} days`);
sent = true;
} catch (e) {
console.error("Cannot send cert notification to " + notification.name);
console.error(e);
}
}
if (sent) {
await R.exec("INSERT INTO notification_sent_history (type, monitor_id, days) VALUES(?, ?, ?)", [
"certificate",
this.id,
targetDays,
]);
}
} else {
debug("No notification, no need to send cert notification");
}
}
}

13
server/model/tag.js

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

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

749
server/modules/apicache/apicache.js

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

14
server/modules/apicache/index.js

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

59
server/modules/apicache/memory-cache.js

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

108
server/notification-providers/aliyun-sms.js

@ -0,0 +1,108 @@
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
const { default: axios } = require("axios");
const Crypto = require("crypto");
const qs = require("qs");
class AliyunSMS extends NotificationProvider {
name = "AliyunSMS";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
try {
if (heartbeatJSON != null) {
let msgBody = JSON.stringify({
name: monitorJSON["name"],
time: heartbeatJSON["time"],
status: this.statusToString(heartbeatJSON["status"]),
msg: heartbeatJSON["msg"],
});
if (this.sendSms(notification, msgBody)) {
return okMsg;
}
} else {
let msgBody = JSON.stringify({
name: "",
time: "",
status: "",
msg: msg,
});
if (this.sendSms(notification, msgBody)) {
return okMsg;
}
}
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
async sendSms(notification, msgbody) {
let params = {
PhoneNumbers: notification.phonenumber,
TemplateCode: notification.templateCode,
SignName: notification.signName,
TemplateParam: msgbody,
AccessKeyId: notification.accessKeyId,
Format: "JSON",
SignatureMethod: "HMAC-SHA1",
SignatureVersion: "1.0",
SignatureNonce: Math.random().toString(),
Timestamp: new Date().toISOString(),
Action: "SendSms",
Version: "2017-05-25",
};
params.Signature = this.sign(params, notification.secretAccessKey);
let config = {
method: "POST",
url: "http://dysmsapi.aliyuncs.com/",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
data: qs.stringify(params),
};
let result = await axios(config);
if (result.data.Message == "OK") {
return true;
}
return false;
}
/** Aliyun request sign */
sign(param, AccessKeySecret) {
let param2 = {};
let data = [];
let oa = Object.keys(param).sort();
for (let i = 0; i < oa.length; i++) {
let key = oa[i];
param2[key] = param[key];
}
for (let key in param2) {
data.push(`${encodeURIComponent(key)}=${encodeURIComponent(param2[key])}`);
}
let StringToSign = `POST&${encodeURIComponent("/")}&${encodeURIComponent(data.join("&"))}`;
return Crypto
.createHmac("sha1", `${AccessKeySecret}&`)
.update(Buffer.from(StringToSign))
.digest("base64");
}
statusToString(status) {
switch (status) {
case DOWN:
return "DOWN";
case UP:
return "UP";
default:
return status;
}
}
}
module.exports = AliyunSMS;

26
server/notification-providers/apprise.js

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

89
server/notification-providers/bark.js

@ -0,0 +1,89 @@
//
// bark.js
// UptimeKuma
//
// Created by Lakr Aream on 2021/10/24.
// Copyright © 2021 Lakr Aream. All rights reserved.
//
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
const { default: axios } = require("axios");
// bark is an APN bridge that sends notifications to Apple devices.
const barkNotificationGroup = "UptimeKuma";
const barkNotificationAvatar = "https://github.com/louislam/uptime-kuma/raw/master/public/icon.png";
const barkNotificationSound = "telegraph";
const successMessage = "Successes!";
class Bark extends NotificationProvider {
name = "Bark";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
try {
var barkEndpoint = notification.barkEndpoint;
// check if the endpoint has a "/" suffix, if so, delete it first
if (barkEndpoint.endsWith("/")) {
barkEndpoint = barkEndpoint.substring(0, barkEndpoint.length - 1);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == UP) {
let title = "UptimeKuma Monitor Up";
return await this.postNotification(title, msg, barkEndpoint);
}
if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] == DOWN) {
let title = "UptimeKuma Monitor Down";
return await this.postNotification(title, msg, barkEndpoint);
}
if (msg != null) {
let title = "UptimeKuma Message";
return await this.postNotification(title, msg, barkEndpoint);
}
} catch (error) {
throw error;
}
}
// add additional parameter for better on device styles (iOS 15 optimized)
appendAdditionalParameters(postUrl) {
// grouping all our notifications
postUrl += "?group=" + barkNotificationGroup;
// set icon to uptime kuma icon, 11kb should be fine
postUrl += "&icon=" + barkNotificationAvatar;
// picked a sound, this should follow system's mute status when arrival
postUrl += "&sound=" + barkNotificationSound;
return postUrl;
}
// thrown if failed to check result, result code should be in range 2xx
checkResult(result) {
if (result.status == null) {
throw new Error("Bark notification failed with invalid response!");
}
if (result.status < 200 || result.status >= 300) {
throw new Error("Bark notification failed with status code " + result.status);
}
}
async postNotification(title, subtitle, endpoint) {
// url encode title and subtitle
title = encodeURIComponent(title);
subtitle = encodeURIComponent(subtitle);
let postUrl = endpoint + "/" + title + "/" + subtitle;
postUrl = this.appendAdditionalParameters(postUrl);
let result = await axios.get(postUrl);
this.checkResult(result);
if (result.statusText != null) {
return "Bark notification succeed: " + result.statusText;
}
// because returned in range 200 ..< 300
return successMessage;
}
}
module.exports = Bark;

42
server/notification-providers/clicksendsms.js

@ -0,0 +1,42 @@
const NotificationProvider = require("./notification-provider");
const axios = require("axios");
class ClickSendSMS extends NotificationProvider {
name = "clicksendsms";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
try {
console.log({ notification });
let config = {
headers: {
"Content-Type": "application/json",
"Authorization": "Basic " + Buffer.from(notification.clicksendsmsLogin + ":" + notification.clicksendsmsPassword).toString('base64'),
"Accept": "text/json",
}
};
let data = {
messages: [
{
"body": msg.replace(/[^\x00-\x7F]/g, ""),
"to": notification.clicksendsmsToNumber,
"source": "uptime-kuma",
"from": notification.clicksendsmsSenderName,
}
]
};
let resp = await axios.post("https://rest.clicksend.com/v3/sms/send", data, config);
if (resp.data.data.messages[0].status !== "SUCCESS") {
let error = "Something gone wrong. Api returned " + resp.data.data.messages[0].status + ".";
this.throwGeneralAxiosError(error);
}
return okMsg;
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
}
module.exports = ClickSendSMS;

79
server/notification-providers/dingding.js

@ -0,0 +1,79 @@
const NotificationProvider = require("./notification-provider");
const { DOWN, UP } = require("../../src/util");
const { default: axios } = require("axios");
const Crypto = require("crypto");
class DingDing extends NotificationProvider {
name = "DingDing";
async send(notification, msg, monitorJSON = null, heartbeatJSON = null) {
let okMsg = "Sent Successfully.";
try {
if (heartbeatJSON != null) {
let params = {
msgtype: "markdown",
markdown: {
title: monitorJSON["name"],
text: `## [${this.statusToString(heartbeatJSON["status"])}] \n > ${heartbeatJSON["msg"]} \n > Time(UTC):${heartbeatJSON["time"]}`,
}
};
if (this.sendToDingDing(notification, params)) {
return okMsg;
}
} else {
let params = {
msgtype: "text",
text: {
content: msg
}
};
if (this.sendToDingDing(notification, params)) {
return okMsg;
}
}
} catch (error) {
this.throwGeneralAxiosError(error);
}
}
async sendToDingDing(notification, params) {
let timestamp = Date.now();
let config = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
url: `${notification.webHookUrl}&timestamp=${timestamp}&sign=${encodeURIComponent(this.sign(timestamp, notification.secretKey))}`,
data: JSON.stringify(params),
};
let result = await axios(config);
if (result.data.errmsg == "ok") {
return true;
}
return false;
}
/** DingDing sign */
sign(timestamp, secretKey) {
return Crypto
.createHmac("sha256", Buffer.from(secretKey, "utf8"))
.update(Buffer.from(`${timestamp}\n${secretKey}`, "utf8"))
.digest("base64");
}
statusToString(status) {
switch (status) {
case DOWN:
return "DOWN";
case UP:
return "UP";
default:
return status;
}
}
}
module.exports = DingDing;

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

Loading…
Cancel
Save