Compare commits

...

449 Commits

Author SHA1 Message Date
Simon Larsen
ba463f44b1 Merge pull request #563 from Kashalls/fifth
value needs to be set with pattern being version
2023-07-29 16:10:11 +01:00
Jordan Jones
a36d0e4258 value needs to be set with pattern being version 2023-07-29 08:07:44 -07:00
Simon Larsen
6a9a535365 Merge pull request #561 from Kashalls/fourthtime
Outdated Docs Will Be My Downfall
2023-07-29 15:41:30 +01:00
Jordan Jones
1b5ba60703 invalid type 2023-07-29 07:31:11 -07:00
Simon Larsen
5ac205ddc0 Merge pull request #558 from Kashalls/thirdtimesthecharm
Thirdtimesthecharm
2023-07-29 14:57:21 +01:00
Jordan Jones
668830063f whoops 2023-07-29 06:50:55 -07:00
Jordan Jones
ed06cef3b1 chore: replace version build args which isnt parsing right 2023-07-29 06:49:37 -07:00
Jordan Jones
6c8154d94b chore: add docker labels 2023-07-29 06:46:57 -07:00
Simon Larsen
ee99f3f558 add docs of ghcr to docker compose file 2023-07-29 14:20:13 +01:00
Simon Larsen
30c9b8ab90 Merge pull request #557 from Kashalls/fix-ghcr
feat: fix build numbers and merge test builds
2023-07-29 13:26:20 +01:00
Jordan Jones
db7e862a31 feat: fix build numbers and merge test builds 2023-07-29 05:23:18 -07:00
Simon Larsen
3b3a6f35f1 Merge pull request #556 from Kashalls/ghcr.io
Add support for ghcr.io as a mirror
2023-07-29 12:29:32 +01:00
Jordan Jones
e3ccf48251 chore: support deploying test releases 2023-07-29 04:26:09 -07:00
Jordan Jones
f01b6f1944 chore: re-add prerun for templating 2023-07-29 04:24:02 -07:00
Kashalls
832e88f288 chore: remove non-modifying raw commands and weirdly managed qemu emulator? 2023-07-29 03:46:59 -07:00
Kashalls
9ceb2d4fc4 feat: add support for building and pushing to ghcr.io 2023-07-29 03:44:22 -07:00
Simon Larsen
3b0c9ddaeb remove ghcr 2023-07-29 10:30:48 +01:00
Simon Larsen
c6df51aae3 fix push to github cr 2023-07-29 10:08:12 +01:00
Simon Larsen
606e8d8349 fix github token 2023-07-28 19:00:28 +01:00
Simon Larsen
b0ba865ea2 push images to ghcr.io 2023-07-28 17:54:29 +01:00
Simon Larsen
d48f86970c fix title length 2023-07-27 15:55:33 +01:00
Simon Larsen
44be11adbb fixc workflow json seralization issue 2023-07-27 13:45:51 +01:00
Simon Larsen
e0965390b9 add oneuptime automation 2023-07-27 13:03:29 +01:00
Simon Larsen
75a9763eb1 add last index to workflow 2023-07-27 10:36:50 +01:00
Simon Larsen
952865298c fix billing payment method perms 2023-07-26 18:08:45 +01:00
Simon Larsen
eb90e19d12 increase char limit on title 2023-07-26 16:49:11 +01:00
Simon Larsen
7f81ae4009 fix common server tests 2023-07-26 12:48:54 +01:00
Simon Larsen
cd8f090a5e add HTTP Head request 2023-07-26 12:38:00 +01:00
Simon Larsen
35f483c650 add type to result 2023-07-26 11:06:39 +01:00
Simon Larsen
8238ce4c5d fix json serilization issue 2023-07-26 11:01:37 +01:00
Simon Larsen
39ab39b024 make workflow code more readable 2023-07-26 10:44:39 +01:00
Simon Larsen
7e3f911225 fix json serialization issue with workflows 2023-07-25 15:12:18 +01:00
Simon Larsen
8a8f975369 fix blank page issues 2023-07-25 11:10:27 +01:00
Simon Larsen
bef9411dcc Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-24 21:52:38 +01:00
Simon Larsen
e861f4b53c update readme in config.example 2023-07-24 21:52:19 +01:00
Simon Larsen
757a66bafa add readme in config. 2023-07-24 21:47:54 +01:00
Simon Larsen
217ec6bcfc change default username to postgres 2023-07-24 21:26:20 +01:00
Simon Larsen
dd4f518a79 Merge branch 'master' into release 2023-07-24 21:06:46 +01:00
Simon Larsen
c87e1513d9 Merge pull request #552 from ckd/typo-emptystate
rename EmnptyState component
2023-07-24 20:51:56 +01:00
Carl Downing
b4e4eb7043 rename EnmptyState component 2023-07-24 12:20:47 -07:00
Simon Larsen
26a4ba606e fix issues with summary detail. 2023-07-24 20:02:20 +01:00
Simon Larsen
88cf88d125 Merge pull request #551 from ckd/more-copy-edits
More copy edits
2023-07-24 17:47:15 +01:00
Carl Downing
499dec5b95 here are 2023-07-24 09:43:59 -07:00
Carl Downing
9a107188aa grammar/copy 2023-07-24 09:41:03 -07:00
Carl Downing
6822dc4f3e request 2023-07-24 09:39:17 -07:00
Carl Downing
6977aec52d requests 2023-07-24 09:38:15 -07:00
Carl Downing
c9a3c23302 correct role descriptions 2023-07-24 09:37:47 -07:00
Simon Larsen
066f055a74 Merge pull request #550 from ckd/copy-edits
Copy edits
2023-07-24 17:15:06 +01:00
Carl Downing
1da7b9747f renaming hasReosurce 2023-07-24 09:08:08 -07:00
Carl Downing
e29af13b73 renaming getReosurceDictionaryByPath 2023-07-24 09:06:55 -07:00
Carl Downing
3e4074ef4b resources 2023-07-24 09:04:07 -07:00
Carl Downing
0f8330d110 copyedit 2023-07-24 08:43:43 -07:00
Carl Downing
4cba9d6042 open source 2023-07-24 08:41:47 -07:00
Carl Downing
556283e7f7 copyedit 2023-07-24 08:40:42 -07:00
Carl Downing
696a3b5fee grammar 2023-07-24 08:38:17 -07:00
Carl Downing
cdd2f241c7 grammar 2023-07-24 08:38:02 -07:00
Carl Downing
2a9978b539 grammar 2023-07-24 08:36:34 -07:00
Simon Larsen
e1917f1fd7 Merge branch 'master' into release 2023-07-24 16:15:42 +01:00
Simon Larsen
cb547790cf fix createdAt null check 2023-07-24 16:15:32 +01:00
Simon Larsen
c754101194 Merge pull request #547 from andersmmg/spelling-fix
Fix misspelled "propogate"
2023-07-24 10:35:41 +01:00
Simon Larsen
a1b772bda1 Merge pull request #548 from ckd/spelling-corrections
Spelling corrections
2023-07-24 10:35:21 +01:00
Carl Downing
a0e4b6b5c7 typos 2023-07-23 21:14:07 -07:00
Carl Downing
02cb4474a3 fix URL typo 2023-07-23 21:01:09 -07:00
Carl Downing
2db09a3aba consistent punctuation 2023-07-23 21:00:27 -07:00
Carl Downing
e09efd5917 consistent punctuation 2023-07-23 20:59:49 -07:00
Carl Downing
b45a47e167 consistent punctuation 2023-07-23 20:56:22 -07:00
Carl Downing
fab4be14dc on-call 2023-07-23 20:54:16 -07:00
Carl Downing
b717f0e09e grammar 2023-07-23 20:52:21 -07:00
Carl Downing
89fc67831c typo: integrate 2023-07-23 20:50:43 -07:00
Joshua Anderson
a504ac95d8 Fix misspelled "propogate" 2023-07-23 20:34:00 -06:00
Simon Larsen
a4f2206c83 Merge branch 'master' into release 2023-07-22 18:51:35 +01:00
Simon Larsen
271535d89f add env to gitignore 2023-07-22 18:51:21 +01:00
Simon Larsen
13f0723405 Merge pull request #546 from OneUptime/notification-settings
Notification settings
2023-07-22 18:50:01 +01:00
Simon Larsen
2159332317 fix fmt 2023-07-22 18:48:32 +01:00
Simon Larsen
3757ecb104 fix incidentservice 2023-07-22 18:33:45 +01:00
Simon Larsen
a40986d51b fix env in dev 2023-07-22 18:14:00 +01:00
Simon Larsen
d5aa9529fa fix docker compose files 2023-07-22 17:57:10 +01:00
Simon Larsen
edc7362fcd fix env in docker compose file for dev 2023-07-22 17:45:12 +01:00
Simon Larsen
e9de7fae51 fix env in docker compose for dev 2023-07-22 17:40:23 +01:00
Simon Larsen
8877536c14 fix fmt 2023-07-22 17:33:22 +01:00
Simon Larsen
5f0be6298c fix fmt 2023-07-22 17:31:57 +01:00
Simon Larsen
3d533db7c0 fix docker files for UI containers 2023-07-22 17:03:13 +01:00
Simon Larsen
46b14a4792 fix send email to subscribers 2023-07-22 16:22:21 +01:00
Simon Larsen
a0b203d9b8 fix notification events 2023-07-22 16:13:32 +01:00
Simon Larsen
b55b20a55f remove global config service 2023-07-22 16:09:51 +01:00
Simon Larsen
b91104e7bd fix compile err 2023-07-22 16:00:51 +01:00
Simon Larsen
478b4dc381 add base servicve 2023-07-22 15:33:24 +01:00
Simon Larsen
8d7c88d4d0 fix filters 2023-07-22 14:46:31 +01:00
Simon Larsen
9c35c26558 add workflow id to logs 2023-07-22 14:42:41 +01:00
Simon Larsen
16166a70f8 fix docker compose 2023-07-22 14:35:31 +01:00
Simon Larsen
42b80bab3c fix email log 2023-07-22 14:33:50 +01:00
Simon Larsen
2724f4eeed add mailservice 2023-07-22 14:14:54 +01:00
Simon Larsen
b6f67f8faa add logging to mailservice. 2023-07-22 14:13:40 +01:00
Simon Larsen
a0bfa75e55 fix send email to subscribers 2023-07-22 13:51:40 +01:00
Simon Larsen
1e0b19efd4 fix mail resources 2023-07-22 13:36:02 +01:00
Simon Larsen
e83d63c07e add more alerts to scheduled maintenance 2023-07-21 17:23:30 +01:00
Simon Larsen
7eb0b79d7b add email logs in project settings 2023-07-21 17:10:46 +01:00
Simon Larsen
2156c8f5d5 add notificatios to state changes 2023-07-21 16:52:25 +01:00
Simon Larsen
9564e57208 add message send service 2023-07-21 16:43:17 +01:00
Simon Larsen
2ba91d6ddf rename api 2023-07-21 14:18:49 +01:00
Simon Larsen
668c88db52 fix lint 2023-07-21 14:17:39 +01:00
Simon Larsen
e4faa3c995 update routemap 2023-07-21 14:15:59 +01:00
Simon Larsen
d86f3a0a33 notification log -> on call log 2023-07-21 14:15:33 +01:00
Simon Larsen
4dda09b406 fix fmt 2023-07-21 14:05:53 +01:00
Simon Larsen
ef605f1248 remove notification settings when the user is removed from the projct 2023-07-21 14:01:32 +01:00
Simon Larsen
632365da7f rename files 2023-07-21 13:48:35 +01:00
Simon Larsen
6ca3d003f7 rename files 2023-07-21 13:48:30 +01:00
Simon Larsen
889b6e00c4 add unsubscribe help text 2023-07-21 13:39:38 +01:00
Simon Larsen
dfa8591562 add unsubscribe help text 2023-07-21 13:39:32 +01:00
Simon Larsen
85d073f110 add migration job 2023-07-21 13:33:53 +01:00
Simon Larsen
55f6faaa60 fix UI issues 2023-07-21 13:23:34 +01:00
Simon Larsen
6939ee1f0d make env work in development. 2023-07-21 12:09:46 +01:00
Simon Larsen
316ef6ff53 add settings model 2023-07-20 20:28:47 +01:00
Simon Larsen
9fe2395796 remove comment 2023-07-20 18:58:48 +01:00
Simon Larsen
7b2a31ef96 remove overflow scroll 2023-07-20 14:14:03 +01:00
Simon Larsen
7971bb2abb Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-20 11:24:17 +01:00
Simon Larsen
5eacc2a18e bake template into nginx image 2023-07-20 11:24:01 +01:00
Simon Larsen
70d18ba49e Merge pull request #545 from OneUptime/release
add read env var
2023-07-20 07:24:16 +01:00
Simon Larsen
3c9628abdb add read env var 2023-07-20 07:14:34 +01:00
Simon Larsen
9793d95b80 remove flag 2023-07-19 22:07:07 +01:00
Simon Larsen
881b190fd8 fix fmt 2023-07-19 22:06:11 +01:00
Simon Larsen
e30565bce3 Merge pull request #543 from OneUptime/dependabot/npm_and_yarn/Common/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /Common
2023-07-19 20:33:58 +01:00
Simon Larsen
f9517412e5 Merge pull request #544 from OneUptime/dependabot/npm_and_yarn/Accounts/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /Accounts
2023-07-19 20:33:53 +01:00
dependabot[bot]
ed6d2faa8d Bump word-wrap from 1.2.3 to 1.2.4 in /Accounts
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 19:33:30 +00:00
Simon Larsen
a1ce939ffc Merge pull request #534 from OneUptime/dependabot/npm_and_yarn/Dashboard/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /Dashboard
2023-07-19 20:33:20 +01:00
Simon Larsen
b34cd86f05 Merge pull request #535 from OneUptime/dependabot/npm_and_yarn/CommonServer/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /CommonServer
2023-07-19 20:33:08 +01:00
dependabot[bot]
45e752cabf Bump word-wrap from 1.2.3 to 1.2.4 in /Common
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 19:33:04 +00:00
Simon Larsen
fa89f9d1a5 Merge pull request #536 from OneUptime/dependabot/npm_and_yarn/TestServer/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /TestServer
2023-07-19 20:33:00 +01:00
Simon Larsen
9db08a9347 Merge pull request #537 from OneUptime/dependabot/npm_and_yarn/ProbeAPI/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /ProbeAPI
2023-07-19 20:32:52 +01:00
Simon Larsen
24c4d37b2c Merge pull request #538 from OneUptime/dependabot/npm_and_yarn/Model/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /Model
2023-07-19 20:32:43 +01:00
Simon Larsen
1f866ee325 Merge pull request #539 from OneUptime/dependabot/npm_and_yarn/CommonUI/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /CommonUI
2023-07-19 20:32:34 +01:00
Simon Larsen
70a0087344 Merge pull request #540 from OneUptime/dependabot/npm_and_yarn/StatusPage/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /StatusPage
2023-07-19 20:32:25 +01:00
Simon Larsen
3dea55f035 Merge pull request #541 from OneUptime/dependabot/npm_and_yarn/Scripts/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4 in /Scripts
2023-07-19 20:32:17 +01:00
Simon Larsen
f47a6e7c6b update readme 2023-07-19 20:30:18 +01:00
Simon Larsen
788e8363ef remove self signed certs generation 2023-07-19 20:29:29 +01:00
Simon Larsen
c9d1c95b38 remove ssl certs from nginx 2023-07-19 20:28:38 +01:00
Simon Larsen
b3a18d69cb add comment 2023-07-19 20:21:55 +01:00
Simon Larsen
3b9e982c35 fix nginx template 2023-07-19 20:20:31 +01:00
Simon Larsen
b28a832ba7 env var for nginx domain 2023-07-19 20:16:43 +01:00
Simon Larsen
38b96e86c3 add nginx to prod and dev docker 2023-07-19 20:02:14 +01:00
Simon Larsen
dafcd001f7 add nginx files 2023-07-19 20:00:53 +01:00
Simon Larsen
7882897466 fix typo 2023-07-19 19:47:08 +01:00
Simon Larsen
3e62082ac2 fix typo 2023-07-19 19:36:26 +01:00
Simon Larsen
e8d790925b Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-19 18:37:51 +01:00
Simon Larsen
83061b1ca8 fix typo in readme 2023-07-19 18:27:26 +01:00
Simon Larsen
554f353990 Merge pull request #542 from OneUptime/release
fix test script
2023-07-19 18:11:23 +01:00
Simon Larsen
d857de0406 fix test script 2023-07-19 18:07:33 +01:00
Simon Larsen
e4d4bbb680 expose postrges port 2023-07-19 16:34:20 +01:00
Simon Larsen
4e8631cec9 add dev readme 2023-07-19 16:33:17 +01:00
Simon Larsen
1f96504c34 package.json 2023-07-19 15:13:05 +01:00
Simon Larsen
c0153f0ecb fix docker compose files 2023-07-19 15:10:47 +01:00
Simon Larsen
42f8a90eeb add code mounts 2023-07-19 14:51:39 +01:00
Simon Larsen
090d68f4e1 add status response to link shortner 2023-07-19 14:27:41 +01:00
Simon Larsen
dcd04ddaa1 add networks 2023-07-19 14:25:00 +01:00
Simon Larsen
906438c325 refactor status check script 2023-07-19 14:21:39 +01:00
Simon Larsen
53ce3537e9 fix spaces 2023-07-19 13:06:39 +01:00
Simon Larsen
550d7f2621 fix probe config 2023-07-19 12:59:10 +01:00
Simon Larsen
b1707a28f8 add 443 port for external status apges 2023-07-19 12:54:37 +01:00
Simon Larsen
3eb15af79c update readme 2023-07-19 12:44:29 +01:00
Simon Larsen
bddd932eb8 remove sudo 2023-07-19 12:42:33 +01:00
Simon Larsen
8a73a7c7ab fix install script 2023-07-19 12:34:59 +01:00
Simon Larsen
a7b6f70ed4 remove secret generation 2023-07-19 12:29:54 +01:00
Simon Larsen
3dea88a97b add test setup 2023-07-19 12:25:50 +01:00
Simon Larsen
5728c1a18c fix test file 2023-07-19 12:16:29 +01:00
Simon Larsen
7da678e82b Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-19 12:01:20 +01:00
Simon Larsen
7b7cbbe6b8 fix config.example 2023-07-19 12:01:09 +01:00
dependabot[bot]
658b359c2c Bump word-wrap from 1.2.3 to 1.2.4 in /Scripts
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:45 +00:00
dependabot[bot]
ff9f97f095 Bump word-wrap from 1.2.3 to 1.2.4 in /StatusPage
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:35 +00:00
dependabot[bot]
558f963648 Bump word-wrap from 1.2.3 to 1.2.4 in /CommonUI
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:30 +00:00
dependabot[bot]
f5883d4840 Bump word-wrap from 1.2.3 to 1.2.4 in /Model
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:27 +00:00
dependabot[bot]
bfdecac3ba Bump word-wrap from 1.2.3 to 1.2.4 in /TestServer
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:26 +00:00
dependabot[bot]
43a765479a Bump word-wrap from 1.2.3 to 1.2.4 in /ProbeAPI
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:26 +00:00
dependabot[bot]
07b33b68ab Bump word-wrap from 1.2.3 to 1.2.4 in /CommonServer
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:24 +00:00
dependabot[bot]
e83b118904 Bump word-wrap from 1.2.3 to 1.2.4 in /Dashboard
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 10:43:22 +00:00
Nawaz Dhandala
fb798290a5 Merge pull request #529 from TobiasGrether/master
use overflow-x-scroll to stop nav bar from operlapping on mobile dashboard
2023-07-19 11:43:07 +01:00
Nawaz Dhandala
46c33b4d1e Merge pull request #533 from OneUptime/dependabot/npm_and_yarn/word-wrap-1.2.4
Bump word-wrap from 1.2.3 to 1.2.4
2023-07-19 11:42:36 +01:00
Simon Larsen
3492e7f949 Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-19 11:41:34 +01:00
Simon Larsen
5a5b861f69 expose port in local dev 2023-07-19 11:41:32 +01:00
dependabot[bot]
17938ddb3f Bump word-wrap from 1.2.3 to 1.2.4
Bumps [word-wrap](https://github.com/jonschlinkert/word-wrap) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/jonschlinkert/word-wrap/releases)
- [Commits](https://github.com/jonschlinkert/word-wrap/compare/1.2.3...1.2.4)

---
updated-dependencies:
- dependency-name: word-wrap
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-19 08:24:35 +00:00
Nawaz Dhandala
3ea065a620 Merge pull request #531 from TobiasGrether/patch-1
Add docker network to docker-compose.yml
2023-07-18 17:02:57 +01:00
Tobias Grether
2f6f8044b8 Add docker network to docker-compose.yml 2023-07-18 10:16:13 +02:00
Tobias Grether
7a17eb12dc feat: use overflow-x-scroll to stop nav bar from operlapping on mobile dashboard 2023-07-18 09:25:59 +02:00
Nawaz Dhandala
dd8d9b3e3f Merge pull request #526 from OneUptime/dependabot/npm_and_yarn/CommonServer/fast-xml-parser-and-aws-sdk/credential-providers-4.2.5
Bump fast-xml-parser and @aws-sdk/credential-providers in /CommonServer
2023-07-17 20:49:22 +01:00
Nawaz Dhandala
22fc04f06a Merge pull request #527 from TobiasGrether/master
Use docker network instead of exposing all ports manually
2023-07-17 20:44:35 +01:00
Tobias Grether
9a121ec62e feat: use docker network instead of exposing all ports manually 2023-07-17 21:39:38 +02:00
Simon Larsen
7909bc95ee bash -> source 2023-07-17 20:33:19 +01:00
Simon Larsen
cad11997f4 bash -> source 2023-07-17 20:33:08 +01:00
Simon Larsen
908a7a2695 fix script 2023-07-17 20:17:30 +01:00
Simon Larsen
d5b4bdbf6b remove env tpl 2023-07-17 20:06:01 +01:00
Simon Larsen
bc482345ce add common vars to nginx 2023-07-17 19:56:14 +01:00
Simon Larsen
a04416e7e7 add default conf file 2023-07-17 19:54:44 +01:00
Simon Larsen
a04eb341e1 add docker compose name 2023-07-17 19:50:48 +01:00
Simon Larsen
687c1bbb67 fix fmt 2023-07-17 19:47:14 +01:00
Simon Larsen
4462ee9bc2 remove company name and phone from OSS install 2023-07-17 19:46:48 +01:00
Simon Larsen
2379a6fd86 read env vars from bash 2023-07-17 19:30:10 +01:00
Simon Larsen
99462978cc edit readme 2023-07-17 17:59:15 +01:00
Simon Larsen
ae7c32a32d makr coookie accepted as false and hide the banner 2023-07-17 17:56:59 +01:00
Simon Larsen
6e4b23293f update readme to make it only docker compose 2023-07-17 17:54:58 +01:00
Simon Larsen
21a017a8ba add docs around external cname 2023-07-17 17:45:07 +01:00
Simon Larsen
5a99e66427 add debugging ports 2023-07-17 17:38:15 +01:00
Simon Larsen
786e88eef5 change protocol to http 2023-07-17 17:32:38 +01:00
Simon Larsen
bb45041dec fix probe prod file 2023-07-17 17:29:57 +01:00
Simon Larsen
0f92ba3e63 add activate 2023-07-17 17:29:13 +01:00
Simon Larsen
25b065eef4 fix common tests 2023-07-17 17:18:56 +01:00
Simon Larsen
dcd35b4686 fix env var 2023-07-17 16:09:18 +01:00
Simon Larsen
a9fc2305eb fix configure 2023-07-17 16:06:22 +01:00
Simon Larsen
7f741cec1b add docker compose file 2023-07-17 16:05:38 +01:00
Simon Larsen
c03e8f2d67 fix configure script 2023-07-17 16:03:05 +01:00
Simon Larsen
4691444545 fix preinstall script 2023-07-17 15:59:56 +01:00
Simon Larsen
970e6c4af2 fix lint. 2023-07-17 15:57:05 +01:00
Simon Larsen
31e0376e62 fix script 2023-07-17 14:30:58 +01:00
Simon Larsen
cc24dad2cd fix package.json 2023-07-17 14:30:31 +01:00
Simon Larsen
74a36c6918 fix env config 2023-07-17 13:30:20 +01:00
Simon Larsen
ab0472005e Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-17 13:28:31 +01:00
Simon Larsen
e171a8c845 fix err in docker compose 2023-07-17 13:28:29 +01:00
Simon Larsen
5de055a350 add config.example.env 2023-07-17 13:08:02 +01:00
dependabot[bot]
3c04194dfd Bump fast-xml-parser and @aws-sdk/credential-providers in /CommonServer
Bumps [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and [@aws-sdk/credential-providers](https://github.com/aws/aws-sdk-js-v3/tree/HEAD/packages/credential-providers). These dependencies needed to be updated together.

Updates `fast-xml-parser` from 4.2.4 to 4.2.5
- [Release notes](https://github.com/NaturalIntelligence/fast-xml-parser/releases)
- [Changelog](https://github.com/NaturalIntelligence/fast-xml-parser/blob/master/CHANGELOG.md)
- [Commits](https://github.com/NaturalIntelligence/fast-xml-parser/compare/v4.2.4...v4.2.5)

Updates `@aws-sdk/credential-providers` from 3.347.1 to 3.370.0
- [Release notes](https://github.com/aws/aws-sdk-js-v3/releases)
- [Changelog](https://github.com/aws/aws-sdk-js-v3/blob/main/packages/credential-providers/CHANGELOG.md)
- [Commits](https://github.com/aws/aws-sdk-js-v3/commits/v3.370.0/packages/credential-providers)

---
updated-dependencies:
- dependency-name: fast-xml-parser
  dependency-type: indirect
- dependency-name: "@aws-sdk/credential-providers"
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-17 11:50:21 +00:00
Nawaz Dhandala
aee54309d8 Merge pull request #525 from OneUptime/dependabot/npm_and_yarn/Accounts/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /Accounts
2023-07-17 12:49:11 +01:00
dependabot[bot]
5831fdfa3e Bump tough-cookie from 4.1.2 to 4.1.3 in /Accounts
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-16 21:46:47 +00:00
Nawaz Dhandala
5267cdfbeb Merge pull request #522 from OneUptime/dependabot/npm_and_yarn/Common/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /Common
2023-07-16 22:45:52 +01:00
Simon Larsen
6094b577ef Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-15 13:43:28 +01:00
Simon Larsen
b1f734166f add poorts to docker compose base 2023-07-15 11:32:30 +01:00
Simon Larsen
52060d1393 add env var to docker compose base 2023-07-15 11:28:50 +01:00
Nawaz Dhandala
9a1589259f Merge pull request #523 from OneUptime/nzdhandala-patch-1
Create IPAddress.md
2023-07-14 21:01:05 +01:00
Nawaz Dhandala
12ae9a1b74 Create IPAddress.md 2023-07-14 21:00:56 +01:00
dependabot[bot]
ed7395db70 Bump tough-cookie from 4.1.2 to 4.1.3 in /Common
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-14 17:19:43 +00:00
Nawaz Dhandala
6a63556fd2 Merge pull request #521 from OneUptime/dependabot/npm_and_yarn/CommonServer/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /CommonServer
2023-07-14 18:19:01 +01:00
Simon Larsen
4ecfce4a5d fix grammar 2023-07-13 12:34:39 +01:00
Simon Larsen
6f827a68c0 Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-13 12:29:40 +01:00
Simon Larsen
8afdf966f3 fix fmt 2023-07-13 12:29:13 +01:00
Simon Larsen
e9e5533372 fix on call page 2023-07-13 12:26:34 +01:00
Simon Larsen
e8acdad270 fix logo on status page 2023-07-13 12:08:28 +01:00
dependabot[bot]
d11116544c Bump tough-cookie from 4.1.2 to 4.1.3 in /CommonServer
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-13 09:34:58 +00:00
Nawaz Dhandala
4741028cc2 Merge pull request #518 from OneUptime/dependabot/npm_and_yarn/Playwright/semver-6.3.1
Bump semver from 6.3.0 to 6.3.1 in /Playwright
2023-07-13 10:34:16 +01:00
Nawaz Dhandala
56af44885d Merge pull request #512 from OneUptime/dependabot/npm_and_yarn/Dashboard/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /Dashboard
2023-07-13 10:34:00 +01:00
Nawaz Dhandala
cc30864ada Merge pull request #513 from OneUptime/dependabot/npm_and_yarn/CommonUI/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /CommonUI
2023-07-13 10:33:52 +01:00
Nawaz Dhandala
5291f78895 Merge pull request #517 from OneUptime/dependabot/npm_and_yarn/Accounts/semver-5.7.2
Bump semver from 5.7.1 to 5.7.2 in /Accounts
2023-07-13 10:33:47 +01:00
Nawaz Dhandala
731f4da92a Merge pull request #519 from OneUptime/dependabot/npm_and_yarn/CommonServer/semver-6.3.1
Bump semver from 6.3.0 to 6.3.1 in /CommonServer
2023-07-13 10:33:36 +01:00
Simon Larsen
da6615ad6f finish workflow page 2023-07-13 10:30:53 +01:00
Simon Larsen
251c763245 remove svg on the sides 2023-07-12 14:22:39 +01:00
Simon Larsen
ac29692485 add workflow images 2023-07-12 14:20:24 +01:00
Simon Larsen
2e0e8f6956 add workflow page 2023-07-12 13:36:13 +01:00
Simon Larsen
74e1532079 fix fmt 2023-07-12 12:15:44 +01:00
Simon Larsen
2657bca277 fix shortlinks 2023-07-12 11:53:08 +01:00
Simon Larsen
9704adba03 fix sms and calls for verification code. 2023-07-12 11:46:35 +01:00
Simon Larsen
a1960cb749 add PG_DBNAME env var 2023-07-12 11:38:40 +01:00
Simon Larsen
b288117b4f fix fmt 2023-07-12 11:03:50 +01:00
Simon Larsen
c22f3f3191 fix bug with logging on-call 2023-07-12 11:02:33 +01:00
Simon Larsen
3b4e0a8dbc add comments in timeout jobs 2023-07-12 10:24:22 +01:00
Simon Larsen
6ef9445b46 fix fmt in timeout jobs 2023-07-12 10:20:30 +01:00
Simon Larsen
55856e9ff0 add timeout jobs 2023-07-12 10:18:57 +01:00
Simon Larsen
8b8585f86c fix issues with service 2023-07-12 09:58:52 +01:00
Simon Larsen
ad427fa6b4 Merge branch 'release' 2023-07-12 09:32:01 +01:00
Simon Larsen
3d4519e2bd add https port 2023-07-12 09:31:50 +01:00
Simon Larsen
d0f0454a0c add docker base 2023-07-12 09:29:36 +01:00
Simon Larsen
e0601e75fa remove nginx docker build 2023-07-11 22:32:38 +01:00
Simon Larsen
a4951a264b add docker base 2023-07-11 22:31:38 +01:00
dependabot[bot]
b8485a1c3e Bump semver from 6.3.0 to 6.3.1 in /CommonServer
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 21:17:03 +00:00
dependabot[bot]
54b4f47b6a Bump semver from 6.3.0 to 6.3.1 in /Playwright
Bumps [semver](https://github.com/npm/node-semver) from 6.3.0 to 6.3.1.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v6.3.1/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v6.3.0...v6.3.1)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 21:16:58 +00:00
Simon Larsen
c558909fd0 remove nginx jobs 2023-07-11 22:16:09 +01:00
Simon Larsen
da3f02f855 add nginx official container 2023-07-11 22:15:34 +01:00
dependabot[bot]
f1ea93719c Bump semver from 5.7.1 to 5.7.2 in /Accounts
Bumps [semver](https://github.com/npm/node-semver) from 5.7.1 to 5.7.2.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/v5.7.2/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v5.7.1...v5.7.2)

---
updated-dependencies:
- dependency-name: semver
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-11 21:03:13 +00:00
Simon Larsen
fc59f65fca add env folder 2023-07-11 20:26:35 +01:00
Simon Larsen
bddf072511 add data folder 2023-07-11 20:22:17 +01:00
Simon Larsen
f5a4cc3c1d remove lets encrypt to make deployment simpler 2023-07-11 11:57:54 +01:00
Nawaz Dhandala
a7e1430898 Merge pull request #516 from OneUptime/on-call-fixes
fix shortlink logs
2023-07-11 09:47:27 +01:00
Simon Larsen
d0cb4b5b17 fix shortlink logs 2023-07-11 09:28:16 +01:00
Nawaz Dhandala
f5055d744e Merge pull request #515 from OneUptime/on-call-fixes
On call fixes
2023-07-10 21:31:24 +01:00
Simon Larsen
8d308b0a7c fix workflow status 2023-07-10 19:23:44 +01:00
Simon Larsen
1515cd7478 running - executing 2023-07-10 19:23:11 +01:00
Simon Larsen
604a5c0c9f Merge branch 'master' of github.com-simon:OneUptime/oneuptime 2023-07-10 08:28:43 +01:00
Simon Larsen
ba46931979 add docker jobs for link shortner 2023-07-10 08:28:23 +01:00
dependabot[bot]
7d620595d2 Bump tough-cookie from 4.1.2 to 4.1.3 in /CommonUI
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:59:16 +00:00
dependabot[bot]
d186adbbbb Bump tough-cookie from 4.1.2 to 4.1.3 in /Dashboard
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:57:56 +00:00
Nawaz Dhandala
3bc6794948 Merge pull request #511 from OneUptime/dependabot/npm_and_yarn/StatusPage/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /StatusPage
2023-07-09 20:57:20 +01:00
Nawaz Dhandala
f5e0f90e11 Merge pull request #510 from OneUptime/dependabot/npm_and_yarn/TestServer/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /TestServer
2023-07-09 20:57:12 +01:00
Nawaz Dhandala
536e0e3cf8 Merge pull request #509 from OneUptime/dependabot/npm_and_yarn/Model/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /Model
2023-07-09 20:57:04 +01:00
Nawaz Dhandala
b82c2acf67 Merge pull request #507 from OneUptime/dependabot/npm_and_yarn/ProbeAPI/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /ProbeAPI
2023-07-09 20:56:58 +01:00
Nawaz Dhandala
bd46971ad8 Merge pull request #506 from OneUptime/dependabot/npm_and_yarn/Scripts/tough-cookie-4.1.3
Bump tough-cookie from 4.1.2 to 4.1.3 in /Scripts
2023-07-09 20:56:49 +01:00
dependabot[bot]
61cbae6a3f Bump tough-cookie from 4.1.2 to 4.1.3 in /StatusPage
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:46:34 +00:00
dependabot[bot]
d9c13333ed Bump tough-cookie from 4.1.2 to 4.1.3 in /TestServer
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:46:29 +00:00
dependabot[bot]
6716339317 Bump tough-cookie from 4.1.2 to 4.1.3 in /Model
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:46:14 +00:00
Nawaz Dhandala
49b4388491 Merge pull request #508 from OneUptime/nzdhandala-patch-1
Update README.md
2023-07-09 20:45:59 +01:00
Nawaz Dhandala
6300416593 Update README.md 2023-07-09 20:45:43 +01:00
dependabot[bot]
c7aa6123b2 Bump tough-cookie from 4.1.2 to 4.1.3 in /ProbeAPI
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:45:41 +00:00
dependabot[bot]
df17c47dd4 Bump tough-cookie from 4.1.2 to 4.1.3 in /Scripts
Bumps [tough-cookie](https://github.com/salesforce/tough-cookie) from 4.1.2 to 4.1.3.
- [Release notes](https://github.com/salesforce/tough-cookie/releases)
- [Changelog](https://github.com/salesforce/tough-cookie/blob/master/CHANGELOG.md)
- [Commits](https://github.com/salesforce/tough-cookie/compare/v4.1.2...v4.1.3)

---
updated-dependencies:
- dependency-name: tough-cookie
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-07-09 19:45:35 +00:00
Nawaz Dhandala
5e8962917b Merge pull request #501 from OneUptime/on-call-duty
On call duty
2023-07-09 20:44:57 +01:00
Simon Larsen
112b72d2ed fix issues with on-call 2023-07-09 20:44:40 +01:00
Simon Larsen
3d3bf1d092 fix regex to include longer phone numbers 2023-07-09 19:49:43 +01:00
Simon Larsen
e5f7fc4cef fix domain and include za 2023-07-09 19:47:30 +01:00
Simon Larsen
bf82694b6e add sent states 2023-07-09 17:14:44 +01:00
Simon Larsen
d1fa52c8dc fix model required fields. 2023-07-09 17:06:10 +01:00
Simon Larsen
577d1dceea add resource notifictions 2023-07-09 16:31:53 +01:00
Simon Larsen
9b4e3172c3 add sidemenu 2023-07-09 15:52:20 +01:00
Simon Larsen
b7db3a42b5 underline on hover 2023-07-09 15:21:36 +01:00
Simon Larsen
a8292e5183 fix fmt 2023-07-09 15:14:22 +01:00
Simon Larsen
bf2b95fda7 fix fmt 2023-07-09 15:13:09 +01:00
Simon Larsen
3f1550096c fix sso docs 2023-07-09 15:11:01 +01:00
Simon Larsen
860beafd74 filter by severity 2023-07-09 13:39:46 +01:00
Simon Larsen
66839a01d6 fix filter 2023-07-09 13:27:14 +01:00
Simon Larsen
cf4fbdc8fc fix date filter 2023-07-09 13:19:29 +01:00
Simon Larsen
f2a1a0596d fix enum status 2023-07-09 13:04:46 +01:00
Simon Larsen
40e72a4c00 add pricing for on-call 2023-07-09 12:53:50 +01:00
Simon Larsen
30cae266b0 refactor into a table component 2023-07-08 22:43:29 +01:00
Simon Larsen
d54708b2c4 fix sidemenu style 2023-07-08 22:22:13 +01:00
Simon Larsen
f33d35a45b fix issues with oncall 2023-07-08 15:16:37 +01:00
Simon Larsen
de1f64aa6b add pricing to home 2023-07-08 14:56:46 +01:00
Simon Larsen
a325b66034 add call and sms pricing to home 2023-07-08 14:51:54 +01:00
Simon Larsen
031ed59108 refactor home project 2023-07-08 14:18:05 +01:00
Simon Larsen
8e78d74568 fix execution log view 2023-07-08 13:16:56 +01:00
Simon Larsen
1c3b462a8f add on call log ui 2023-07-07 22:14:24 +01:00
Simon Larsen
ee25e8f218 add notification timeline page. 2023-07-07 19:21:43 +01:00
Simon Larsen
573c074aef add new fields to timeline 2023-07-07 14:34:55 +01:00
Simon Larsen
53b55ac7f6 add notification logs page 2023-07-07 14:13:59 +01:00
Simon Larsen
f054b131e4 add notification logs page 2023-07-05 22:18:19 +01:00
Simon Larsen
f80ae8e806 fix infinate type 2023-07-05 21:18:48 +01:00
Simon Larsen
5464fed1a8 add workers for timelines 2023-07-05 20:20:46 +01:00
Simon Larsen
b4311d02d4 add dotdash logo 2023-07-05 09:41:15 +01:00
Simon Larsen
7778182f02 add types 2023-07-04 12:49:59 +01:00
Simon Larsen
b5fb766f3d add notification id to notification service 2023-07-04 12:42:22 +01:00
Simon Larsen
d236131171 add ack of incident 2023-07-04 12:26:49 +01:00
Simon Larsen
f88c0d5161 add call handler api 2023-07-03 22:15:17 +01:00
Simon Larsen
9eab1cd1c1 Merge branch 'master' into on-call-duty 2023-07-03 20:40:54 +01:00
Simon Larsen
a68cefd27c fix adding triggr node 2023-07-03 17:14:51 +01:00
Simon Larsen
71ce42476b add run to webhook 2023-07-03 17:07:34 +01:00
Simon Larsen
e795470ea7 add success port to webhook 2023-07-03 17:05:32 +01:00
Simon Larsen
f87f721487 add timelne service and events. 2023-07-02 22:28:37 +01:00
Simon Larsen
962c79e3dc add user notification rule 2023-07-02 13:39:51 +01:00
Simon Larsen
2ef0c9334d fix fmt 2023-07-01 13:08:50 +01:00
Simon Larsen
f18bb3a3de add url shortner 2023-07-01 12:58:59 +01:00
Simon Larsen
d724932660 link shortner 2023-07-01 12:01:54 +01:00
Simon Larsen
4de9a308bd add link shortner service 2023-07-01 11:57:53 +01:00
Simon Larsen
1760731fab add new fields in on-call-ex-log 2023-06-30 13:45:36 +01:00
Simon Larsen
88e554d26b add on call policy to incident 2023-06-30 12:32:02 +01:00
Simon Larsen
50dac60b65 fix fmt 2023-06-30 11:48:40 +01:00
Simon Larsen
c2fb75cdc5 add monitors 2023-06-30 11:27:06 +01:00
Simon Larsen
560acb7626 select on call policy 2023-06-30 10:56:01 +01:00
Simon Larsen
394571144d fix display of users and teams 2023-06-29 19:36:46 +01:00
Simon Larsen
35fef64623 add list props in table 2023-06-29 12:56:55 +01:00
Simon Larsen
fdaca5f804 fix sort order 2023-06-29 12:02:23 +01:00
Simon Larsen
716fe16487 enable drag and drop on list 2023-06-29 11:35:20 +01:00
Simon Larsen
7d63433f65 add err in findOneById 2023-06-28 13:53:10 +01:00
Simon Larsen
ea122c0e77 fix issue with fetching id. 2023-06-28 13:46:57 +01:00
Simon Larsen
f0d71bc65b fix link in on-call duty 2023-06-27 20:46:03 +01:00
Simon Larsen
c33b2b0946 add order to on-call escalation rule 2023-06-27 20:24:57 +01:00
Simon Larsen
0475c18b0f fix typo 2023-06-26 18:55:41 +01:00
Simon Larsen
8396d7cbd7 do not show view id btn causes confusion 2023-06-26 17:59:03 +01:00
Simon Larsen
66e34014b9 fix fmt 2023-06-26 12:00:25 +01:00
Simon Larsen
908c108116 add log statements to domain verification 2023-06-26 11:59:03 +01:00
Simon Larsen
8130bb3bb7 fix issues with incident auto-resolve 2023-06-26 11:50:45 +01:00
Simon Larsen
0813f1425f relaod bash 2023-06-26 11:09:58 +01:00
Simon Larsen
3f9ca54c61 add probe monitor response. 2023-06-25 20:09:22 +01:00
Simon Larsen
03c49bc5cc add id generation 2023-06-25 19:06:43 +01:00
Simon Larsen
7007834394 add auto resolve incident in montor response 2023-06-25 19:02:43 +01:00
Simon Larsen
e7ee37c218 add incident id 2023-06-25 17:03:31 +01:00
Simon Larsen
5590b4fde2 fix fmt 2023-06-25 15:16:39 +01:00
Simon Larsen
1750692328 add root casuse messages 2023-06-25 15:14:54 +01:00
Simon Larsen
03ceda4f77 fix grammar 2023-06-25 15:03:50 +01:00
Simon Larsen
110f596cf6 fix incident and monitor service 2023-06-25 14:56:14 +01:00
Simon Larsen
63288ab589 fix fmt 2023-06-25 14:51:38 +01:00
Simon Larsen
c9480bea8f fix permissions and root cause 2023-06-25 14:46:32 +01:00
Simon Larsen
3a78307c2e add root cause 2023-06-25 14:33:49 +01:00
Simon Larsen
89ed205b50 add root cause 2023-06-25 14:11:59 +01:00
Simon Larsen
490edf1859 add root cause to monitoring 2023-06-25 13:34:25 +01:00
Simon Larsen
5fb42b9c6d add logs to status timeline 2023-06-25 11:24:23 +01:00
Simon Larsen
d5e07fc788 add logs to monitor probe 2023-06-25 10:23:42 +01:00
Simon Larsen
c3c871f9cc add auto resolve types 2023-06-23 17:30:37 +01:00
Simon Larsen
72635b8c8f fix deserlization 2023-06-23 11:22:51 +01:00
Simon Larsen
057d895aaf add type checking 2023-06-23 11:00:51 +01:00
Simon Larsen
407fc1240a add pricing controls 2023-06-22 20:53:38 +01:00
Simon Larsen
2bc307c564 add column access pricing controls 2023-06-22 20:41:03 +01:00
Simon Larsen
c42790e6f2 center loader 2023-06-22 20:20:04 +01:00
Simon Larsen
ecdbea2aab remove company name from user settings 2023-06-22 20:12:12 +01:00
Simon Larsen
7cb98456b1 ad owner fields to project model 2023-06-22 20:03:21 +01:00
Simon Larsen
4f80317b14 add disabled settings 2023-06-22 18:55:55 +01:00
Simon Larsen
7a589d65a3 add disable monitor page 2023-06-22 18:07:07 +01:00
Simon Larsen
acd5d04ee9 fix createdAt 2023-06-22 17:56:16 +01:00
Simon Larsen
998c85e393 update project last active 2023-06-22 17:51:28 +01:00
Simon Larsen
70478bd1fa fix createdAt not populating 2023-06-22 17:41:19 +01:00
Simon Larsen
4c06feeb50 fix fmt 2023-06-21 19:40:44 +01:00
Simon Larsen
2acd6d5ce0 add disable monitoring 2023-06-21 19:39:17 +01:00
Simon Larsen
56e7c0c7d0 fix monitor type enum 2023-06-21 19:00:23 +01:00
Simon Larsen
7948070be6 add user limit 2023-06-21 18:47:35 +01:00
Nawaz Dhandala
a9139fcca0 Merge pull request #484 from OneUptime/on-call
On-Call Duty -> On Call Duty Policy
2023-06-21 15:57:16 +01:00
Simon Larsen
99b3dc65a7 rename file with typo 2023-06-21 14:25:32 +01:00
Simon Larsen
599c7a175e fix 2023-06-21 14:25:17 +01:00
Simon Larsen
0a03dc652c fix migrations 2023-06-21 14:20:00 +01:00
Simon Larsen
53f72c2192 fix case 2023-06-21 13:39:24 +01:00
Simon Larsen
53334ad3dc make notiifction rule work properly 2023-06-20 15:41:54 +01:00
Simon Larsen
4d7ddf7be1 add notification rule 2023-06-20 15:34:33 +01:00
Simon Larsen
9dfdd0841f add delete trigger to call email and sms 2023-06-20 12:47:26 +01:00
Simon Larsen
7f662291e4 fix rule 2023-06-20 12:03:22 +01:00
Simon Larsen
9bbd32424e Merge branch 'master' into on-call 2023-06-20 11:53:49 +01:00
Simon Larsen
41b5fe3a19 fix null issue with select 2023-06-20 11:51:54 +01:00
Simon Larsen
d35195a591 fix notification types 2023-06-20 11:43:54 +01:00
Simon Larsen
ee229d3711 fix relation fetch in table 2023-06-20 10:05:41 +01:00
Simon Larsen
9eb12a5348 fix issues with table 2023-06-20 10:02:11 +01:00
Simon Larsen
0bb8343f0b fix typo 2023-06-19 20:27:43 +01:00
Simon Larsen
d5c13f5c26 fix fmt 2023-06-19 19:52:24 +01:00
Simon Larsen
9e57fe1531 add notification rule 2023-06-19 19:49:15 +01:00
Simon Larsen
8b10e0d9f0 fix fmt 2023-06-19 19:40:38 +01:00
Simon Larsen
45d7dc90b3 add donation in readme 2023-06-19 19:06:51 +01:00
Simon Larsen
da2683391d add notification rule 2023-06-19 17:57:48 +01:00
Simon Larsen
ea50830dae add notification rule model. 2023-06-19 17:52:49 +01:00
Simon Larsen
985a7ca973 fix side menu link 2023-06-19 13:11:48 +01:00
Simon Larsen
2c649bed07 fix on call custom fields 2023-06-19 13:06:22 +01:00
Simon Larsen
78fad54d6a Merge branch 'master' into on-call 2023-06-19 12:31:44 +01:00
Simon Larsen
05c583fd81 add plan name in project model 2023-06-19 12:30:52 +01:00
Simon Larsen
b99912abd6 add plan name to project 2023-06-19 12:27:10 +01:00
Simon Larsen
c3a5a8a4e8 add custom fields 2023-06-19 12:07:53 +01:00
Simon Larsen
ad451fd9c9 Merge branch 'master' into on-call 2023-06-19 11:29:39 +01:00
Simon Larsen
ce31e0cfff Merge pull request #489 from OneUptime/created-at-refactor
fix createdat
2023-06-19 11:24:40 +01:00
Simon Larsen
545dcea3e8 fix createdat 2023-06-19 11:24:25 +01:00
Simon Larsen
29accb2e6f Merge branch 'master' into release 2023-06-19 10:35:28 +01:00
Simon Larsen
8d59fdc732 Merge pull request #487 from OneUptime/master
Staus Page redirection fix
2023-06-16 19:45:16 +01:00
Simon Larsen
a7fe18fd65 fix rounded corners 2023-06-16 18:25:18 +01:00
Simon Larsen
e80835c380 Merge branch 'master' into on-call 2023-06-16 18:13:21 +01:00
Simon Larsen
622bb87b89 add call logs 2023-06-16 14:04:57 +01:00
Simon Larsen
3d3c9876eb add env var 2023-06-16 14:00:40 +01:00
Simon Larsen
ea588be0f7 Merge branch 'master' into on-call 2023-06-16 13:32:34 +01:00
Simon Larsen
71f2d3b87a add side menu item 2023-06-16 13:29:11 +01:00
Simon Larsen
8d0670d05c add call log 2023-06-16 13:26:32 +01:00
Simon Larsen
1b6eccfb36 fix fmt 2023-06-16 12:33:16 +01:00
Simon Larsen
9a7c2cedf5 add call service 2023-06-16 12:25:37 +01:00
Simon Larsen
55b9a6bf9f Merge branch 'master' into on-call 2023-06-16 12:22:05 +01:00
Simon Larsen
ff1f564527 add call config 2023-06-16 10:40:27 +01:00
Simon Larsen
6ef61221bf ad sms service 2023-06-15 15:07:34 +01:00
Simon Larsen
2edbe0df08 add resend verifiction code 2023-06-14 21:16:07 +01:00
Simon Larsen
a96dc90104 fix template 2023-06-14 21:05:43 +01:00
Simon Larsen
3e8b966dc8 fix models 2023-06-14 21:02:10 +01:00
Simon Larsen
1ee94f10c4 fix fmt 2023-06-14 20:13:24 +01:00
Simon Larsen
74866edadb add workflow help banner 2023-06-14 20:07:44 +01:00
Simon Larsen
e402ebc14c Merge branch 'master' into on-call 2023-06-14 20:04:00 +01:00
Simon Larsen
ab48de6e9b add user settings 2023-06-14 19:41:03 +01:00
Simon Larsen
314b905e8f add api for user notification methods 2023-06-14 14:56:47 +01:00
Simon Larsen
db60c0fefb add more icons 2023-06-14 14:38:35 +01:00
Simon Larsen
713d9464a2 add default value capability 2023-06-14 14:04:32 +01:00
Simon Larsen
84cc4a35d4 fix user email 2023-06-14 13:55:38 +01:00
Simon Larsen
6a64b8658a add user emails for notifications. 2023-06-14 13:47:01 +01:00
Simon Larsen
b8ee827068 fix lint 2023-06-14 12:28:54 +01:00
Simon Larsen
8fea1b6e3d fix sidemenu 2023-06-14 12:19:03 +01:00
Simon Larsen
96934f5f22 fix app.tsx 2023-06-14 12:17:45 +01:00
Simon Larsen
a2ad4d30e7 fix populate route params 2023-06-14 12:11:53 +01:00
Simon Larsen
0623588019 fix lint. 2023-06-14 11:30:09 +01:00
Simon Larsen
f1d087da44 add services and api 2023-06-13 17:03:38 +01:00
Simon Larsen
5dca4a0fd3 add services 2023-06-13 16:57:02 +01:00
Simon Larsen
7d085274de add models of on-call 2023-06-13 16:46:25 +01:00
Simon Larsen
1da9184a14 Merge branch 'master' into on-call 2023-06-13 10:47:06 +01:00
Simon Larsen
a7757e547c On-Call Duty -> On Call Duty Policy 2023-06-12 19:59:38 +01:00
502 changed files with 77299 additions and 6799 deletions

View File

@@ -39,6 +39,20 @@ jobs:
- run: cd CommonServer && npm install
- run: cd ApiReference && npm install && npm run compile
compile-link-shortner:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && npm install
- run: cd LinkShortner && npm install && npm run compile
compile-common-server:
runs-on: ubuntu-latest
env:

View File

@@ -25,6 +25,21 @@ jobs:
- name: build docker image
run: sudo docker build -f ./Accounts/Dockerfile .
docker-build-link-shortner:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for accounts service
- name: build docker image
run: sudo docker build -f ./LinkShortner/Dockerfile .
docker-build-api-reference:
runs-on: ubuntu-latest
env:
@@ -191,20 +206,6 @@ jobs:
- name: build docker image
run: sudo docker build -f ./Notification/Dockerfile .
docker-build-nginx:
runs-on: ubuntu-latest
env:
CI_PIPELINE_ID: ${{github.run_number}}
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Preinstall
run: npm run prerun
# build image for mail service
- name: build docker image
run: sudo docker build -f ./Nginx/Dockerfile ./Nginx
docker-build-probe:
runs-on: ubuntu-latest

File diff suppressed because it is too large Load Diff

View File

@@ -1,442 +0,0 @@
name: Test Image Deploy to DockerHub
on:
push:
branches:
- "master"
jobs:
generate-build-number:
runs-on: ubuntu-latest
outputs:
build_number: ${{ steps.buildnumber.outputs.build_number }}
steps:
- name: Generate build number
id: buildnumber
uses: onyxmueller/build-tag-number@v1.0.2
with:
token: ${{secrets.github_token}}
- run: echo "Build number is ${{ steps.buildnumber.outputs.build_number }}"
test-server-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/test-server:$ONEUPTIME_VERSION-test --tag oneuptime/test-server:test --push -f ./TestServer/Dockerfile .
workflow-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/workflow:$ONEUPTIME_VERSION-test --tag oneuptime/workflow:test --push -f ./Workflow/Dockerfile .
workers-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy workers.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/workers:$ONEUPTIME_VERSION-test --tag oneuptime/workers:test --push -f ./Workers/Dockerfile .
status-page-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy status-page.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/status-page:$ONEUPTIME_VERSION-test --tag oneuptime/status-page:test --push -f ./StatusPage/Dockerfile .
realtime-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy realtime.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/realtime:$ONEUPTIME_VERSION-test --tag oneuptime/realtime:test --push -f ./Realtime/Dockerfile .
probe-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy probe-api.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/probe:$ONEUPTIME_VERSION-test --tag oneuptime/probe:test --push -f ./Probe/Dockerfile .
probe-api-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy probe-api.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/probe-api:$ONEUPTIME_VERSION-test --tag oneuptime/probe-api:test --push -f ./ProbeAPI/Dockerfile .
nginx-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/nginx:$ONEUPTIME_VERSION-test --tag oneuptime/nginx:test --push -f ./Nginx/Dockerfile .
notification-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/notification:$ONEUPTIME_VERSION-test --tag oneuptime/notification:test --push -f ./Notification/Dockerfile .
licensing-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/licensing:$ONEUPTIME_VERSION-test --tag oneuptime/licensing:test --push -f ./Licensing/Dockerfile .
integrations-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/integrations:$ONEUPTIME_VERSION-test --tag oneuptime/integrations:test --push -f ./Integration/Dockerfile .
identity-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/identity:$ONEUPTIME_VERSION-test --tag oneuptime/identity:test --push -f ./Identity/Dockerfile .
home-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/home:$ONEUPTIME_VERSION-test --tag oneuptime/home:test --push -f ./Home/Dockerfile .
helm-chart-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/helm-chart:$ONEUPTIME_VERSION-test --tag oneuptime/helm-chart:test --push -f ./HelmChart/Dockerfile .
haraka-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/haraka:$ONEUPTIME_VERSION-test --tag oneuptime/haraka:test --push -f ./Haraka/Dockerfile .
file-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy file.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/file:$ONEUPTIME_VERSION-test --tag oneuptime/file:test --push -f ./File/Dockerfile .
dashboard-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy dashboard-api.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/dashboard:$ONEUPTIME_VERSION-test --tag oneuptime/dashboard:test --push -f ./Dashboard/Dockerfile .
dashboard-api-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy dashboard-api.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/dashboard-api:$ONEUPTIME_VERSION-test --tag oneuptime/dashboard-api:test --push -f ./DashboardAPI/Dockerfile .
api-reference-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy api-reference.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/api-reference:$ONEUPTIME_VERSION-test --tag oneuptime/api-reference:test --push -f ./ApiReference/Dockerfile .
accounts-test-docker-image-deploy:
needs: generate-build-number
runs-on: ubuntu-latest
env:
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 18.3.0
- run: npm run prerun
- run: sudo docker run --rm --privileged docker/binfmt:820fdd95a9972a5308930a2bdfb8573dd4447ad3
# Build and deploy accounts.
- run: sudo docker login --username $DOCKERHUB_USERNAME --password $DOCKERHUB_PASSWORD
- run: sudo docker buildx create --use
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/accounts:$ONEUPTIME_VERSION-test --tag oneuptime/accounts:test --push -f ./Accounts/Dockerfile .

View File

@@ -20,4 +20,4 @@ jobs:
- run: cd Common && npm install
- run: cd Model && npm install
- run: cd CommonServer && bash test-setup.sh
- run: cd CommonServer && npm install && npm run test
- run: export $(grep -v '^#' config.env | xargs) && cd CommonServer && npm install && npm run test

4
.gitignore vendored
View File

@@ -69,12 +69,10 @@ secret.env
config.env
config.env.tmp
config.env.temp
docker-compose.yml
logs.txt
*/Cert.crt
*/Key.key
Nginx/default.conf
Certs/StatusPageCerts/*.crt
Certs/StatusPageCerts/*.key
@@ -85,3 +83,5 @@ Certs/ServerCerts/*.key
Backups/*.backup
Backups/*.sql
Backups/*.tar
.env

44
.vscode/launch.json vendored
View File

@@ -41,6 +41,34 @@
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/ApiReference",
"name": "API Reference: Debug with Docker",
"port": 9178,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/LinkShortner",
"name": "Link Shortner: Debug with Docker",
"port": 9826,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/TestServer",
@@ -58,7 +86,7 @@
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/Probe",
"name": "Dashboard API: Debug with Docker",
"name": "Probe: Debug with Docker",
"port": 9655,
"remoteRoot": "/usr/src/app",
"request": "attach",
@@ -307,20 +335,6 @@
"restart": true,
"autoAttachChildProcesses": true
},
{
"address": "127.0.0.1",
"localRoot": "${workspaceFolder}/probe",
"name": "Probe: Debug with Docker",
"port": 9238,
"remoteRoot": "/usr/src/app",
"request": "attach",
"skipFiles": [
"<node_internals>/**"
],
"type": "node",
"restart": true,
"autoAttachChildProcesses": true
},
{
"name": "CommonServer: Debug Tests",
"type": "node",

View File

@@ -1 +0,0 @@
PORT=3003

View File

@@ -1 +0,0 @@
PORT={{ .Env.ACCOUNTS_PORT }}

View File

@@ -73,6 +73,8 @@ EXPOSE 3003
{{ if eq .Env.ENVIRONMENT "development" }}
RUN mkdir /usr/src/app/dev-env
RUN touch /usr/src/app/dev-env/.env
#Run the app
CMD [ "npm", "run", "dev" ]
{{ else }}

View File

@@ -0,0 +1 @@
This is where env will be stored for the dev environment. This is where you will find the .env file when you exec into the container.

View File

@@ -1,4 +1,4 @@
{
"watch": ["webpack.config.js"],
"exec": "export DEBUG=express:* && webpack-dev-server --port=3003 --mode=development"
"exec": "export DEBUG=express:* && printenv > /usr/src/app/dev-env/.env && webpack-dev-server --port=3003 --mode=development"
}

View File

@@ -7,7 +7,6 @@
"": {
"name": "accounts",
"version": "0.1.0",
"hasInstallScript": true,
"dependencies": {
"Common": "file:../Common",
"CommonServer": "file:../CommonServer",
@@ -57,6 +56,7 @@
"@types/uuid": "^8.3.4",
"axios": "^0.26.1",
"crypto-js": "^4.1.1",
"json5": "^2.2.3",
"moment": "^2.29.2",
"moment-timezone": "^0.5.40",
"nanoid": "^3.3.2",
@@ -88,12 +88,14 @@
"@types/ejs": "^3.1.1",
"@types/gridfs-stream": "^0.5.35",
"@types/json2csv": "^5.0.3",
"@types/markdown-it": "^12.2.3",
"@types/nodemailer": "^6.4.7",
"airtable": "^0.11.3",
"axios": "^1.3.3",
"bullmq": "^3.6.6",
"Common": "file:../Common",
"cors": "^2.8.5",
"cron-parser": "^4.8.1",
"dotenv": "^16.0.0",
"ejs": "^3.1.8",
"express": "^4.17.3",
@@ -101,6 +103,7 @@
"handlebars": "^4.7.7",
"json2csv": "^5.0.7",
"jsonwebtoken": "^9.0.0",
"markdown-it": "^13.0.1",
"Model": "file:../Model",
"node-device-detector": "^2.0.0",
"nodemailer": "^6.7.3",
@@ -109,6 +112,7 @@
"redis": "^4.2.0",
"socket.io": "^4.4.1",
"stripe": "^10.17.0",
"twilio": "^4.13.0",
"typeorm": "^0.3.10",
"typeorm-extension": "^2.2.13",
"vm2": "^3.9.14",
@@ -283,9 +287,9 @@
}
},
"node_modules/@babel/core/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -316,9 +320,9 @@
}
},
"node_modules/@babel/eslint-parser/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -390,9 +394,9 @@
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -449,9 +453,9 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -1782,9 +1786,9 @@
}
},
"node_modules/@babel/plugin-transform-runtime/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -1994,9 +1998,9 @@
}
},
"node_modules/@babel/preset-env/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -4836,9 +4840,9 @@
}
},
"node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -7060,9 +7064,9 @@
}
},
"node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -7134,9 +7138,9 @@
}
},
"node_modules/eslint-plugin-react/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -9150,9 +9154,9 @@
}
},
"node_modules/istanbul-lib-instrument/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -10430,9 +10434,9 @@
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"bin": {
"semver": "bin/semver.js"
}
@@ -10796,9 +10800,9 @@
}
},
"node_modules/nodemon/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -12886,9 +12890,9 @@
}
},
"node_modules/react-app-rewired/node_modules/semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true,
"bin": {
"semver": "bin/semver"
@@ -13647,9 +13651,9 @@
}
},
"node_modules/semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dependencies": {
"lru-cache": "^6.0.0"
},
@@ -14647,9 +14651,9 @@
}
},
"node_modules/tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"dependencies": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
@@ -15645,9 +15649,9 @@
"dev": true
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"engines": {
"node": ">=0.10.0"
}
@@ -16135,9 +16139,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -16157,9 +16161,9 @@
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw=="
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -16214,9 +16218,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -16257,9 +16261,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -17120,9 +17124,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -17277,9 +17281,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -19339,9 +19343,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -19848,6 +19852,7 @@
"axios": "^0.26.1",
"crypto-js": "^4.1.1",
"jest": "^27.5.1",
"json5": "^2.2.3",
"moment": "^2.29.2",
"moment-timezone": "^0.5.40",
"nanoid": "^3.3.2",
@@ -19891,6 +19896,7 @@
"@types/jest": "^27.4.1",
"@types/json2csv": "^5.0.3",
"@types/jsonwebtoken": "^8.5.9",
"@types/markdown-it": "^12.2.3",
"@types/node": "^17.0.22",
"@types/nodemailer": "^6.4.7",
"airtable": "^0.11.3",
@@ -19898,6 +19904,7 @@
"bullmq": "^3.6.6",
"Common": "file:../Common",
"cors": "^2.8.5",
"cron-parser": "^4.8.1",
"dotenv": "^16.0.0",
"ejs": "^3.1.8",
"express": "^4.17.3",
@@ -19906,6 +19913,7 @@
"jest": "^27.5.1",
"json2csv": "^5.0.7",
"jsonwebtoken": "^9.0.0",
"markdown-it": "^13.0.1",
"Model": "file:../Model",
"node-device-detector": "^2.0.0",
"nodemailer": "^6.7.3",
@@ -19915,6 +19923,7 @@
"socket.io": "^4.4.1",
"stripe": "^10.17.0",
"ts-jest": "^27.1.4",
"twilio": "^4.13.0",
"typeorm": "^0.3.10",
"typeorm-extension": "^2.2.13",
"vm2": "^3.9.14",
@@ -21163,9 +21172,9 @@
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -21210,9 +21219,9 @@
}
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -22615,9 +22624,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -23597,9 +23606,9 @@
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="
}
}
},
@@ -23879,9 +23888,9 @@
"dev": true
},
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
},
"supports-color": {
@@ -25195,9 +25204,9 @@
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"version": "5.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
"dev": true
}
}
@@ -25728,9 +25737,9 @@
}
},
"semver": {
"version": "7.3.8",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"requires": {
"lru-cache": "^6.0.0"
}
@@ -26499,9 +26508,9 @@
}
},
"tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"requires": {
"psl": "^1.1.33",
"punycode": "^2.1.1",
@@ -27202,9 +27211,9 @@
"dev": true
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ=="
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA=="
},
"workbox-background-sync": {
"version": "6.5.4",

View File

@@ -65,7 +65,7 @@ const ForgotPassword: FunctionComponent = () => {
formType={FormType.Create}
maxPrimaryButtonWidth={true}
footer={
<div className="actions pointer text-center mt-4 underline-on-hover fw-semibold">
<div className="actions pointer text-center mt-4 hover:underline fw-semibold">
<p>
<Link
to={new Route('/accounts/login')}

View File

@@ -79,7 +79,7 @@ const LoginPage: FunctionComponent = () => {
}}
maxPrimaryButtonWidth={true}
footer={
<div className="actions pointer text-center mt-4 underline-on-hover fw-semibold">
<div className="actions pointer text-center mt-4 hover:underline fw-semibold">
<p>
{!showSsoTip && (
<div

View File

@@ -9,9 +9,10 @@ import LoginUtil from '../Utils/Login';
import { JSONObject } from 'Common/Types/JSON';
import UserUtil from 'CommonUI/src/Utils/User';
import Navigation from 'CommonUI/src/Utils/Navigation';
import { DASHBOARD_URL } from 'CommonUI/src/Config';
import { BILLING_ENABLED, DASHBOARD_URL } from 'CommonUI/src/Config';
import URL from 'Common/Types/API/URL';
import { SIGNUP_API_URL } from '../Utils/ApiPaths';
import Fields from 'CommonUI/src/Components/Forms/Types/Fields';
const RegisterPage: FunctionComponent = () => {
const apiUrl: URL = SIGNUP_API_URL;
@@ -20,6 +21,80 @@ const RegisterPage: FunctionComponent = () => {
Navigation.navigate(DASHBOARD_URL);
}
let formFields: Fields<User> = [
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: 'jeff@example.com',
required: true,
title: 'Email',
},
{
field: {
name: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Jeff Smith',
required: true,
title: 'Full Name',
},
];
if (BILLING_ENABLED) {
formFields = formFields.concat([
{
field: {
companyName: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Acme, Inc.',
required: true,
title: 'Company Name',
},
{
field: {
companyPhoneNumber: true,
},
fieldType: FormFieldSchemaType.Phone,
required: true,
placeholder: '+11234567890',
title: 'Phone Number',
},
]);
}
formFields = formFields.concat([
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: 'Password',
title: 'Password',
required: true,
},
{
field: {
confirmPassword: true,
} as any,
validation: {
minLength: 6,
toMatchField: 'password',
},
fieldType: FormFieldSchemaType.Password,
placeholder: 'Confirm Password',
title: 'Confirm Password',
overideFieldKey: 'confirmPassword',
required: true,
forceShow: true,
},
]);
return (
<div className="flex min-h-full flex-col justify-center py-12 sm:px-6 lg:px-8">
<div className="sm:mx-auto sm:w-full sm:max-w-md">
@@ -56,71 +131,7 @@ const RegisterPage: FunctionComponent = () => {
password: '',
confirmPassword: '',
}}
fields={[
{
field: {
email: true,
},
fieldType: FormFieldSchemaType.Email,
placeholder: 'jeff@example.com',
required: true,
title: 'Email',
},
{
field: {
name: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Jeff Smith',
required: true,
title: 'Full Name',
},
{
field: {
companyName: true,
},
fieldType: FormFieldSchemaType.Text,
placeholder: 'Acme, Inc.',
required: true,
title: 'Company Name',
},
{
field: {
companyPhoneNumber: true,
},
fieldType: FormFieldSchemaType.Phone,
required: true,
placeholder: '+11234567890',
title: 'Phone Number',
},
{
field: {
password: true,
},
fieldType: FormFieldSchemaType.Password,
validation: {
minLength: 6,
},
placeholder: 'Password',
title: 'Password',
required: true,
},
{
field: {
confirmPassword: true,
},
validation: {
minLength: 6,
toMatchField: 'password',
},
fieldType: FormFieldSchemaType.Password,
placeholder: 'Confirm Password',
title: 'Confirm Password',
overideFieldKey: 'confirmPassword',
required: true,
forceShow: true,
},
]}
fields={formFields}
apiUrl={apiUrl}
formType={FormType.Create}
submitButtonText={'Sign Up'}

View File

@@ -109,7 +109,7 @@ const VerifyEmail: FunctionComponent = () => {
'/accounts/login'
)
}
className="underline-on-hover text-primary fw-semibold"
className="hover:underline text-primary fw-semibold"
>
Login.
</Link>

View File

@@ -38,9 +38,7 @@ module.exports = {
new webpack.DefinePlugin({
'process': {
'env': {
...readEnvFile('../Common/.env'),
...readEnvFile('../CommonUI/.env'),
...readEnvFile('./.env')
...readEnvFile('/usr/src/app/dev-env/.env')
}
}
}),

View File

View File

@@ -1 +0,0 @@
PORT={{ .Env.API_DOCS_PORT }}

View File

@@ -20,7 +20,7 @@ import DataTypeServiceHandler from './Service/DataType';
import Dictionary from 'Common/Types/Dictionary';
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getReosurceDictionaryByPath();
ResourceUtil.getResourceDictionaryByPath();
const APP_NAME: string = 'reference';

View File

@@ -15,7 +15,7 @@ import PageNotFoundServiceHandler from './PageNotFound';
const Resources: Array<ModelDocumentation> = ResourceUtil.getResources();
const ResourceDictionary: Dictionary<ModelDocumentation> =
ResourceUtil.getReosurceDictionaryByPath();
ResourceUtil.getResourceDictionaryByPath();
const PermissionDictionary: Dictionary<PermissionProps> =
PermissionHelper.getAllPermissionPropsAsDictionary();

View File

@@ -52,7 +52,7 @@ export default class ResourceUtil {
);
}
public static getReosurceDictionaryByPath(): Dictionary<ModelDocumentation> {
public static getResourceDictionaryByPath(): Dictionary<ModelDocumentation> {
const dict: Dictionary<ModelDocumentation> = {};
const resources: Array<ModelDocumentation> =

View File

@@ -30,7 +30,7 @@
</div>
</div>
<h1 class="font-bold text-xl">API Documentation</h1>
<p class="lead">Use the OneUptime API to access any reosurce in your projects, create automated
<p class="lead">Use the OneUptime API to access any resource in your projects, create automated
workflows, and more
and
seamlessly integrate your project into the other tools and services you use in your

View File

@@ -1,4 +0,0 @@
CLICKHOUSE_USER={{ .Env.CLICKHOUSE_USER }}
CLICKHOUSE_PASSWORD={{ .Env.CLICKHOUSE_PASSWORD }}
CLICKHOUSE_DB=oneuptime
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT=1

3
Clickhouse/README.md Normal file
View File

@@ -0,0 +1,3 @@
# Clickhouse
This folder is for clickhouse related files.

View File

@@ -1,9 +0,0 @@
NODE_ENV={{ .Env.ENVIRONMENT }}
BILLING_ENABLED={{ .Env.BILLING_ENABLED }}
BILLING_PUBLIC_KEY={{ .Env.BILLING_PUBLIC_KEY }}
SUBSCRIPTION_PLAN_BASIC={{ .Env.SUBSCRIPTION_PLAN_BASIC }}
SUBSCRIPTION_PLAN_GROWTH={{ .Env.SUBSCRIPTION_PLAN_GROWTH }}
SUBSCRIPTION_PLAN_SCALE={{ .Env.SUBSCRIPTION_PLAN_SCALE }}
SUBSCRIPTION_PLAN_ENTERPRISE={{ .Env.SUBSCRIPTION_PLAN_ENTERPRISE }}
METERED_PLAN_ACTIVE_MONITORING={{ .Env.METERED_PLAN_ACTIVE_MONITORING }}
DOMAIN={{ .Env.DOMAIN }}

View File

@@ -28,13 +28,17 @@ import Permission, {
UserPermission,
UserTenantAccessPermission,
} from '../Types/Permission';
import { ColumnAccessControl } from '../Types/Database/AccessControl/AccessControl';
import {
ColumnAccessControl,
ColumnBillingAccessControl,
} from '../Types/Database/AccessControl/AccessControl';
import { getColumnAccessControlForAllColumns } from '../Types/Database/AccessControl/ColumnAccessControl';
import BadDataException from '../Types/Exception/BadDataException';
import { PlanSelect } from '../Types/Billing/SubscriptionPlan';
import { EnableWorkflowOn } from '../Types/Model/EnableWorkflow';
import IconProp from '../Types/Icon/IconProp';
import Text from '../Types/Text';
import { getColumnBillingAccessControlForAllColumns } from '../Types/Database/AccessControl/ColumnBillingAccessControl';
export type DbTypes =
| string
@@ -202,6 +206,14 @@ export default class BaseModel extends BaseEntity {
return dictionary[columnName] as TableColumnMetadata;
}
public getColumnBillingAccessControl(
columnName: string
): ColumnBillingAccessControl {
const dictionary: Dictionary<ColumnBillingAccessControl> =
getColumnBillingAccessControlForAllColumns(this);
return dictionary[columnName] as ColumnBillingAccessControl;
}
public getColumnAccessControlFor(
columnName: string
): ColumnAccessControl | null {

View File

@@ -3,6 +3,7 @@ enum HTTPMethod {
POST = 'POST',
DELETE = 'DELETE',
PUT = 'PUT',
HEAD = 'HEAD',
}
export default HTTPMethod;

View File

@@ -0,0 +1,30 @@
import URL from '../API/URL';
import Phone from '../Phone';
export interface Say {
sayMessage: string;
}
export interface OnCallInputRequest {
[x: string]: Say; // input.
default: Say; // what if there is no input or invalid input.
}
export interface GatherInput {
introMessage: string;
numDigits: number;
timeoutInSeconds: number;
noInputMessage: string;
onInputCallRequest: OnCallInputRequest;
responseUrl: URL;
}
export enum CallAction {}
export interface CallRequestMessage {
data: Array<Say | CallAction | GatherInput>;
}
export default interface CallRequest extends CallRequestMessage {
to: Phone;
}

View File

@@ -0,0 +1,9 @@
enum CallStatus {
Success = 'Success',
Error = 'Error',
LowBalance = 'Low Balance',
MissedCall = 'Missed Call',
Busy = 'Busy',
}
export default CallStatus;

View File

@@ -17,3 +17,9 @@ export interface BillingAccessControl {
update: PlanSelect;
delete: PlanSelect;
}
export interface ColumnBillingAccessControl {
create: PlanSelect;
read: PlanSelect;
update: PlanSelect;
}

View File

@@ -0,0 +1,45 @@
import 'reflect-metadata';
import BaseModel from '../../../Models/BaseModel';
import Dictionary from '../../Dictionary';
import { ReflectionMetadataType } from '../../Reflection';
import { ColumnBillingAccessControl } from './AccessControl';
const accessControlSymbol: Symbol = Symbol('ColumnBillingAccessControl');
export default (
accessControl: ColumnBillingAccessControl
): ReflectionMetadataType => {
return Reflect.metadata(accessControlSymbol, accessControl);
};
export const getColumnBillingAccessControl: Function = (
target: BaseModel,
propertyKey: string
): ColumnBillingAccessControl => {
return Reflect.getMetadata(
accessControlSymbol,
target,
propertyKey
) as ColumnBillingAccessControl;
};
export const getColumnBillingAccessControlForAllColumns: Function = <
T extends BaseModel
>(
target: T
): Dictionary<ColumnBillingAccessControl> => {
const dictonary: Dictionary<ColumnBillingAccessControl> = {};
const keys: Array<string> = Object.keys(target);
for (const key of keys) {
if (Reflect.getMetadata(accessControlSymbol, target, key)) {
dictonary[key] = Reflect.getMetadata(
accessControlSymbol,
target,
key
) as ColumnBillingAccessControl;
}
}
return dictonary;
};

View File

@@ -1,3 +1,5 @@
import TableColumnType from './TableColumnType';
enum ColumnLength {
Version = 30,
Slug = 100,
@@ -15,4 +17,53 @@ enum ColumnLength {
OTP = 8,
}
export const getMaxLengthFromTableColumnType: Function = (
type: TableColumnType
): number | undefined => {
if (type === TableColumnType.Version) {
return ColumnLength.Version;
}
if (type === TableColumnType.Slug) {
return ColumnLength.Slug;
}
if (type === TableColumnType.Email) {
return ColumnLength.Email;
}
if (type === TableColumnType.Domain) {
return ColumnLength.Domain;
}
if (type === TableColumnType.Color) {
return ColumnLength.Color;
}
if (type === TableColumnType.Name) {
return ColumnLength.Name;
}
if (type === TableColumnType.Description) {
return ColumnLength.Description;
}
if (type === TableColumnType.LongText) {
return ColumnLength.LongText;
}
if (type === TableColumnType.Password) {
return ColumnLength.Password;
}
if (type === TableColumnType.ShortURL) {
return ColumnLength.ShortURL;
}
if (type === TableColumnType.ShortText) {
return ColumnLength.ShortText;
}
if (type === TableColumnType.HashedString) {
return ColumnLength.HashedString;
}
if (type === TableColumnType.Phone) {
return ColumnLength.Phone;
}
if (type === TableColumnType.OTP) {
return ColumnLength.OTP;
}
return undefined;
};
export default ColumnLength;

View File

@@ -19,6 +19,7 @@ export interface TableColumnMetadata {
type: TableColumnType;
canReadOnRelationQuery?: boolean;
modelType?: { new (): BaseModel };
forceGetDefaultValueOnCreate?: () => string | number | boolean; // overwrites any value that is being passed and generates a new one. Useful for generating OTPs, etc.
}
export default (props: TableColumnMetadata): ReflectionMetadataType => {

View File

@@ -1,5 +1,6 @@
import InBetween from './Database/InBetween';
import BadDataException from './Exception/BadDataException';
import { JSONObject } from './JSON';
import { JSONObject, ObjectType } from './JSON';
import PositiveNumber from './PositiveNumber';
import moment from 'moment-timezone';
@@ -65,6 +66,21 @@ export default class OneUptimeDate {
return YYYY + '-' + MM + '-' + DD + 'T' + HH + ':' + II + ':' + SS;
}
public static fromJSON(json: JSONObject): Date {
if (json['_type'] === ObjectType.DateTime) {
return OneUptimeDate.fromString(json['value'] as string);
}
throw new BadDataException('Invalid JSON: ' + JSON.stringify(json));
}
public static toJSON(date: Date): JSONObject {
return {
_type: ObjectType.DateTime,
value: OneUptimeDate.toString(date),
};
}
public static addRemoveMinutes(date: Date, minutes: number): Date {
date = this.fromString(date);
return moment(date).add(minutes, 'minutes').toDate();
@@ -364,6 +380,18 @@ export default class OneUptimeDate {
);
}
public static getDifferenceInMinutes(date: Date, date2: Date): number {
date = this.fromString(date);
date2 = this.fromString(date2);
const minutes: number = moment(date).diff(moment(date2), 'minutes');
if (minutes < 0) {
return minutes * -1;
}
return minutes;
}
public static getDateAsFormattedArrayInMultipleTimezones(
date: string | Date,
onlyShowDate?: boolean
@@ -449,6 +477,10 @@ export default class OneUptimeDate {
);
}
public static getDayInSeconds(): number {
return 24 * 60 * 60;
}
public static getCurrentTimezoneString(): string {
return moment.tz(moment.tz.guess()).zoneAbbr();
}
@@ -495,4 +527,13 @@ export default class OneUptimeDate {
const formatstring: string = 'YYYY-MM-DD';
return moment(date).local().format(formatstring);
}
public static asFilterDateForDatabaseQuery(date: string | Date): InBetween {
date = this.fromString(date);
const formattedDate: Date = moment(date).toDate();
return new InBetween(
OneUptimeDate.getStartOfDay(formattedDate),
OneUptimeDate.getEndOfDay(formattedDate)
);
}
}

View File

@@ -26,7 +26,7 @@ export default class Domain extends DatabaseProperty {
'|'
);
const secondTLDs: Array<string> =
'ac|academy|accountant|accountants|actor|adult|ag|agency|ai|airforce|am|amsterdam|apartments|app|archi|army|art|asia|associates|at|attorney|au|auction|auto|autos|baby|band|bar|barcelona|bargains|basketball|bayern|be|beauty|beer|berlin|best|bet|bid|bike|bingo|bio|biz|biz.pl|black|blog|blue|boats|boston|boutique|broker|build|builders|business|buzz|bz|ca|cab|cafe|camera|camp|capital|car|cards|care|careers|cars|casa|cash|casino|catering|cc|center|ceo|ch|charity|chat|cheap|church|city|cl|claims|cleaning|clinic|clothing|cloud|club|cn|co|co.in|co.jp|co.kr|co.nz|co.uk|co.za|coach|codes|coffee|college|com|com.ag|com.au|com.br|com.bz|com.cn|com.co|com.es|com.ky|com.mx|com.pe|com.ph|com.pl|com.ru|com.tw|community|company|computer|condos|construction|consulting|contact|contractors|cooking|cool|country|coupons|courses|credit|creditcard|cricket|cruises|cymru|cz|dance|date|dating|de|deals|degree|delivery|democrat|dental|dentist|design|dev|diamonds|digital|direct|directory|discount|dk|doctor|dog|domains|download|earth|education|email|energy|engineer|engineering|enterprises|equipment|es|estate|eu|events|exchange|expert|exposed|express|fail|faith|family|fan|fans|farm|fashion|film|finance|financial|firm.in|fish|fishing|fit|fitness|flights|florist|fm|football|forsale|foundation|fr|fun|fund|furniture|futbol|fyi|gallery|games|garden|gay|gen.in|gg|gifts|gives|giving|glass|global|gmbh|gold|golf|graphics|gratis|green|gripe|group|gs|guide|guru|hair|haus|health|healthcare|hockey|holdings|holiday|homes|horse|hospital|host|house|idv.tw|immo|immobilien|in|inc|ind.in|industries|info|info.pl|ink|institute|insure|international|investments|io|irish|ist|istanbul|it|jetzt|jewelry|jobs|jp|kaufen|kids|kim|kitchen|kiwi|kr|ky|la|land|lat|law|lawyer|lease|legal|lgbt|life|lighting|limited|limo|live|llc|llp|loan|loans|london|love|ltd|ltda|luxury|maison|makeup|management|market|marketing|mba|me|me.uk|media|melbourne|memorial|men|menu|miami|mobi|moda|moe|money|monster|mortgage|motorcycles|movie|ms|music|mx|nagoya|name|navy|ne.kr|net|net.ag|net.au|net.br|net.bz|net.cn|net.co|net.in|net.ky|net.nz|net.pe|net.ph|net.pl|net.ru|network|news|ninja|nl|no|nom.co|nom.es|nom.pe|nrw|nyc|okinawa|one|onl|online|org|org.ag|org.au|org.cn|org.es|org.in|org.ky|org.nz|org.pe|org.ph|org.pl|org.ru|org.uk|organic|page|paris|partners|parts|party|pe|pet|ph|photography|photos|pictures|pink|pizza|pl|place|plumbing|plus|poker|porn|press|pro|productions|promo|properties|protection|pub|pw|quebec|quest|racing|re.kr|realestate|recipes|red|rehab|reise|reisen|rent|rentals|repair|report|republican|rest|restaurant|review|reviews|rich|rip|rocks|rodeo|rugby|run|ryukyu|sale|salon|sarl|school|schule|science|se|security|services|sex|sg|sh|shiksha|shoes|shop|shopping|show|singles|site|ski|skin|soccer|social|software|solar|solutions|space|storage|store|stream|studio|study|style|supplies|supply|support|surf|surgery|sydney|systems|tax|taxi|team|tech|technology|tel|tennis|theater|theatre|tickets|tienda|tips|tires|today|tokyo|tools|tours|town|toys|trade|trading|training|travel|tube|tv|tw|uk|university|uno|us|vacations|vc|vegas|ventures|vet|viajes|video|villas|vin|vip|vision|vodka|vote|voto|voyage|wales|watch|web|webcam|website|wedding|wiki|win|wine|work|works|world|ws|wtf|xxx|xyz|yachts|yoga|yokohama|zone|移动|dev|com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc'.split(
'ac|academy|accountant|accountants|actor|adult|ag|agency|ai|airforce|am|amsterdam|apartments|app|archi|army|art|asia|associates|at|attorney|au|auction|auto|autos|baby|band|bar|barcelona|bargains|basketball|bayern|be|beauty|beer|berlin|best|bet|bid|bike|bingo|bio|biz|biz.pl|black|blog|blue|boats|boston|boutique|broker|build|builders|business|buzz|bz|ca|cab|cafe|camera|camp|capital|car|cards|care|careers|cars|casa|cash|casino|catering|cc|center|ceo|ch|charity|chat|cheap|church|city|cl|claims|cleaning|clinic|clothing|cloud|club|cn|co|co.in|co.jp|co.kr|co.nz|co.uk|co.za|coach|codes|coffee|college|com|com.ag|com.au|com.br|com.bz|com.cn|com.co|com.es|com.ky|com.mx|com.pe|com.ph|com.pl|com.ru|com.tw|community|company|computer|condos|construction|consulting|contact|contractors|cooking|cool|country|coupons|courses|credit|creditcard|cricket|cruises|cymru|cz|dance|date|dating|de|deals|degree|delivery|democrat|dental|dentist|design|dev|diamonds|digital|direct|directory|discount|dk|doctor|dog|domains|download|earth|education|email|energy|engineer|engineering|enterprises|equipment|es|estate|eu|events|exchange|expert|exposed|express|fail|faith|family|fan|fans|farm|fashion|film|finance|financial|firm.in|fish|fishing|fit|fitness|flights|florist|fm|football|forsale|foundation|fr|fun|fund|furniture|futbol|fyi|gallery|games|garden|gay|gen.in|gg|gifts|gives|giving|glass|global|gmbh|gold|golf|graphics|gratis|green|gripe|group|gs|guide|guru|hair|haus|health|healthcare|hockey|holdings|holiday|homes|horse|hospital|host|house|idv.tw|immo|immobilien|in|inc|ind.in|industries|info|info.pl|ink|institute|insure|international|investments|io|irish|ist|istanbul|it|jetzt|jewelry|jobs|jp|kaufen|kids|kim|kitchen|kiwi|kr|ky|la|land|lat|law|lawyer|lease|legal|lgbt|life|lighting|limited|limo|live|llc|llp|loan|loans|london|love|ltd|ltda|luxury|maison|makeup|management|market|marketing|mba|me|me.uk|media|melbourne|memorial|men|menu|miami|mobi|moda|moe|money|monster|mortgage|motorcycles|movie|ms|music|mx|nagoya|name|navy|ne.kr|net|net.ag|net.au|net.br|net.bz|net.cn|net.co|net.in|net.ky|net.nz|net.pe|net.ph|net.pl|net.ru|network|news|ninja|nl|no|nom.co|nom.es|nom.pe|nrw|nyc|okinawa|one|onl|online|org|org.ag|org.au|org.cn|org.es|org.in|org.ky|org.nz|org.pe|org.ph|org.pl|org.ru|org.uk|organic|page|paris|partners|parts|party|pe|pet|ph|photography|photos|pictures|pink|pizza|pl|place|plumbing|plus|poker|porn|press|pro|productions|promo|properties|protection|pub|pw|quebec|quest|racing|re.kr|realestate|recipes|red|rehab|reise|reisen|rent|rentals|repair|report|republican|rest|restaurant|review|reviews|rich|rip|rocks|rodeo|rugby|run|ryukyu|sale|salon|sarl|school|schule|science|se|security|services|sex|sg|sh|shiksha|shoes|shop|shopping|show|singles|site|ski|skin|soccer|social|software|solar|solutions|space|storage|store|stream|studio|study|style|supplies|supply|support|surf|surgery|sydney|systems|tax|taxi|team|tech|technology|tel|tennis|theater|theatre|tickets|tienda|tips|tires|today|tokyo|tools|tours|town|toys|trade|trading|training|travel|tube|tv|tw|uk|university|uno|us|vacations|vc|vegas|ventures|vet|viajes|video|villas|vin|vip|vision|vodka|vote|voto|voyage|wales|watch|web|webcam|website|wedding|wiki|win|wine|work|works|world|ws|wtf|xxx|xyz|yachts|yoga|yokohama|zone|移动|dev|com|edu|gov|net|mil|org|nom|sch|caa|res|off|gob|int|tur|ip6|uri|urn|asn|act|nsw|qld|tas|vic|pro|biz|adm|adv|agr|arq|art|ato|bio|bmd|cim|cng|cnt|ecn|eco|emp|eng|esp|etc|eti|far|fnd|fot|fst|g12|ggf|imb|ind|inf|jor|jus|leg|lel|mat|med|mus|not|ntr|odo|ppg|psc|psi|qsl|rec|slg|srv|teo|tmp|trd|vet|zlg|web|ltd|sld|pol|fin|k12|lib|pri|aip|fie|eun|sci|prd|cci|pvt|mod|idv|rel|sex|gen|nic|abr|bas|cal|cam|emr|fvg|laz|lig|lom|mar|mol|pmn|pug|sar|sic|taa|tos|umb|vao|vda|ven|mie|北海道|和歌山|神奈川|鹿児島|ass|rep|tra|per|ngo|soc|grp|plc|its|air|and|bus|can|ddr|jfk|mad|nrw|nyc|ski|spy|tcm|ulm|usa|war|fhs|vgs|dep|eid|fet|fla|flå|gol|hof|hol|sel|vik|cri|iwi|ing|abo|fam|gok|gon|gop|gos|aid|atm|gsm|sos|elk|waw|est|aca|bar|cpa|jur|law|sec|plo|www|bir|cbg|jar|khv|msk|nov|nsk|ptz|rnd|spb|stv|tom|tsk|udm|vrn|cmw|kms|nkz|snz|pub|fhv|red|ens|nat|rns|rnu|bbs|tel|bel|kep|nhs|dni|fed|isa|nsn|gub|e12|tec|орг|обр|упр|alt|nis|jpn|mex|ath|iki|nid|gda|inc|za'.split(
'|'
);

View File

@@ -2,10 +2,13 @@ import Email from '../Email';
import Dictionary from '../Dictionary';
import EmailTemplateType from './EmailTemplateType';
export default interface EmailMessage {
toEmail: Email;
export interface EmailEnvelope {
subject: string;
templateType?: EmailTemplateType;
vars: Dictionary<string>;
body?: string;
}
export default interface EmailMessage extends EmailEnvelope {
toEmail: Email;
}

View File

@@ -1,8 +1,10 @@
import Email from '../Email';
import Port from '../Port';
import Hostname from '../API/Hostname';
import ObjectID from '../ObjectID';
export default interface EmailServer {
id?: ObjectID | undefined; // If this is custom SMTP, this is the ID of the SMTP config. Otherwise, it's undefined
host: Hostname;
port: Port;
username: string;

View File

@@ -32,6 +32,8 @@ enum EmailTemplateType {
StatusPageOwnerAdded = 'StatusPageOwnerAdded.hbs',
StatusPageOwnerAnnouncementPosted = 'StatusPageOwnerAnnouncementPosted.hbs',
SimpleMessage = 'SimpleMessage.hbs',
VerificationCode = 'VerificationCode.hbs',
AcknowledgeIncident = 'AcknowledgeIncident.hbs',
}
export default EmailTemplateType;

View File

@@ -94,6 +94,14 @@ enum IconProp {
TransparentCube = 'TransparentCube',
Logs = 'Logs',
Bolt = 'Bolt',
BarsArrowUp = 'BarsArrowUp',
BarsArrowDown = 'BarsArrowDown',
Bell = 'Bell',
BellRinging = 'BellRinging',
AdjustmentVertical = 'AdjustmentVertical',
AdjustmentHorizontal = 'AdjustmentHorizontal',
Minus = 'Minus',
MinusSmall = 'MinusSmall',
}
export default IconProp;

View File

@@ -22,6 +22,7 @@ import { BaseEntity } from 'typeorm';
import EqualToOrNull from './Database/EqualToOrNull';
import NotEqual from './Database/NotEqual';
import { CheckOn, FilterType } from './Monitor/CriteriaFilter';
import CallRequest from './Call/CallRequest';
export enum ObjectType {
ObjectID = 'ObjectID',
@@ -122,6 +123,7 @@ export type JSONValue =
| Array<JSONValue>
| Array<Permission>
| Array<JSONValue>
| CallRequest
| undefined
| null;

View File

@@ -10,6 +10,16 @@ import SerializableObjectDictionary from './SerializableObjectDictionary';
import JSON5 from 'json5';
export default class JSONFunctions {
public static isEmptyObject(
obj: JSONObject | BaseModel | null | undefined
): boolean {
if (!obj) {
return true;
}
return Object.keys(obj).length === 0;
}
public static toJSON(
model: BaseModel,
modelType: { new (): BaseModel }
@@ -159,9 +169,13 @@ export default class JSONFunctions {
}
public static fromJSONObject<T extends BaseModel>(
json: JSONObject,
json: JSONObject | T,
type: { new (): T }
): T {
if (json instanceof BaseModel) {
return json;
}
return this.fromJSON<T>(json, type) as T;
}

View File

@@ -0,0 +1,6 @@
enum MailStatus {
Success = 'Success',
Error = 'Error',
}
export default MailStatus;

View File

@@ -4,4 +4,7 @@ export interface CriteriaIncident {
title: string;
description: string;
incidentSeverityId?: ObjectID | undefined;
autoResolveIncident?: boolean | undefined;
id: string;
onCallPolicyIds?: Array<ObjectID> | undefined;
}

View File

@@ -117,6 +117,9 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
title: `${arg.monitorType} monitor is offline`,
description: `${arg.monitorType} monitor is currently offline.`,
incidentSeverityId: arg.incidentSeverityId,
autoResolveIncident: true,
id: ObjectID.generate().toString(),
onCallPolicyIds: [],
},
],
changeMonitorStatus: true,
@@ -151,6 +154,9 @@ export default class MonitorCriteriaInstance extends DatabaseProperty {
title: `${arg.monitorType} monitor is offline`,
description: `${arg.monitorType} monitor is currently offline.`,
incidentSeverityId: arg.incidentSeverityId,
autoResolveIncident: true,
id: ObjectID.generate().toString(),
onCallPolicyIds: [],
},
],
changeMonitorStatus: true,

View File

@@ -0,0 +1,7 @@
enum NoticationRuleType {
ON_CALL_INCIDENT_CREATED = 'When incident is created during on call',
WHEN_USER_GOES_ON_CALL = 'When user goes on call',
WHEN_USER_GOES_OFF_CALL = 'When user goes off call',
}
export default NoticationRuleType;

View File

@@ -0,0 +1,25 @@
enum NotificationSettingEventType {
// Incident
SEND_INCIDENT_CREATED_OWNER_NOTIFICATION = 'Send incident created notification when I am the owner of the incident',
SEND_INCIDENT_NOTE_POSTED_OWNER_NOTIFICATION = 'Send incident note posted notification when I am the owner of the incident',
SEND_INCIDENT_STATE_CHANGED_OWNER_NOTIFICATION = 'Send incident state changed notification when I am the owner of the incident',
SEND_INCIDENT_OWNER_ADDED_NOTIFICATION = 'Send notification when I am added as a owner to the incident',
// Monitors
SEND_MONITOR_OWNER_ADDED_NOTIFICATION = 'Send notification when I am added as a owner to the monitor',
SEND_MONITOR_CREATED_OWNER_NOTIFICATION = 'Send monitor created notification when I am the owner of the monitor',
SEND_MONITOR_STATUS_CHANGED_OWNER_NOTIFICATION = 'Send monitor status changed notification when I am the owner of the monitor',
// Scheduled Maintenance
SEND_SCHEDULED_MAINTENANCE_CREATED_OWNER_NOTIFICATION = 'Send scheduled maintenance created notification when I am the owner of the scheduled maintenance',
SEND_SCHEDULED_MAINTENANCE_NOTE_POSTED_OWNER_NOTIFICATION = 'Send scheduled maintenance note posted notification when I am the owner of the scheduled maintenance',
SEND_SCHEDULED_MAINTENANCE_OWNER_ADDED_NOTIFICATION = 'Send notification when I am added as a owner to the scheduled maintenance',
SEND_SCHEDULED_MAINTENANCE_STATE_CHANGED_OWNER_NOTIFICATION = 'Send scheduled maintenance state changed notification when I am the owner of the scheduled maintenance',
// Status Page
SEND_STATUS_PAGE_ANNOUNCEMENT_CREATED_OWNER_NOTIFICATION = 'Send status page announcement created notification when I am the owner of the status page',
SEND_STATUS_PAGE_CREATED_OWNER_NOTIFICATION = 'Send status page created notification when I am the owner of the status page',
SEND_STATUS_PAGE_OWNER_ADDED_NOTIFICATION = 'Send notification when I am added as a owner to the status page',
}
export default NotificationSettingEventType;

View File

@@ -19,6 +19,10 @@ export default class ObjectID extends DatabaseProperty {
this.id = id;
}
public equals(other: ObjectID): boolean {
return this.id.toString() === other.id.toString();
}
public override toString(): string {
return this.id;
}

View File

@@ -0,0 +1,10 @@
enum OnCallDutyExecutionLogTimelineStatus {
Skipped = 'Skipped',
Started = 'Started',
Executing = 'Executing',
SuccessfullyAcknowledged = 'Successfully Acknowledged',
NotificationSent = 'Notification Sent',
Error = 'Error',
}
export default OnCallDutyExecutionLogTimelineStatus;

View File

@@ -0,0 +1,7 @@
enum OnCallDutyPolicyStatus {
SuccessfullyAcknowledged = 'Successfully Acknowledged',
FailedToAcknowledge = 'Failed to Acknowledge',
Error = 'Error',
}
export default OnCallDutyPolicyStatus;

View File

@@ -0,0 +1,9 @@
enum OnCallDutyPolicyStatus {
Scheduled = 'Scheduled',
Started = 'Started',
Executing = 'Executing',
Completed = 'Execution Completed',
Error = 'Error',
}
export default OnCallDutyPolicyStatus;

View File

@@ -63,6 +63,11 @@ enum Permission {
CanEditMonitorCustomField = 'CanEditMonitorCustomField',
CanReadMonitorCustomField = 'CanReadMonitorCustomField',
CanCreateOnCallDutyPolicyCustomField = 'CanCreateOnCallDutyPolicyCustomField',
CanDeleteOnCallDutyPolicyCustomField = 'CanDeleteOnCallDutyPolicyCustomField',
CanEditOnCallDutyPolicyCustomField = 'CanEditOnCallDutyPolicyCustomField',
CanReadOnCallDutyPolicyCustomField = 'CanReadOnCallDutyPolicyCustomField',
CanCreateScheduledMaintenanceCustomField = 'CanCreateScheduledMaintenanceCustomField',
CanDeleteScheduledMaintenanceCustomField = 'CanDeleteScheduledMaintenanceCustomField',
CanEditScheduledMaintenanceCustomField = 'CanEditScheduledMaintenanceCustomField',
@@ -73,10 +78,9 @@ enum Permission {
CanEditMonitorProbe = 'CanEditMonitorProbe',
CanReadMonitorProbe = 'CanReadMonitorProbe',
CanCreateSmsLog = 'CanCreateSmsLog',
CanDeleteSmsLog = 'CanDeleteSmsLog',
CanEditSmsLog = 'CanEditSmsLog',
CanReadSmsLog = 'CanReadSmsLog',
CanReadEmailLog = 'CanReadEmailLog',
CanReadCallLog = 'CanReadCallLog',
CanCreateIncidentOwnerTeam = 'CanCreateIncidentOwnerTeam',
CanDeleteIncidentOwnerTeam = 'CanDeleteIncidentOwnerTeam',
@@ -251,6 +255,12 @@ enum Permission {
CanReadIncidentStateTimeline = 'CanReadIncidentStateTimeline',
CanDeleteIncidentStateTimeline = 'CanDeleteIncidentStateTimeline',
// Incident Status Permissions (Owner + Admin Permission by default)
CanCreateMonitorStatusTimeline = 'CanCreateMonitorStatusTimeline',
CanEditMonitorStatusTimeline = 'CanEditMonitorStatusTimeline',
CanReadMonitorStatusTimeline = 'CanReadMonitorStatusTimeline',
CanDeleteMonitorStatusTimeline = 'CanDeleteMonitorStatusTimeline',
// MonitorStatus Permissions (Owner + Admin Permission by default)
CanCreateProjectMonitorStatus = 'CanCreateProjectMonitorStatus',
CanEditProjectMonitorStatus = 'CanEditProjectMonitorStatus',
@@ -296,10 +306,31 @@ enum Permission {
CanReadProjectStatusPage = 'CanReadProjectStatusPage',
// Resource Permissions (Team Permission)
CanCreateProjectOnCallDuty = 'CanCreateProjectOnCallDuty',
CanEditProjectOnCallDuty = 'CanEditProjectOnCallDuty',
CanDeleteProjectOnCallDuty = 'CanDeleteProjectOnCallDuty',
CanReadProjectOnCallDuty = 'CanReadProjectOnCallDuty',
CanCreateProjectOnCallDutyPolicy = 'CanCreateProjectOnCallDutyPolicy',
CanEditProjectOnCallDutyPolicy = 'CanEditProjectOnCallDutyPolicy',
CanDeleteProjectOnCallDutyPolicy = 'CanDeleteProjectOnCallDutyPolicy',
CanReadProjectOnCallDutyPolicy = 'CanReadProjectOnCallDutyPolicy',
CanReadProjectOnCallDutyPolicyExecutionLogTimeline = 'CanReadProjectOnCallDutyPolicyExecutionLogTimeline',
CanReadProjectOnCallDutyPolicyExecutionLog = 'CanReadProjectOnCallDutyPolicyExecutionLog',
// Resource Permissions (Team Permission)
CanCreateProjectOnCallDutyPolicyEscalationRule = 'CanCreateProjectOnCallDutyPolicyEscalationRule',
CanEditProjectOnCallDutyPolicyEscalationRule = 'CanEditProjectOnCallDutyPolicyEscalationRule',
CanDeleteProjectOnCallDutyPolicyEscalationRule = 'CanDeleteProjectOnCallDutyPolicyEscalationRule',
CanReadProjectOnCallDutyPolicyEscalationRule = 'CanReadProjectOnCallDutyPolicyEscalationRule',
// Resource Permissions (Team Permission)
CanCreateProjectOnCallDutyPolicyEscalationRuleUser = 'CanCreateProjectOnCallDutyPolicyEscalationRuleUser',
CanEditProjectOnCallDutyPolicyEscalationRuleUser = 'CanEditProjectOnCallDutyPolicyEscalationRuleUser',
CanDeleteProjectOnCallDutyPolicyEscalationRuleUser = 'CanDeleteProjectOnCallDutyPolicyEscalationRuleUser',
CanReadProjectOnCallDutyPolicyEscalationRuleUser = 'CanReadProjectOnCallDutyPolicyEscalationRuleUser',
// Resource Permissions (Team Permission)
CanCreateProjectOnCallDutyPolicyEscalationRuleTeam = 'CanCreateProjectOnCallDutyPolicyEscalationRuleTeam',
CanEditProjectOnCallDutyPolicyEscalationRuleTeam = 'CanEditProjectOnCallDutyPolicyEscalationRuleTeam',
CanDeleteProjectOnCallDutyPolicyEscalationRuleTeam = 'CanDeleteProjectOnCallDutyPolicyEscalationRuleTeam',
CanReadProjectOnCallDutyPolicyEscalationRuleTeam = 'CanReadProjectOnCallDutyPolicyEscalationRuleTeam',
// Project SMTP Config (Team Permission)
CanCreateProjectSMTPConfig = 'CanCreateProjectSMTPConfig',
@@ -449,7 +480,7 @@ export class PermissionHelper {
permission: Permission.ProjectOwner,
title: 'Project Owner',
description:
'Owner of this project, manages billing, inviting other admins to this project, and can delete this project.',
'Owner of this project. Manages billing, inviting other admins to this project, and can delete this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
@@ -465,7 +496,14 @@ export class PermissionHelper {
permission: Permission.ProjectAdmin,
title: 'Project Admin',
description:
'Owner of this project, manages billing, inviting other admins to this project, and can delete this project.',
'Admin of this project. Manages team members in this project, however cannot manage billing or delete this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.ProjectUser,
title: 'Project User',
description: 'User of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
@@ -654,6 +692,39 @@ export class PermissionHelper {
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateMonitorStatusTimeline,
title: 'Can Create Monitor Status Timeline',
description:
'This permission can create Monitor Status history of an incident in this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanDeleteMonitorStatusTimeline,
title: 'Can Delete Monitor Status Timeline',
description:
'This permission can delete Monitor Status history of an incident in this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanEditMonitorStatusTimeline,
title: 'Can Edit Monitor Status Timeline',
description:
'This permission can edit Monitor Status history of an incident in this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanReadMonitorStatusTimeline,
title: 'Can Read Monitor Status Timeline',
description:
'This permission can read Monitor Status history of an incident in this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateProjectMonitorStatus,
title: 'Can Create Monitor Status',
@@ -1446,32 +1517,163 @@ export class PermissionHelper {
},
{
permission: Permission.CanCreateProjectOnCallDuty,
title: 'Can Create On-Call Duty',
permission:
Permission.CanReadProjectOnCallDutyPolicyExecutionLogTimeline,
title: 'Can Read On-Call Duty Policy Execution Log Timeline',
description:
'This permission can read teams in on-call duty execution log timeline.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanReadProjectOnCallDutyPolicyExecutionLog,
title: 'Can Read On-Call Duty Policy Execution Log',
description:
'This permission can read teams in on-call duty execution log.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanCreateProjectOnCallDutyPolicyEscalationRuleTeam,
title: 'Can Create On-Call Duty Policy Escalation Rule',
description:
'This permission can create teams in on-call duty escalation rule this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanDeleteProjectOnCallDutyPolicyEscalationRuleTeam,
title: 'Can Delete On-Call Duty Policy Escalation Rule Team',
description:
'This permission can delete teams in on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanEditProjectOnCallDutyPolicyEscalationRuleTeam,
title: 'Can Edit On-Call Duty Policy Escalation Rule Team',
description:
'This permission can edit teams in on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanReadProjectOnCallDutyPolicyEscalationRuleTeam,
title: 'Can Read On-Call Duty Policy Escalation Rule Team',
description:
'This permission can read teams in on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanCreateProjectOnCallDutyPolicyEscalationRuleUser,
title: 'Can Create On-Call Duty Policy Escalation Rule User',
description:
'This permission can create on-call duty escalation rule this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanDeleteProjectOnCallDutyPolicyEscalationRuleUser,
title: 'Can Delete On-Call Duty Policy Escalation Rule User',
description:
'This permission can delete on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanEditProjectOnCallDutyPolicyEscalationRuleUser,
title: 'Can Edit On-Call Duty Policy Escalation Rule User',
description:
'This permission can edit on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanReadProjectOnCallDutyPolicyEscalationRuleUser,
title: 'Can Read On-Call Duty Policy Escalation Rule User',
description:
'This permission can read on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanCreateProjectOnCallDutyPolicyEscalationRule,
title: 'Can Create On-Call Duty Policy Escalation Rule',
description:
'This permission can create on-call duty escalation rule this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanDeleteProjectOnCallDutyPolicyEscalationRule,
title: 'Can Delete On-Call Duty Policy Escalation Rule',
description:
'This permission can delete on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanEditProjectOnCallDutyPolicyEscalationRule,
title: 'Can Edit On-Call Duty Policy Escalation Rule',
description:
'This permission can edit on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission:
Permission.CanReadProjectOnCallDutyPolicyEscalationRule,
title: 'Can Read On-Call Duty Policy Escalation Rule',
description:
'This permission can read on-call duty escalation rule of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission: Permission.CanCreateProjectOnCallDutyPolicy,
title: 'Can Create On-Call Duty Policy',
description:
'This permission can create on-call duty this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission: Permission.CanDeleteProjectOnCallDuty,
title: 'Can Delete On-Call Duty',
permission: Permission.CanDeleteProjectOnCallDutyPolicy,
title: 'Can Delete On-Call Duty Policy',
description:
'This permission can delete on-call duty of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission: Permission.CanEditProjectOnCallDuty,
title: 'Can Edit On-Call Duty',
permission: Permission.CanEditProjectOnCallDutyPolicy,
title: 'Can Edit On-Call Duty Policy',
description:
'This permission can edit on-call duty of this project.',
isAssignableToTenant: true,
isAccessControlPermission: true,
},
{
permission: Permission.CanReadProjectOnCallDuty,
title: 'Can Read On-Call Duty',
permission: Permission.CanReadProjectOnCallDutyPolicy,
title: 'Can Read On-Call Duty Policy',
description:
'This permission can read on-call duty of this project.',
isAssignableToTenant: true,
@@ -1541,6 +1743,39 @@ export class PermissionHelper {
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateOnCallDutyPolicyCustomField,
title: 'Can Create On Call Policy Custom Field',
description:
'This permission can create On Call Policy Custom Field this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanDeleteOnCallDutyPolicyCustomField,
title: 'Can Delete On Call Policy Custom Field',
description:
'This permission can delete On Call Policy Custom Field of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanEditOnCallDutyPolicyCustomField,
title: 'Can Edit On Call Policy Custom Field',
description:
'This permission can edit On Call Policy Custom Field of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanReadOnCallDutyPolicyCustomField,
title: 'Can Read On Call Policy Custom Field',
description:
'This permission can read On Call Policy Custom Field of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateMonitorCustomField,
title: 'Can Create Monitor Custom Field',
@@ -1673,29 +1908,6 @@ export class PermissionHelper {
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateSmsLog,
title: 'Can Create SMS Log',
description: 'This permission can create SMS Log this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanDeleteSmsLog,
title: 'Can Delete SMS Log',
description:
'This permission can delete SMS Log of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanEditSmsLog,
title: 'Can Edit SMS Log',
description:
'This permission can edit SMS Log of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanReadSmsLog,
title: 'Can Read SMS Log',
@@ -1705,6 +1917,15 @@ export class PermissionHelper {
isAccessControlPermission: false,
},
{
permission: Permission.CanReadCallLog,
title: 'Can Read Call Log',
description:
'This permission can read Call Logs of this project.',
isAssignableToTenant: true,
isAccessControlPermission: false,
},
{
permission: Permission.CanCreateMonitorProbe,
title: 'Can Create Monitor Probe',

View File

@@ -19,7 +19,7 @@ export default class Phone extends DatabaseProperty {
* }
*/
const re: RegExp =
/^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/; // regex for international phone numbers format based on (ITU-T E.123)
/^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,7}$/; // regex for international phone numbers format based on (ITU-T E.123)
const isValid: boolean = re.test(v);
if (!isValid) {
throw new BadDataException(`Phone is not in valid format: ${v}`);

View File

@@ -5,4 +5,5 @@ export default interface ProbeApiIngestResponse {
ingestedMonitorStepId?: ObjectID | undefined;
nextMonitorStepId?: ObjectID | undefined;
criteriaMetId?: string | undefined;
rootCause: string | null;
}

View File

@@ -10,4 +10,5 @@ export default interface ProbeMonitorResponse {
responseBody?: string | JSONObject | undefined;
monitorStepId: ObjectID;
monitorId: ObjectID;
probeId: ObjectID;
}

9
Common/Types/SMS/SMS.ts Normal file
View File

@@ -0,0 +1,9 @@
import Phone from '../Phone';
export interface SMSMessage {
message: string;
}
export default interface SMS extends SMSMessage {
to: Phone;
}

View File

@@ -26,9 +26,11 @@ import HashedString from './HashedString';
import InBetween from './Database/InBetween';
import NotNull from './Database/NotNull';
import IsNull from './Database/IsNull';
import OneUptimeDate from './Date';
const SerializableObjectDictionary: Dictionary<any> = {
[ObjectType.Phone]: Phone,
[ObjectType.DateTime]: OneUptimeDate,
[ObjectType.ObjectID]: ObjectID,
[ObjectType.Name]: Name,
[ObjectType.EqualToOrNull]: EqualToOrNull,

View File

@@ -16,6 +16,22 @@ export default class Text {
return result;
}
public static generateRandomNumber(length?: number): string {
if (!length) {
length = 10;
}
let result: string = '';
const characters: string = '12134567890';
const charactersLength: number = characters.length;
for (let i: number = 0; i < length; i++) {
result += characters.charAt(
Math.floor(Math.random() * charactersLength)
);
}
return result;
}
public static convertNumberToWords(num: number): string {
const words: Array<string> = [
'first',

View File

@@ -0,0 +1,5 @@
enum UserNotificationEventType {
IncidentCreated = 'Incident Created',
}
export default UserNotificationEventType;

View File

@@ -0,0 +1,9 @@
enum UserNotificationExecutionStatus {
Scheduled = 'Scheduled',
Started = 'Strated',
Executing = 'Executing',
Completed = 'Completed',
Error = 'Error',
}
export default UserNotificationExecutionStatus;

View File

@@ -0,0 +1,9 @@
enum UserNotificationStatus {
Sent = 'Sent',
Acknowledged = 'Acknowledged',
Error = 'Error',
Sending = 'Sending',
Skipped = 'Skipped',
}
export default UserNotificationStatus;

View File

@@ -1,7 +1,8 @@
import axios, { AxiosResponse } from 'axios';
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import Headers from './API/Headers';
import URL from './API/URL';
import HTML from './Html';
import HTTPMethod from './API/HTTPMethod';
export interface WebsiteResponse {
url: URL;
@@ -13,18 +14,32 @@ export interface WebsiteResponse {
}
export default class WebsiteRequest {
public static async get(
public static async fetch(
url: URL,
options: {
headers?: Headers | undefined;
timeout?: number | undefined;
isHeadRequest?: boolean | undefined;
}
): Promise<WebsiteResponse> {
// use axios to fetch an HTML page
const response: AxiosResponse = await axios.get(url.toString(), {
headers: options.headers || {},
const axiosOptions: AxiosRequestConfig = {
timeout: options.timeout || 5000,
});
method: HTTPMethod.GET,
};
if (options.headers) {
axiosOptions.headers = options.headers;
}
if (options.isHeadRequest) {
axiosOptions.method = HTTPMethod.HEAD;
}
// use axios to fetch an HTML page
const response: AxiosResponse = await axios(
url.toString(),
axiosOptions
);
// return the response
return {

View File

@@ -160,7 +160,7 @@ export default class BaseModelComponent {
arguments: [],
returnValues: [
{
id: 'data',
id: 'model',
name: `${model.singularName}`,
description: `${model.singularName} deleted in the database`,
type: ComponentInputType.BaseModel,
@@ -300,7 +300,7 @@ export default class BaseModelComponent {
],
returnValues: [
{
id: 'data',
id: 'model',
name: `${model.singularName}`,
description: `${model.singularName} created in the database`,
type: ComponentInputType.BaseModel,
@@ -443,7 +443,7 @@ export default class BaseModelComponent {
],
returnValues: [
{
id: 'data',
id: 'model',
name: `${model.singularName}`,
description: `Updated ${model.singularName}`,
type: ComponentInputType.BaseModel,

View File

@@ -88,6 +88,24 @@ export default class API {
);
}
public async head<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
path: Route,
data?: JSONObject | JSONArray,
headers?: Headers
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
return await API.head<T>(
new URL(
this.protocol,
this.hostname,
this.baseRoute.addRoute(path)
),
data,
headers
);
}
public async put<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
@@ -179,6 +197,16 @@ export default class API {
return await this.fetch(HTTPMethod.DELETE, url, data, headers);
}
public static async head<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(
url: URL,
data?: JSONObject | JSONArray,
headers?: Headers
): Promise<HTTPResponse<T> | HTTPErrorResponse> {
return await this.fetch(HTTPMethod.HEAD, url, data, headers);
}
public static async put<
T extends JSONObject | JSONArray | BaseModel | Array<BaseModel>
>(

View File

@@ -3,3 +3,4 @@ export const EVERY_DAY: string = '0 8 * * *';
export const EVERY_HOUR: string = '1 * * * *';
export const EVERY_FIVE_MINUTE: string = '*/5 * * * *';
export const EVERY_FIVE_SECONDS: string = '*/5 * * * * *';
export const EVERY_WEEK: string = '0 0 * * 0';

View File

@@ -4095,9 +4095,9 @@
}
},
"node_modules/tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"dev": true,
"dependencies": {
"psl": "^1.1.33",
@@ -4588,9 +4588,9 @@
}
},
"node_modules/word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
@@ -7774,9 +7774,9 @@
}
},
"tough-cookie": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.2.tgz",
"integrity": "sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==",
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.3.tgz",
"integrity": "sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==",
"dev": true,
"requires": {
"psl": "^1.1.33",
@@ -8067,9 +8067,9 @@
}
},
"word-wrap": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
"integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.4.tgz",
"integrity": "sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==",
"dev": true
},
"wrap-ansi": {

View File

@@ -1,52 +0,0 @@
ONEUPTIME_SECRET={{ .Env.ONEUPTIME_SECRET }}
DATABASE_PORT={{ .Env.DATABASE_PORT }}
DATABASE_USERNAME={{ .Env.DATABASE_USERNAME }}
DATABASE_PASSWORD={{ .Env.DATABASE_PASSWORD }}
DATABASE_NAME={{ .Env.DATABASE_NAME }}
DATABASE_HOST={{ .Env.DATABASE_HOST }}
REDIS_PASSWORD={{ .Env.REDIS_PASSWORD }}
REDIS_HOST={{ .Env.REDIS_HOST }}
REDIS_PORT={{ .Env.REDIS_PORT }}
ENCRYPTION_SECRET={{ .Env.ENCRYPTION_SECRET }}
DISABLE_SIGNUP={{ .Env.DISABLE_SIGNUP }}
REALTIME_HOSTNAME={{ .Env.REALTIME_HOSTNAME }}
NOTIFICATION_HOSTNAME={{ .Env.NOTIFICATION_HOSTNAME }}
DASHBOARD_HOSTNAME=d{{ .Env.DASHBOARD_HOSTNAME }}
DASHBOARD_API_HOSTNAME={{ .Env.DASHBOARD_API_HOSTNAME }}
PROBE_API_HOSTNAME={{ .Env.DATA_INGESTOR_HOSTNAME }}
DATA_INGESTOR_HOSTNAME={{ .Env.DATA_INGESTOR_HOSTNAME }}
ACCOUNTS_HOSTNAME={{ .Env.ACCOUNTS_HOSTNAME }}
HOME_HOSTNAME={{ .Env.HOME_HOSTNAME }}
WORKER_HOSTNAME={{ .Env.WORKER_HOSTNAME }}
WORKFLOW_HOSTNAME={{ .Env.WORKFLOW_HOSTNAME }}
BILLING_PRIVATE_KEY={{ .Env.BILLING_PRIVATE_KEY }}
BILLING_PUBLIC_KEY={{ .Env.BILLING_PUBLIC_KEY }}
BILLING_ENABLED={{ .Env.BILLING_ENABLED }}
DOMAIN={{ .Env.DOMAIN }}
HTTP_PROTOCOL={{ .Env.HTTP_PROTOCOL }}
REALTIME_ROUTE={{ .Env.REALTIME_ROUTE }}
NOTIFICATION_ROUTE={{ .Env.NOTIFICATION_ROUTE }}
DASHBOARD_ROUTE={{ .Env.DASHBOARD_ROUTE }}
DASHBOARD_API_ROUTE={{ .Env.DASHBOARD_API_ROUTE }}
PROBE_API_ROUTE={{ .Env.PROBE_API_ROUTE }}
DATA_INGESTOR_ROUTE={{ .Env.DATA_INGESTOR_ROUTE }}
ACCOUNTS_ROUTE={{ .Env.ACCOUNTS_ROUTE }}
HOME_ROUTE={{ .Env.HOME_ROUTE }}
HELMCHARTS_ROUTE={{ .Env.HELMCHARTS_ROUTE }}
API_REFERENCE_ROUTE={{ .Env.API_REFERENCE_ROUTE }}
IDENTITY_ROUTE={{ .Env.IDENTITY_ROUTE }}
FILE_ROUTE={{ .Env.FILE_ROUTE }}
WORKFLOW_ROUTE={{ .Env.WORKFLOW_ROUTE }}
STATUS_PAGE_ROUTE={{ .Env.STATUS_PAGE_ROUTE }}
IS_SERVER=true
ANALYTICS_KEY={{ .Env.ANALYTICS_KEY }}
ANALYTICS_HOST={{ .Env.ANALYTICS_HOST }}

View File

@@ -609,6 +609,7 @@ export default class StatusPageAPI extends BaseAPI<
projectId: statusPage.projectId!,
},
select: {
createdAt: true,
note: true,
incidentId: true,
},
@@ -792,6 +793,7 @@ export default class StatusPageAPI extends BaseAPI<
projectId: statusPage.projectId!,
},
select: {
createdAt: true,
note: true,
scheduledMaintenanceId: true,
},
@@ -1340,6 +1342,7 @@ export default class StatusPageAPI extends BaseAPI<
projectId: statusPage.projectId!,
},
select: {
createdAt: true,
note: true,
scheduledMaintenanceId: true,
},
@@ -1696,6 +1699,7 @@ export default class StatusPageAPI extends BaseAPI<
projectId: statusPage.projectId!,
},
select: {
createdAt: true,
note: true,
incidentId: true,
},

View File

@@ -0,0 +1,122 @@
import UserCall from 'Model/Models/UserCall';
import UserCallService, {
Service as UserCallServiceType,
} from '../Services/UserCallService';
import BaseAPI from './BaseAPI';
import UserMiddleware from '../Middleware/UserAuthorization';
import {
ExpressRequest,
ExpressResponse,
OneUptimeRequest,
} from '../Utils/Express';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Response from '../Utils/Response';
import UserSMS from 'Model/Models/UserSMS';
export default class UserCallAPI extends BaseAPI<
UserCall,
UserCallServiceType
> {
public constructor() {
super(UserCall, UserCallService);
this.router.post(
`/user-call/verify`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
if (!req.body.code) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
// Check if the code matches and verify the phone number.
const item: UserSMS | null = await this.service.findOneById({
id: req.body['itemId'],
props: {
isRoot: true,
},
select: {
userId: true,
verificationCode: true,
},
});
if (!item) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Item not found')
);
}
//cehck user id
if (
item.userId?.toString() !==
(
req as OneUptimeRequest
)?.userAuthorization?.userId?.toString()
) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid user ID')
);
}
if (item.verificationCode !== req.body['code']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
await this.service.updateOneById({
id: item.id!,
props: {
isRoot: true,
},
data: {
isVerified: true,
},
});
return Response.sendEmptyResponse(req, res);
}
);
this.router.post(
`/user-call/resend-verification-code`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
await this.service.resendVerificationCode(req.body.itemId);
return Response.sendEmptyResponse(req, res);
}
);
}
}

View File

@@ -0,0 +1,123 @@
import UserEmail from 'Model/Models/UserEmail';
import UserEmailService, {
Service as UserEmailServiceType,
} from '../Services/UserEmailService';
import BaseAPI from './BaseAPI';
import {
ExpressRequest,
ExpressResponse,
OneUptimeRequest,
} from '../Utils/Express';
import UserMiddleware from '../Middleware/UserAuthorization';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Response from '../Utils/Response';
export default class UserEmailAPI extends BaseAPI<
UserEmail,
UserEmailServiceType
> {
public constructor() {
super(UserEmail, UserEmailService);
this.router.post(
`${new this.entityType().getCrudApiPath()?.toString()}/verify`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
if (!req.body.code) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
// Check if the code matches and verify the email.
const item: UserEmail | null = await this.service.findOneById({
id: req.body['itemId'],
props: {
isRoot: true,
},
select: {
userId: true,
verificationCode: true,
},
});
if (!item) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Item not found')
);
}
//cehck user id
if (
item.userId?.toString() !==
(
req as OneUptimeRequest
)?.userAuthorization?.userId?.toString()
) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid user ID')
);
}
if (item.verificationCode !== req.body['code']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
await this.service.updateOneById({
id: item.id!,
props: {
isRoot: true,
},
data: {
isVerified: true,
},
});
return Response.sendEmptyResponse(req, res);
}
);
this.router.post(
`${new this.entityType()
.getCrudApiPath()
?.toString()}/resend-verification-code`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
await this.service.resendVerificationCode(req.body.itemId);
return Response.sendEmptyResponse(req, res);
}
);
}
}

View File

@@ -0,0 +1,161 @@
import UserOnCallLogTimeline from 'Model/Models/UserOnCallLogTimeline';
import UserOnCallLogTimelineService, {
Service as UserNotificationLogTimelineServiceType,
} from '../Services/UserOnCallLogTimelineService';
import BaseAPI from './BaseAPI';
import {
ExpressRequest,
ExpressResponse,
OneUptimeRequest,
} from '../Utils/Express';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Response from '../Utils/Response';
import ObjectID from 'Common/Types/ObjectID';
import { JSONObject } from 'Common/Types/JSON';
import NotificationMiddleware from '../Middleware/NotificationMiddleware';
import OneUptimeDate from 'Common/Types/Date';
import URL from 'Common/Types/API/URL';
import { DashboardRoute, Domain, HttpProtocol } from '../Config';
import UserNotificationStatus from 'Common/Types/UserNotification/UserNotificationStatus';
export default class UserNotificationLogTimelineAPI extends BaseAPI<
UserOnCallLogTimeline,
UserNotificationLogTimelineServiceType
> {
public constructor() {
super(UserOnCallLogTimeline, UserOnCallLogTimelineService);
this.router.post(
`${new this.entityType()
.getCrudApiPath()
?.toString()}/call/gather-input/:itemId`,
NotificationMiddleware.isValidCallNotificationRequest,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.params['itemId']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
const token: JSONObject = (req as any).callTokenData;
const itemId: ObjectID = new ObjectID(req.params['itemId']);
const timelineItem: UserOnCallLogTimeline | null =
await this.service.findOneById({
id: itemId,
select: {
_id: true,
projectId: true,
triggeredByIncidentId: true,
},
props: {
isRoot: true,
},
});
if (!timelineItem) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item Id')
);
}
// check digits.
if (req.body['Digits'] === '1') {
// then ack incident
await this.service.updateOneById({
id: itemId,
data: {
acknowledgedAt: OneUptimeDate.getCurrentDate(),
isAcknowledged: true,
status: UserNotificationStatus.Acknowledged,
statusMessage: 'Notification Acknowledged',
},
props: {
isRoot: true,
},
});
}
return NotificationMiddleware.sendResponse(
req,
res,
token as any
);
}
);
this.router.get(
`${new this.entityType()
.getCrudApiPath()
?.toString()}/acknowledge/:itemId`,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.params['itemId']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Item ID is required')
);
}
const itemId: ObjectID = new ObjectID(req.params['itemId']);
const timelineItem: UserOnCallLogTimeline | null =
await this.service.findOneById({
id: itemId,
select: {
_id: true,
projectId: true,
triggeredByIncidentId: true,
},
props: {
isRoot: true,
},
});
if (!timelineItem) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item Id')
);
}
await this.service.updateOneById({
id: itemId,
data: {
acknowledgedAt: OneUptimeDate.getCurrentDate(),
isAcknowledged: true,
status: UserNotificationStatus.Acknowledged,
statusMessage: 'Notification Acknowledged',
},
props: {
isRoot: true,
},
});
// redirect to dashboard to incidents page.
return Response.redirect(
req,
res,
new URL(
HttpProtocol,
Domain,
DashboardRoute.addRoute(
`/${timelineItem.projectId?.toString()}/incidents/${timelineItem.triggeredByIncidentId!.toString()}`
)
)
);
}
);
}
}

View File

@@ -0,0 +1,118 @@
import UserSMS from 'Model/Models/UserSMS';
import UserSMSService, {
Service as UserSMSServiceType,
} from '../Services/UserSmsService';
import BaseAPI from './BaseAPI';
import UserMiddleware from '../Middleware/UserAuthorization';
import {
ExpressRequest,
ExpressResponse,
OneUptimeRequest,
} from '../Utils/Express';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Response from '../Utils/Response';
export default class UserSMSAPI extends BaseAPI<UserSMS, UserSMSServiceType> {
public constructor() {
super(UserSMS, UserSMSService);
this.router.post(
`/user-sms/verify`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
if (!req.body.code) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
// Check if the code matches and verify the phone number.
const item: UserSMS | null = await this.service.findOneById({
id: req.body['itemId'],
props: {
isRoot: true,
},
select: {
userId: true,
verificationCode: true,
},
});
if (!item) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Item not found')
);
}
//cehck user id
if (
item.userId?.toString() !==
(
req as OneUptimeRequest
)?.userAuthorization?.userId?.toString()
) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid user ID')
);
}
if (item.verificationCode !== req.body['code']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid code')
);
}
await this.service.updateOneById({
id: item.id!,
props: {
isRoot: true,
},
data: {
isVerified: true,
},
});
return Response.sendEmptyResponse(req, res);
}
);
this.router.post(
`/user-sms/resend-verification-code`,
UserMiddleware.getUserMiddleware,
async (req: ExpressRequest, res: ExpressResponse) => {
req = req as OneUptimeRequest;
if (!req.body.itemId) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid item ID')
);
}
await this.service.resendVerificationCode(req.body.itemId);
return Response.sendEmptyResponse(req, res);
}
);
}
}

View File

@@ -28,7 +28,7 @@ export const DatabasePort: Port = new Port(
);
export const DatabaseUsername: string =
process.env['DATABASE_USERNAME'] || 'oneuptimedbuser';
process.env['DATABASE_USERNAME'] || 'postgres';
export const DatabasePassword: string =
process.env['DATABASE_PASSWORD'] || 'password';
@@ -66,6 +66,10 @@ export const WorkerHostname: Hostname = Hostname.fromString(
process.env['WORKER_HOSTNAME'] || 'worker'
);
export const LinkShortnerHostname: Route = new Route(
process.env['LINK_SHORTNER_HOSTNAME'] || 'link-shortner'
);
export const WorkflowHostname: Hostname = Hostname.fromString(
process.env['WORKFLOW_HOSTNAME'] || 'workflow'
);
@@ -124,6 +128,10 @@ export const StatusPageRoute: Route = new Route(
process.env['STATUS_PAGE_ROUTE'] || '/status-page'
);
export const LinkShortnerRoute: Route = new Route(
process.env['LINK_SHORTNER_ROUTE'] || '/l'
);
export const DashboardRoute: Route = new Route(
process.env['DASHBOARD_ROUTE'] || '/dashboard'
);

View File

@@ -0,0 +1,71 @@
import {
ExpressRequest,
ExpressResponse,
NextFunction,
OneUptimeRequest,
} from '../Utils/Express';
import Response from '../Utils/Response';
import BadDataException from 'Common/Types/Exception/BadDataException';
import JSONFunctions from 'Common/Types/JSONFunctions';
import JSONWebToken from '../Utils/JsonWebToken';
import { OnCallInputRequest } from 'Common/Types/Call/CallRequest';
import VoiceResponse from 'twilio/lib/twiml/VoiceResponse';
export default class NotificationMiddleware {
public static async sendResponse(
req: ExpressRequest,
res: ExpressResponse,
onCallInputRequest: OnCallInputRequest
): Promise<void> {
const response: VoiceResponse = new VoiceResponse();
if (onCallInputRequest[req.body['Digits']]) {
response.say(onCallInputRequest[req.body['Digits']]!.sayMessage);
} else {
response.say(onCallInputRequest['default']!.sayMessage);
}
return Response.sendXmlResponse(req, res, response.toString());
}
public static async isValidCallNotificationRequest(
req: ExpressRequest,
res: ExpressResponse,
next: NextFunction
): Promise<void> {
req = req as OneUptimeRequest;
if (!req.body['Digits']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid input')
);
}
if (!req.query['token']) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid token')
);
}
const token: string = req.query['token'] as string;
try {
(req as any).callTokenData = JSONFunctions.deserialize(
JSONWebToken.decodeJsonPayload(token)
);
} catch (e) {
return Response.sendErrorResponse(
req,
res,
new BadDataException('Invalid token')
);
}
return next();
}
}

View File

@@ -121,7 +121,8 @@ export default class UserMiddleware {
if (tenantId) {
oneuptimeRequest.tenantId = tenantId;
// check if the force sso for login is present and if it is, check if the sso token is present and if it is then allow, otherwise decline.
// update last active of project
await ProjectService.updateLastActive(tenantId);
}
if (ProjectMiddleware.hasApiKey(req)) {

View File

@@ -15,17 +15,20 @@ import Label from 'Model/Models/Label';
import QueryHelper from '../Types/Database/QueryHelper';
import APIKeyPermission from 'Model/Models/ApiKeyPermission';
import ApiKeyPermissionService from './ApiKeyPermissionService';
import BaseService from './BaseService';
enum PermissionNamespace {
GlobalPermission = 'global-permissions',
ProjectPermission = 'project-permissions',
}
export default class AccessTokenService {
public static async refreshUserAllPermissions(
userId: ObjectID
): Promise<void> {
await AccessTokenService.refreshUserGlobalAccessPermission(userId);
export class AccessTokenService extends BaseService {
public constructor() {
super();
}
public async refreshUserAllPermissions(userId: ObjectID): Promise<void> {
await this.refreshUserGlobalAccessPermission(userId);
// query for all projects user belongs to.
const teamMembers: Array<TeamMember> = await TeamMemberService.findBy({
@@ -54,14 +57,11 @@ export default class AccessTokenService {
);
for (const projectId of projectIds) {
await AccessTokenService.refreshUserTenantAccessPermission(
userId,
projectId
);
await this.refreshUserTenantAccessPermission(userId, projectId);
}
}
public static async getDefaultApiGlobalPermission(
public async getDefaultApiGlobalPermission(
projectId: ObjectID
): Promise<UserGlobalAccessPermission> {
return {
@@ -75,7 +75,7 @@ export default class AccessTokenService {
};
}
public static async getApiTenantAccessPermission(
public async getApiTenantAccessPermission(
projectId: ObjectID,
apiKeyId: ObjectID
): Promise<UserTenantAccessPermission> {
@@ -116,14 +116,14 @@ export default class AccessTokenService {
}
const permission: UserTenantAccessPermission =
AccessTokenService.getDefaultUserTenantAccessPermission(projectId);
this.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
return permission;
}
public static async refreshUserGlobalAccessPermission(
public async refreshUserGlobalAccessPermission(
userId: ObjectID
): Promise<UserGlobalAccessPermission> {
// query for all projects user belongs to.
@@ -163,7 +163,7 @@ export default class AccessTokenService {
return permissionToStore;
}
public static getDefaultUserTenantAccessPermission(
public getDefaultUserTenantAccessPermission(
projectId: ObjectID
): UserTenantAccessPermission {
const userPermissions: Array<UserPermission> = [];
@@ -189,7 +189,7 @@ export default class AccessTokenService {
return permission;
}
public static async getUserGlobalAccessPermission(
public async getUserGlobalAccessPermission(
userId: ObjectID
): Promise<UserGlobalAccessPermission | null> {
const json: JSONObject | null = await GlobalCache.getJSON(
@@ -198,9 +198,7 @@ export default class AccessTokenService {
);
if (!json) {
return await AccessTokenService.refreshUserGlobalAccessPermission(
userId
);
return await this.refreshUserGlobalAccessPermission(userId);
}
const accessPermission: UserGlobalAccessPermission =
@@ -211,7 +209,7 @@ export default class AccessTokenService {
return accessPermission;
}
public static async refreshUserTenantAccessPermission(
public async refreshUserTenantAccessPermission(
userId: ObjectID,
projectId: ObjectID
): Promise<UserTenantAccessPermission | null> {
@@ -279,7 +277,7 @@ export default class AccessTokenService {
}
const permission: UserTenantAccessPermission =
AccessTokenService.getDefaultUserTenantAccessPermission(projectId);
this.getDefaultUserTenantAccessPermission(projectId);
permission.permissions = permission.permissions.concat(userPermissions);
@@ -292,7 +290,7 @@ export default class AccessTokenService {
return permission;
}
public static async getUserTenantAccessPermission(
public async getUserTenantAccessPermission(
userId: ObjectID,
projectId: ObjectID
): Promise<UserTenantAccessPermission | null> {
@@ -307,7 +305,7 @@ export default class AccessTokenService {
}
if (!json) {
return await AccessTokenService.refreshUserTenantAccessPermission(
return await this.refreshUserTenantAccessPermission(
userId,
projectId
);
@@ -316,3 +314,5 @@ export default class AccessTokenService {
return json;
}
}
export default new AccessTokenService();

View File

@@ -0,0 +1,3 @@
export default class BaseService {
public constructor() {}
}

View File

@@ -1,18 +1,18 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/BillingInvoice';
import DatabaseService, { OnDelete, OnFind } from './DatabaseService';
import DatabaseService, { OnFind } from './DatabaseService';
import FindBy from '../Types/Database/FindBy';
import ProjectService from './ProjectService';
import BadDataException from 'Common/Types/Exception/BadDataException';
import Project from 'Model/Models/Project';
import BillingService, { Invoice } from './BillingService';
import DeleteBy from '../Types/Database/DeleteBy';
import URL from 'Common/Types/API/URL';
import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
this.setDoNotAllowDelete(true);
}
protected override async onBeforeFind(
@@ -87,12 +87,6 @@ export class Service extends DatabaseService<Model> {
return { findBy, carryForward: invoices };
}
protected override async onBeforeDelete(
_deleteBy: DeleteBy<Model>
): Promise<OnDelete<Model>> {
throw new BadDataException('Invoice should not be deleted.');
}
}
export default new Service();

View File

@@ -10,6 +10,7 @@ import Stripe from 'stripe';
import { BillingPrivateKey, IsBillingEnabled } from '../Config';
import ServerMeteredPlan from '../Types/Billing/MeteredPlan/ServerMeteredPlan';
import SubscriptionStatus from 'Common/Types/Billing/SubscriptionStatus';
import BaseService from './BaseService';
export interface PaymentMethod {
id: string;
@@ -28,16 +29,17 @@ export interface Invoice {
customerId: string | undefined;
}
export class BillingService {
private static stripe: Stripe = new Stripe(BillingPrivateKey, {
export class BillingService extends BaseService {
public constructor() {
super();
}
private stripe: Stripe = new Stripe(BillingPrivateKey, {
apiVersion: '2022-08-01',
});
// returns billing id of the customer.
public static async createCustomer(
name: string,
id: ObjectID
): Promise<string> {
public async createCustomer(name: string, id: ObjectID): Promise<string> {
if (!this.isBillingEnabled()) {
throw new BadDataException(
'Billing is not enabled for this server.'
@@ -55,7 +57,7 @@ export class BillingService {
return customer.id;
}
public static async updateCustomerName(
public async updateCustomerName(
id: string,
newName: string
): Promise<void> {
@@ -68,7 +70,7 @@ export class BillingService {
await this.stripe.customers.update(id, { name: newName });
}
public static async deleteCustomer(id: string): Promise<void> {
public async deleteCustomer(id: string): Promise<void> {
if (!this.isBillingEnabled()) {
throw new BadDataException(
'Billing is not enabled for this server.'
@@ -78,11 +80,11 @@ export class BillingService {
await this.stripe.customers.del(id);
}
public static isBillingEnabled(): boolean {
public isBillingEnabled(): boolean {
return IsBillingEnabled;
}
public static async subscribeToPlan(
public async subscribeToPlan(
projectId: ObjectID,
customerId: string,
serverMeteredPlans: Array<typeof ServerMeteredPlan>,
@@ -149,7 +151,7 @@ export class BillingService {
};
}
public static async changeQuantity(
public async changeQuantity(
subscriptionId: string,
quantity: number
): Promise<void> {
@@ -183,7 +185,7 @@ export class BillingService {
});
}
public static async addOrUpdateMeteredPricingOnSubscription(
public async addOrUpdateMeteredPricingOnSubscription(
subscriptionId: string,
meteredPlan: MeteredPlan,
quantity: number,
@@ -264,7 +266,7 @@ export class BillingService {
// complete.
}
public static async changePlan(
public async changePlan(
projectId: ObjectID,
subscriptionId: string,
serverMeteredPlans: Array<typeof ServerMeteredPlan>,
@@ -324,7 +326,7 @@ export class BillingService {
};
}
public static async deletePaymentMethod(
public async deletePaymentMethod(
customerId: string,
paymentMethodId: string
): Promise<void> {
@@ -346,9 +348,7 @@ export class BillingService {
await this.stripe.paymentMethods.detach(paymentMethodId);
}
public static async hasPaymentMethods(
customerId: string
): Promise<boolean> {
public async hasPaymentMethods(customerId: string): Promise<boolean> {
if ((await this.getPaymentMethods(customerId)).length > 0) {
return true;
}
@@ -356,7 +356,7 @@ export class BillingService {
return false;
}
public static async getPaymentMethods(
public async getPaymentMethods(
customerId: string
): Promise<Array<PaymentMethod>> {
if (!this.isBillingEnabled()) {
@@ -429,9 +429,7 @@ export class BillingService {
return paymenMethods;
}
public static async getSetupIntentSecret(
customerId: string
): Promise<string> {
public async getSetupIntentSecret(customerId: string): Promise<string> {
const setupIntent: Stripe.Response<Stripe.SetupIntent> =
await this.stripe.setupIntents.create({
customer: customerId,
@@ -446,9 +444,7 @@ export class BillingService {
return setupIntent.client_secret;
}
public static async cancelSubscription(
subscriptionId: string
): Promise<void> {
public async cancelSubscription(subscriptionId: string): Promise<void> {
if (!this.isBillingEnabled()) {
throw new BadDataException(
'Billing is not enabled for this server.'
@@ -461,7 +457,7 @@ export class BillingService {
}
}
public static async getSubscriptionStatus(
public async getSubscriptionStatus(
subscriptionId: string
): Promise<SubscriptionStatus> {
const subscription: Stripe.Subscription = await this.getSubscription(
@@ -470,7 +466,7 @@ export class BillingService {
return subscription.status as SubscriptionStatus;
}
public static async getSubscription(
public async getSubscription(
subscriptionId: string
): Promise<Stripe.Subscription> {
if (!this.isBillingEnabled()) {
@@ -485,9 +481,7 @@ export class BillingService {
return subscription;
}
public static async getInvoices(
customerId: string
): Promise<Array<Invoice>> {
public async getInvoices(customerId: string): Promise<Array<Invoice>> {
const invoices: Stripe.ApiList<Stripe.Invoice> =
await this.stripe.invoices.list({
customer: customerId,
@@ -507,7 +501,7 @@ export class BillingService {
});
}
public static async genrateInvoiceAndChargeCustomer(
public async genrateInvoiceAndChargeCustomer(
customerId: string,
itemText: string,
amountInUsd: number
@@ -540,9 +534,7 @@ export class BillingService {
}
}
public static async voidInvoice(
invoiceId: string
): Promise<Stripe.Invoice> {
public async voidInvoice(invoiceId: string): Promise<Stripe.Invoice> {
const invoice: Stripe.Invoice = await this.stripe.invoices.voidInvoice(
invoiceId
);
@@ -550,7 +542,7 @@ export class BillingService {
return invoice;
}
public static async payInvoice(
public async payInvoice(
customerId: string,
invoiceId: string
): Promise<Invoice> {
@@ -583,4 +575,4 @@ export class BillingService {
}
}
export default BillingService;
export default new BillingService();

View File

@@ -0,0 +1,12 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/CallLog';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
this.hardDeleteItemsOlderThanInDays('createdAt', 30);
}
}
export default new Service();

View File

@@ -0,0 +1,52 @@
import EmptyResponseData from 'Common/Types/API/EmptyResponse';
import HTTPResponse from 'Common/Types/API/HTTPResponse';
import Route from 'Common/Types/API/Route';
import URL from 'Common/Types/API/URL';
import { JSONObject } from 'Common/Types/JSON';
import API from 'Common/Utils/API';
import { NotificationHostname } from '../Config';
import Protocol from 'Common/Types/API/Protocol';
import ClusterKeyAuthorization from '../Middleware/ClusterKeyAuthorization';
import Phone from 'Common/Types/Phone';
import ObjectID from 'Common/Types/ObjectID';
import CallRequest from 'Common/Types/Call/CallRequest';
import BaseService from './BaseService';
export class CallService extends BaseService {
public constructor() {
super();
}
public async makeCall(
callRequest: CallRequest,
options: {
projectId?: ObjectID | undefined; // project id for sms log
from?: Phone; // from phone number
isSensitive?: boolean; // if true, message will not be logged
userOnCallLogTimelineId?: ObjectID;
}
): Promise<HTTPResponse<EmptyResponseData>> {
const body: JSONObject = {
callRequest: callRequest,
from: options.from?.toString(),
projectId: options.projectId?.toString(),
isSensitive: options.isSensitive,
userOnCallLogTimelineId:
options.userOnCallLogTimelineId?.toString(),
};
return await API.post<EmptyResponseData>(
new URL(
Protocol.HTTP,
NotificationHostname,
new Route('/call/make-call')
),
body,
{
...ClusterKeyAuthorization.getClusterKeyHeaders(),
}
);
}
}
export default new CallService();

View File

@@ -1,5 +1,5 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/GlobalConfig';
import Model from 'Model/Models/DataMigration';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
@@ -7,5 +7,4 @@ export class Service extends DatabaseService<Model> {
super(Model, postgresDatabase);
}
}
export default new Service();

View File

@@ -49,6 +49,9 @@ import Route from 'Common/Types/API/Route';
import URL from 'Common/Types/API/URL';
import ClusterKeyAuthorization from '../Middleware/ClusterKeyAuthorization';
import Text from 'Common/Types/Text';
import logger from '../Utils/Logger';
import BaseService from './BaseService';
import { getMaxLengthFromTableColumnType } from 'Common/Types/Database/ColumnLength';
export type DatabaseTriggerType = 'on-create' | 'on-update' | 'on-delete';
@@ -72,7 +75,7 @@ export interface OnUpdate<TBaseModel extends BaseModel> {
carryForward: any;
}
class DatabaseService<TBaseModel extends BaseModel> {
class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
private postgresDatabase!: PostgresDatabase;
public entityType!: { new (): TBaseModel };
private model!: TBaseModel;
@@ -94,10 +97,13 @@ class DatabaseService<TBaseModel extends BaseModel> {
this._hardDeleteItemsOlderThanDays = v;
}
public doNotAllowDelete: boolean = false;
public constructor(
modelType: { new (): TBaseModel },
postgresDatabase?: PostgresDatabase
) {
super();
this.entityType = modelType;
this.model = new modelType();
this.modelName = modelType.name;
@@ -107,6 +113,10 @@ class DatabaseService<TBaseModel extends BaseModel> {
}
}
public setDoNotAllowDelete(doNotAllowDelete: boolean): void {
this.doNotAllowDelete = doNotAllowDelete;
}
public hardDeleteItemsOlderThanInDays(
columnName: string,
olderThan: number
@@ -151,7 +161,21 @@ class DatabaseService<TBaseModel extends BaseModel> {
return true;
}
protected checkRequiredFields(data: TBaseModel): void {
protected generateDefaultValues(data: TBaseModel): TBaseModel {
const tableColumns: Array<string> = data.getTableColumns().columns;
for (const column of tableColumns) {
const metadata: TableColumnMetadata =
data.getTableColumnMetadata(column);
if (metadata.forceGetDefaultValueOnCreate) {
(data as any)[column] = metadata.forceGetDefaultValueOnCreate();
}
}
return data;
}
protected checkRequiredFields(data: TBaseModel): TBaseModel {
// Check required fields.
const relatationalColumns: Dictionary<string> = {};
@@ -203,6 +227,8 @@ class DatabaseService<TBaseModel extends BaseModel> {
throw new BadDataException(`${requiredField} is required`);
}
}
return data;
}
protected async onBeforeCreate(
@@ -411,6 +437,8 @@ class DatabaseService<TBaseModel extends BaseModel> {
props: DatabaseCommonInteractionProps,
isUpdate: boolean = false
): Promise<TBaseModel | QueryDeepPartialEntity<TBaseModel>> {
data = this.checkMaxLengthOfFields(data as TBaseModel);
const columns: Columns = this.model.getTableColumns();
for (const columnName of columns.columns) {
@@ -505,25 +533,29 @@ class DatabaseService<TBaseModel extends BaseModel> {
projectId: ObjectID,
triggerType: DatabaseTriggerType
): Promise<void> {
await API.post(
new URL(
Protocol.HTTP,
WorkflowHostname,
new Route(
`${WorkflowRoute.toString()}/model/${projectId.toString()}/${Text.pascalCaseToDashes(
this.getModel().tableName!
)}/${triggerType}`
)
),
{
data: {
_id: id.toString(),
if (this.getModel().enableWorkflowOn) {
API.post(
new URL(
Protocol.HTTP,
WorkflowHostname,
new Route(
`${WorkflowRoute.toString()}/model/${projectId.toString()}/${Text.pascalCaseToDashes(
this.getModel().tableName!
)}/${triggerType}`
)
),
{
data: {
_id: id.toString(),
},
},
},
{
...ClusterKeyAuthorization.getClusterKeyHeaders(),
}
);
{
...ClusterKeyAuthorization.getClusterKeyHeaders(),
}
).catch((error: Error) => {
logger.error(error);
});
}
}
public async create(createBy: CreateBy<TBaseModel>): Promise<TBaseModel> {
@@ -546,7 +578,8 @@ class DatabaseService<TBaseModel extends BaseModel> {
data.setColumnValue(tenantColumnName, _createdBy.props.tenantId);
}
this.checkRequiredFields(data);
data = this.generateDefaultValues(data);
data = this.checkRequiredFields(data);
if (!this.isValid(data)) {
throw new BadDataException('Data is not valid');
@@ -593,22 +626,22 @@ class DatabaseService<TBaseModel extends BaseModel> {
}
// hit workflow.;
if (
this.getModel().enableWorkflowOn?.create &&
(createBy.props.tenantId ||
(this.getModel().getTenantColumn() &&
createBy.data.getValue<ObjectID>(
this.getModel().getTenantColumn()!
)))
) {
await this.onTrigger(
createBy.data.id!,
createBy.props.tenantId ||
createBy.data.getValue<ObjectID>(
this.getModel().getTenantColumn()!
),
'on-create'
);
if (this.getModel().enableWorkflowOn?.create) {
let tenantId: ObjectID | undefined = createBy.props.tenantId;
if (!tenantId && this.getModel().getTenantColumn()) {
tenantId = createBy.data.getValue<ObjectID>(
this.getModel().getTenantColumn()!
);
}
if (tenantId) {
await this.onTrigger(
createBy.data.id!,
tenantId,
'on-create'
);
}
}
return createBy.data;
@@ -618,6 +651,38 @@ class DatabaseService<TBaseModel extends BaseModel> {
}
}
private checkMaxLengthOfFields<TBaseModel extends BaseModel>(
data: TBaseModel
): TBaseModel {
// Check required fields.
const tableColumns: Array<string> =
this.model.getTableColumns().columns;
for (const column of tableColumns) {
const metadata: TableColumnMetadata =
this.model.getTableColumnMetadata(column);
if (
(data as any)[column] &&
metadata.type &&
getMaxLengthFromTableColumnType(metadata.type)
) {
if (
(data as any)[column].toString().length >
getMaxLengthFromTableColumnType(metadata.type)!
) {
throw new BadDataException(
`${column} length cannot be more than ${getMaxLengthFromTableColumnType(
metadata.type
)} characters`
);
}
}
}
return data;
}
private async checkTotalItemsBy(
createdBy: CreateBy<TBaseModel>
): Promise<void> {
@@ -855,6 +920,10 @@ class DatabaseService<TBaseModel extends BaseModel> {
private async _deleteBy(deleteBy: DeleteBy<TBaseModel>): Promise<number> {
try {
if (this.doNotAllowDelete) {
throw new BadDataException('Delete not allowed');
}
const onDelete: OnDelete<TBaseModel> = deleteBy.props.ignoreHooks
? { deleteBy, carryForward: [] }
: await this.onBeforeDelete(deleteBy);
@@ -930,21 +999,23 @@ class DatabaseService<TBaseModel extends BaseModel> {
(deleteBy.props.tenantId || this.getModel().getTenantColumn())
) {
for (const item of items) {
if (
(this.getModel().getTenantColumn() &&
item.getValue<ObjectID>(
if (this.getModel().enableWorkflowOn?.create) {
let tenantId: ObjectID | undefined =
deleteBy.props.tenantId;
if (!tenantId && this.getModel().getTenantColumn()) {
tenantId = item.getValue<ObjectID>(
this.getModel().getTenantColumn()!
)) ||
deleteBy.props.tenantId
) {
await this.onTrigger(
item.id!,
deleteBy.props.tenantId ||
item.getValue<ObjectID>(
this.getModel().getTenantColumn()!
),
'on-delete'
);
);
}
if (tenantId) {
await this.onTrigger(
item.id!,
tenantId,
'on-delete'
);
}
}
}
}
@@ -976,15 +1047,27 @@ class DatabaseService<TBaseModel extends BaseModel> {
withDeleted?: boolean | undefined
): Promise<Array<TBaseModel>> {
try {
let automaticallyAddedCreatedAtInSelect: boolean = false;
if (!findBy.sort || Object.keys(findBy.sort).length === 0) {
findBy.sort = {
createdAt: SortOrder.Descending,
};
if (!findBy.select) {
findBy.select = {} as any;
}
if (!(findBy.select as any)['createdAt']) {
(findBy.select as any)['createdAt'] = true;
automaticallyAddedCreatedAtInSelect = true;
}
}
const onFind: OnFind<TBaseModel> = findBy.props.ignoreHooks
? { findBy, carryForward: [] }
: await this.onBeforeFind(findBy);
const onBeforeFind: FindBy<TBaseModel> = onFind.findBy;
const onBeforeFind: FindBy<TBaseModel> = { ...onFind.findBy };
const carryForward: any = onFind.carryForward;
if (
@@ -998,10 +1081,6 @@ class DatabaseService<TBaseModel extends BaseModel> {
(onBeforeFind.select as any)['_id'] = true;
}
if (!(onBeforeFind.select as any)['createdAt']) {
(onBeforeFind.select as any)['createdAt'] = true;
}
const result: {
query: Query<TBaseModel>;
select: Select<TBaseModel> | null;
@@ -1044,6 +1123,13 @@ class DatabaseService<TBaseModel extends BaseModel> {
decryptedItems,
onBeforeFind
);
for (const item of decryptedItems) {
if (automaticallyAddedCreatedAtInSelect) {
delete (item as any).createdAt;
}
}
if (!findBy.props.ignoreHooks) {
decryptedItems = await (
await this.onFindSuccess(
@@ -1141,6 +1227,10 @@ class DatabaseService<TBaseModel extends BaseModel> {
public async findOneById(
findOneById: FindOneByID<TBaseModel>
): Promise<TBaseModel | null> {
if (!findOneById.id) {
throw new BadDataException('findOneById.id is required');
}
return await this.findOneBy({
query: {
_id: findOneById.id.toString() as any,
@@ -1205,22 +1295,19 @@ class DatabaseService<TBaseModel extends BaseModel> {
await this.getRepository().save(updatedItem);
// hit workflow.
if (
(this.getModel().enableWorkflowOn?.update &&
updateBy.props.tenantId) ||
(this.getModel().getTenantColumn() &&
item.getValue<ObjectID>(
if (this.getModel().enableWorkflowOn?.update) {
let tenantId: ObjectID | undefined =
updateBy.props.tenantId;
if (!tenantId && this.getModel().getTenantColumn()) {
tenantId = item.getValue<ObjectID>(
this.getModel().getTenantColumn()!
))
) {
await this.onTrigger(
item.id!,
updateBy.props.tenantId ||
item.getValue<ObjectID>(
this.getModel().getTenantColumn()!
),
'on-update'
);
);
}
if (tenantId) {
await this.onTrigger(item.id!, tenantId, 'on-update');
}
}
}
@@ -1264,6 +1351,10 @@ class DatabaseService<TBaseModel extends BaseModel> {
public async updateOneById(
updateById: UpdateByID<TBaseModel>
): Promise<void> {
if (!updateById.id) {
throw new BadDataException('updateById.id is required');
}
await this.updateOneBy({
query: {
_id: updateById.id.toString() as any,

View File

@@ -5,6 +5,8 @@ import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
this.hardDeleteItemsOlderThanInDays('createdAt', 30);
}
}
export default new Service();

View File

@@ -1,6 +1,6 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/Incident';
import DatabaseService, { OnCreate } from './DatabaseService';
import DatabaseService, { OnCreate, OnUpdate } from './DatabaseService';
import ObjectID from 'Common/Types/ObjectID';
import Monitor from 'Model/Models/Monitor';
import MonitorService from './MonitorService';
@@ -21,12 +21,70 @@ import URL from 'Common/Types/API/URL';
import User from 'Model/Models/User';
import TeamMemberService from './TeamMemberService';
import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
import UserService from './UserService';
import { JSONObject } from 'Common/Types/JSON';
import OnCallDutyPolicyService from './OnCallDutyPolicyService';
import UserNotificationEventType from 'Common/Types/UserNotification/UserNotificationEventType';
import SortOrder from 'Common/Types/Database/SortOrder';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
public async acknowledgeIncident(
incidentId: ObjectID,
acknowledgedByUserId: ObjectID
): Promise<void> {
const incident: Model | null = await this.findOneById({
id: incidentId,
select: {
projectId: true,
},
props: {
isRoot: true,
},
});
if (!incident || !incident.projectId) {
throw new BadDataException('Incident not found.');
}
const incidentState: IncidentState | null =
await IncidentStateService.findOneBy({
query: {
projectId: incident.projectId,
isAcknowledgedState: true,
},
select: {
_id: true,
},
props: {
isRoot: true,
},
});
if (!incidentState || !incidentState.id) {
throw new BadDataException(
'Acknowledged state not found for this project. Please add acknowledged state from settings.'
);
}
const incidentStateTimeline: IncidentStateTimeline =
new IncidentStateTimeline();
incidentStateTimeline.projectId = incident.projectId;
incidentStateTimeline.incidentId = incidentId;
incidentStateTimeline.incidentStateId = incidentState.id;
incidentStateTimeline.createdByUserId = acknowledgedByUserId;
await IncidentStateTimelineService.create({
data: incidentStateTimeline,
props: {
isRoot: true,
},
});
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>
): Promise<OnCreate<Model>> {
@@ -59,6 +117,41 @@ export class Service extends DatabaseService<Model> {
createBy.data.currentIncidentStateId = incidentState.id;
if (
(createBy.data.createdByUserId ||
createBy.data.createdByUser ||
createBy.props.userId) &&
!createBy.data.rootCause
) {
let userId: ObjectID | undefined = createBy.data.createdByUserId;
if (createBy.props.userId) {
userId = createBy.props.userId;
}
if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
userId = createBy.data.createdByUser.id;
}
const user: User | null = await UserService.findOneBy({
query: {
_id: userId?.toString()!,
},
select: {
_id: true,
name: true,
email: true,
},
props: {
isRoot: true,
},
});
if (user) {
createBy.data.rootCause = `Incident created by ${user.name} (${user.email})`;
}
}
return { createBy, carryForward: null };
}
@@ -87,6 +180,11 @@ export class Service extends DatabaseService<Model> {
}) || [],
createdItem.changeMonitorStatusToId,
true, // notifyMonitorOwners
createdItem.rootCause ||
'Status was changed because incident ' +
createdItem.id.toString() +
' was created.',
createdItem.createdStateLog,
onCreate.createBy.props
);
}
@@ -97,6 +195,8 @@ export class Service extends DatabaseService<Model> {
createdItem.currentIncidentStateId,
false,
false,
createdItem.rootCause,
createdItem.createdStateLog,
{
isRoot: true,
}
@@ -123,6 +223,22 @@ export class Service extends DatabaseService<Model> {
);
}
if (
createdItem.onCallDutyPolicies?.length &&
createdItem.onCallDutyPolicies?.length > 0
) {
for (const policy of createdItem.onCallDutyPolicies) {
await OnCallDutyPolicyService.executePolicy(
new ObjectID(policy._id as string),
{
triggeredByIncidentId: createdItem.id!,
userNotificationEventType:
UserNotificationEventType.IncidentCreated,
}
);
}
}
return createdItem;
}
@@ -248,14 +364,71 @@ export class Service extends DatabaseService<Model> {
);
}
protected override async onUpdateSuccess(
onUpdate: OnUpdate<Model>,
updatedItemIds: ObjectID[]
): Promise<OnUpdate<Model>> {
if (
onUpdate.updateBy.data.currentIncidentStateId &&
onUpdate.updateBy.props.tenantId
) {
for (const itemId of updatedItemIds) {
await this.changeIncidentState(
onUpdate.updateBy.props.tenantId as ObjectID,
itemId,
onUpdate.updateBy.data.currentIncidentStateId as ObjectID,
true,
true, // notifyOwners = true
'This status was changed when the incident was updated.',
undefined,
{
isRoot: true,
}
);
}
}
return onUpdate;
}
public async changeIncidentState(
projectId: ObjectID,
incidentId: ObjectID,
incidentStateId: ObjectID,
notifyStatusPageSubscribers: boolean,
notifyOwners: boolean,
props: DatabaseCommonInteractionProps
rootCause: string | undefined,
stateChangeLog: JSONObject | undefined,
props: DatabaseCommonInteractionProps | undefined
): Promise<void> {
// get last monitor status timeline.
const lastIncidentStatusTimeline: IncidentStateTimeline | null =
await IncidentStateTimelineService.findOneBy({
query: {
incidentId: incidentId,
projectId: projectId,
},
select: {
_id: true,
incidentStateId: true,
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
});
if (
lastIncidentStatusTimeline &&
lastIncidentStatusTimeline.incidentStateId &&
lastIncidentStatusTimeline.incidentStateId.toString() ===
incidentStateId.toString()
) {
return;
}
const statusTimeline: IncidentStateTimeline =
new IncidentStateTimeline();
@@ -266,9 +439,16 @@ export class Service extends DatabaseService<Model> {
statusTimeline.isStatusPageSubscribersNotified =
!notifyStatusPageSubscribers;
if (stateChangeLog) {
statusTimeline.stateChangeLog = stateChangeLog;
}
if (rootCause) {
statusTimeline.rootCause = rootCause;
}
await IncidentStateTimelineService.create({
data: statusTimeline,
props: props,
props: props || {},
});
}
}

View File

@@ -14,12 +14,82 @@ import MonitorStatusService from './MonitorStatusService';
import MonitorStatus from 'Model/Models/MonitorStatus';
import MonitorStatusTimeline from 'Model/Models/MonitorStatusTimeline';
import MonitorStatusTimelineService from './MonitorStatusTimelineService';
import CreateBy from '../Types/Database/CreateBy';
import UserService from './UserService';
import User from 'Model/Models/User';
export class Service extends DatabaseService<IncidentStateTimeline> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(IncidentStateTimeline, postgresDatabase);
}
public async getResolvedStateIdForProject(
projectId: ObjectID
): Promise<ObjectID> {
const resolvedState: IncidentState | null =
await IncidentStateService.findOneBy({
query: {
projectId: projectId,
isResolvedState: true,
},
props: {
isRoot: true,
},
select: {
_id: true,
},
});
if (!resolvedState) {
throw new BadDataException(
'No resolved state found for the project'
);
}
return resolvedState.id!;
}
protected override async onBeforeCreate(
createBy: CreateBy<MonitorStatusTimeline>
): Promise<OnCreate<MonitorStatusTimeline>> {
if (
(createBy.data.createdByUserId ||
createBy.data.createdByUser ||
createBy.props.userId) &&
!createBy.data.rootCause
) {
let userId: ObjectID | undefined = createBy.data.createdByUserId;
if (createBy.props.userId) {
userId = createBy.props.userId;
}
if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
userId = createBy.data.createdByUser.id;
}
const user: User | null = await UserService.findOneBy({
query: {
_id: userId?.toString()!,
},
select: {
_id: true,
name: true,
email: true,
},
props: {
isRoot: true,
},
});
if (user) {
createBy.data.rootCause = `Incident state created by ${user.name} (${user.email})`;
}
}
return { createBy, carryForward: null };
}
protected override async onCreateSuccess(
onCreate: OnCreate<IncidentStateTimeline>,
createdItem: IncidentStateTimeline
@@ -95,6 +165,35 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
if (resolvedMonitorState) {
for (const monitor of incident.monitors) {
//check state of the monitor.
const latestState: MonitorStatusTimeline | null =
await MonitorStatusTimelineService.findOneBy({
query: {
monitorId: monitor.id!,
projectId: incident.projectId!,
},
select: {
_id: true,
monitorStatusId: true,
},
props: {
isRoot: true,
},
sort: {
createdAt: SortOrder.Descending,
},
});
if (
latestState &&
latestState.monitorStatusId?.toString() ===
resolvedMonitorState.id!.toString()
) {
// already on this state. Skip.
continue;
}
const monitorStatusTimeline: MonitorStatusTimeline =
new MonitorStatusTimeline();
monitorStatusTimeline.monitorId = monitor.id!;

View File

@@ -27,7 +27,7 @@ import StatusPageHeaderLinkService from './StatusPageHeaderLinkService';
import StatusPagePrivateUserService from './StatusPagePrivateUserService';
// On Call Duty
import OnCallDutyService from './OnCallDutyService';
import OnCallDutyPolicyService from './OnCallDutyPolicyService';
// Monitors
import MonitorService from './MonitorService';
@@ -70,57 +70,151 @@ import WorkflowLogService from './WorkflowLogService';
// SMS Log Servce
import SmsLogService from './SmsLogService';
import CallLogService from './CallLogService';
import EmailLogService from './EmailLogService';
import BillingService from './BillingService';
import AccessTokenService from './AccessTokenService';
import CallService from './CallService';
import DataMigrationService from './DataMigrationService';
import IncidentCustomFieldService from './IncidentCustomFieldService';
import IncidentOwnerTeamService from './IncidentOwnerTeamService';
import IncidentOwnerUserService from './IncidentOwnerUserService';
import MailService from './MailService';
import MonitorCustomFieldService from './MonitorCustomFieldService';
import MonitorOwnerTeamService from './MonitorOwnerTeamService';
import MonitorOwnerUserService from './MonitorOwnerUserService';
import MonitorProbeService from './MonitorProbeService';
import NotificationService from './NotificationService';
import OnCallDutyPolicyCustomFieldService from './OnCallDutyPolicyCustomFieldService';
import OnCallDutyPolicyEscalationRuleService from './OnCallDutyPolicyEscalationRuleService';
import OnCallDutyPolicyEscalationRuleTeamService from './OnCallDutyPolicyEscalationRuleTeamService';
import OnCallDutyPolicyEscalationRuleUserService from './OnCallDutyPolicyEscalationRuleUserService';
import OnCallDutyPolicyExecutionLogService from './OnCallDutyPolicyExecutionLogService';
import OnCallDutyPolicyExecutionLogTimelineService from './OnCallDutyPolicyExecutionLogTimelineService';
import ProjectSsoService from './ProjectSsoService';
import ScheduledMaintenanceCustomFieldService from './ScheduledMaintenanceCustomFieldService';
import ScheduledMaintenanceOwnerTeamService from './ScheduledMaintenanceOwnerTeamService';
import ScheduledMaintenanceOwnerUserService from './ScheduledMaintenanceOwnerUserService';
import ShortLinkService from './ShortLinkService';
import SmsService from './SmsService';
import StatusPageCertificateService from './StatusPageCertificateService';
import StatusPageCustomFieldService from './StatusPageCustomFieldService';
import StatusPageOwnerTeamService from './StatusPageOwnerTeamService';
import StatusPageOwnerUserService from './StatusPageOwnerUserService';
import StatusPageSsoService from './StatusPageSsoService';
import UserCallService from './UserCallService';
import UserEmailService from './UserEmailService';
import UserSmsService from './UserSmsService';
import UserNotificationRuleService from './UserNotificationRuleService';
import UserNotificationSettingService from './UserNotificationSettingService';
import UserOnCallLogService from './UserOnCallLogService';
import UserOnCallLogTimelineService from './UserOnCallLogTimelineService';
import BaseService from './BaseService';
export default [
UserService,
ProbeService,
ProjectService,
EmailVerificationTokenService,
TeamService,
TeamMemberService,
TeamPermissionService,
ApiKeyService,
LabelService,
const services: Array<BaseService> = [
// Import all services in current folder here.
AccessTokenService,
ApiKeyPermissionService,
ProjectSmtpConfigService,
StatusPageService,
OnCallDutyService,
MonitorService,
MonitorStatusService,
IncidentStateService,
IncidentService,
IncidentStateTimelineService,
MonitorStatusTimelineService,
IncidentPublicNoteService,
IncidentInternalNoteService,
FileService,
ApiKeyService,
BillingInvoiceService,
BillingPaymentMethodsService,
BillingService,
CallLogService,
CallService,
DataMigrationService,
DomainService,
StatusPageGroupService,
StatusPageDomainService,
StatusPageResourceService,
IncidentSeverityService,
StatusPageAnnouncementService,
StatusPageSubscriberService,
StatusPageFooterLinkService,
StatusPageHeaderLinkService,
StatusPagePrivateUserService,
EmailLogService,
EmailVerificationTokenService,
ScheduledMaintenanceStateService,
ScheduledMaintenanceService,
ScheduledMaintenanceStateTimelineService,
ScheduledMaintenancePublicNoteService,
ScheduledMaintenanceInternalNoteService,
FileService,
BillingPaymentMethodsService,
BillingInvoiceService,
GreenlockChallengeService,
GreenlockCertificateService,
GreenlockChallengeService,
IncidentCustomFieldService,
IncidentInternalNoteService,
IncidentOwnerTeamService,
IncidentOwnerUserService,
IncidentPublicNoteService,
IncidentService,
IncidentSeverityService,
IncidentStateService,
IncidentStateTimelineService,
LabelService,
MailService,
MonitorCustomFieldService,
MonitorOwnerTeamService,
MonitorOwnerUserService,
MonitorProbeService,
MonitorService,
MonitorStatusService,
MonitorStatusTimelineService,
NotificationService,
OnCallDutyPolicyCustomFieldService,
OnCallDutyPolicyEscalationRuleService,
OnCallDutyPolicyEscalationRuleTeamService,
OnCallDutyPolicyEscalationRuleUserService,
OnCallDutyPolicyExecutionLogService,
OnCallDutyPolicyExecutionLogTimelineService,
OnCallDutyPolicyService,
ProjectService,
ProjectSmtpConfigService,
ProbeService,
ProjectSsoService,
ScheduledMaintenanceCustomFieldService,
ScheduledMaintenanceInternalNoteService,
ScheduledMaintenanceOwnerTeamService,
ScheduledMaintenanceOwnerUserService,
ScheduledMaintenancePublicNoteService,
ScheduledMaintenanceService,
ScheduledMaintenanceStateService,
ScheduledMaintenanceStateTimelineService,
ShortLinkService,
SmsLogService,
SmsService,
StatusPageAnnouncementService,
StatusPageCertificateService,
StatusPageCustomFieldService,
StatusPageDomainService,
StatusPageFooterLinkService,
StatusPageGroupService,
StatusPageHeaderLinkService,
StatusPageOwnerTeamService,
StatusPageOwnerUserService,
StatusPagePrivateUserService,
StatusPageResourceService,
StatusPageService,
StatusPageSsoService,
StatusPageSubscriberService,
TeamMemberService,
TeamPermissionService,
TeamService,
UserService,
UserCallService,
UserEmailService,
UserNotificationRuleService,
UserNotificationSettingService,
UserOnCallLogService,
UserOnCallLogTimelineService,
UserSmsService,
WorkflowLogService,
WorkflowService,
WorkflowVariablesService,
WorkflowLogService,
SmsLogService,
];
export default services;

View File

@@ -9,25 +9,41 @@ import Email from 'Common/Types/Email/EmailMessage';
import EmailServer from 'Common/Types/Email/EmailServer';
import Protocol from 'Common/Types/API/Protocol';
import ClusterKeyAuthorization from '../Middleware/ClusterKeyAuthorization';
import ObjectID from 'Common/Types/ObjectID';
import BaseService from './BaseService';
export default class MailService {
public static async sendMail(
export class MailService extends BaseService {
public async sendMail(
mail: Email,
mailServer?: EmailServer
options?: {
mailServer?: EmailServer | undefined;
userOnCallLogTimelineId?: ObjectID;
projectId?: ObjectID | undefined;
}
): Promise<HTTPResponse<EmptyResponseData>> {
const body: JSONObject = {
...mail,
toEmail: mail.toEmail.toString(),
};
if (mailServer) {
body['SMTP_USERNAME'] = mailServer.username;
body['SMTP_EMAIL'] = mailServer.fromEmail.toString();
body['SMTP_FROM_NAME'] = mailServer.fromName;
body['SMTP_IS_SECURE'] = mailServer.secure;
body['SMTP_PORT'] = mailServer.port.toNumber();
body['SMTP_HOST'] = mailServer.host.toString();
body['SMTP_PASSWORD'] = mailServer.password;
if (options && options.mailServer) {
body['SMTP_ID'] = options.mailServer.id?.toString();
body['SMTP_USERNAME'] = options.mailServer.username;
body['SMTP_EMAIL'] = options.mailServer.fromEmail.toString();
body['SMTP_FROM_NAME'] = options.mailServer.fromName;
body['SMTP_IS_SECURE'] = options.mailServer.secure;
body['SMTP_PORT'] = options.mailServer.port.toNumber();
body['SMTP_HOST'] = options.mailServer.host.toString();
body['SMTP_PASSWORD'] = options.mailServer.password;
}
if (options?.userOnCallLogTimelineId) {
body['userOnCallLogTimelineId'] =
options.userOnCallLogTimelineId.toString();
}
if (options?.projectId) {
body['projectId'] = options.projectId.toString();
}
return await API.post<EmptyResponseData>(
@@ -43,3 +59,5 @@ export default class MailService {
);
}
}
export default new MailService();

View File

@@ -1,6 +1,10 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/Monitor';
import DatabaseService, { OnCreate, OnDelete } from './DatabaseService';
import DatabaseService, {
OnCreate,
OnDelete,
OnUpdate,
} from './DatabaseService';
import CreateBy from '../Types/Database/CreateBy';
import MonitorStatus from 'Model/Models/MonitorStatus';
import MonitorStatusService from './MonitorStatusService';
@@ -25,6 +29,8 @@ import Typeof from 'Common/Types/Typeof';
import TeamMemberService from './TeamMemberService';
import User from 'Model/Models/User';
import URL from 'Common/Types/API/URL';
import { JSONObject } from 'Common/Types/JSON';
import SortOrder from 'Common/Types/Database/SortOrder';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
@@ -44,9 +50,49 @@ export class Service extends DatabaseService<Model> {
return onDelete;
}
protected override async onUpdateSuccess(
onUpdate: OnUpdate<Model>,
updatedItemIds: ObjectID[]
): Promise<OnUpdate<Model>> {
if (
onUpdate.updateBy.data.currentMonitorStatusId &&
onUpdate.updateBy.props.tenantId
) {
await this.changeMonitorStatus(
onUpdate.updateBy.props.tenantId as ObjectID,
updatedItemIds as Array<ObjectID>,
onUpdate.updateBy.data.currentMonitorStatusId as ObjectID,
true, // notifyOwners = true
'This status was changed when the monitor was updated.',
undefined,
{
isRoot: true,
}
);
}
return onUpdate;
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>
): Promise<OnCreate<Model>> {
if (!createBy.data.monitorType) {
throw new BadDataException(
'Monitor type required to create monitor.'
);
}
if (!Object.values(MonitorType).includes(createBy.data.monitorType)) {
throw new BadDataException(
`Invalid monitor type "${
createBy.data.monitorType
}". Valid monitor types are ${Object.values(MonitorType).join(
', '
)}.`
);
}
if (!createBy.props.tenantId) {
throw new BadDataException('ProjectId required to create monitor.');
}
@@ -97,6 +143,8 @@ export class Service extends DatabaseService<Model> {
[createdItem.id],
createdItem.currentMonitorStatusId,
false, // notifyOwners = false
'This status was created when the monitor was created.',
undefined,
onCreate.createBy.props
);
@@ -325,9 +373,39 @@ export class Service extends DatabaseService<Model> {
monitorIds: Array<ObjectID>,
monitorStatusId: ObjectID,
notifyOwners: boolean,
rootCause: string | undefined,
statusChangeLog: JSONObject | undefined,
props: DatabaseCommonInteractionProps
): Promise<void> {
for (const monitorId of monitorIds) {
// get last monitor status timeline.
const lastMonitorStatusTimeline: MonitorStatusTimeline | null =
await MonitorStatusTimelineService.findOneBy({
query: {
monitorId: monitorId,
projectId: projectId,
},
select: {
_id: true,
monitorStatusId: true,
},
sort: {
createdAt: SortOrder.Descending,
},
props: {
isRoot: true,
},
});
if (
lastMonitorStatusTimeline &&
lastMonitorStatusTimeline.monitorStatusId &&
lastMonitorStatusTimeline.monitorStatusId.toString() ===
monitorStatusId.toString()
) {
continue;
}
const statusTimeline: MonitorStatusTimeline =
new MonitorStatusTimeline();
@@ -336,6 +414,13 @@ export class Service extends DatabaseService<Model> {
statusTimeline.projectId = projectId;
statusTimeline.isOwnerNotified = !notifyOwners;
if (statusChangeLog) {
statusTimeline.statusChangeLog = statusChangeLog;
}
if (rootCause) {
statusTimeline.rootCause = rootCause;
}
await MonitorStatusTimelineService.create({
data: statusTimeline,
props: props,

View File

@@ -7,12 +7,56 @@ import MonitorStatusTimeline from 'Model/Models/MonitorStatusTimeline';
import ObjectID from 'Common/Types/ObjectID';
import SortOrder from 'Common/Types/Database/SortOrder';
import PositiveNumber from 'Common/Types/PositiveNumber';
import CreateBy from '../Types/Database/CreateBy';
import UserService from './UserService';
import User from 'Model/Models/User';
export class Service extends DatabaseService<MonitorStatusTimeline> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(MonitorStatusTimeline, postgresDatabase);
}
protected override async onBeforeCreate(
createBy: CreateBy<MonitorStatusTimeline>
): Promise<OnCreate<MonitorStatusTimeline>> {
if (
(createBy.data.createdByUserId ||
createBy.data.createdByUser ||
createBy.props.userId) &&
!createBy.data.rootCause
) {
let userId: ObjectID | undefined = createBy.data.createdByUserId;
if (createBy.props.userId) {
userId = createBy.props.userId;
}
if (createBy.data.createdByUser && createBy.data.createdByUser.id) {
userId = createBy.data.createdByUser.id;
}
const user: User | null = await UserService.findOneBy({
query: {
_id: userId?.toString()!,
},
select: {
_id: true,
name: true,
email: true,
},
props: {
isRoot: true,
},
});
if (user) {
createBy.data.rootCause = `Monitor status created by ${user.name} (${user.email})`;
}
}
return { createBy, carryForward: null };
}
protected override async onCreateSuccess(
onCreate: OnCreate<MonitorStatusTimeline>,
createdItem: MonitorStatusTimeline

View File

@@ -5,9 +5,14 @@ import ProjectService from './ProjectService';
import BillingService from './BillingService';
import logger from '../Utils/Logger';
import BadDataException from 'Common/Types/Exception/BadDataException';
import BaseService from './BaseService';
export default class NotificationService {
public static async rechargeBalance(
export class NotificationService extends BaseService {
public constructor() {
super();
}
public async rechargeBalance(
projectId: ObjectID,
amountInUSD: number
): Promise<number> {
@@ -84,7 +89,7 @@ export default class NotificationService {
failedCallAndSMSBalanceChargeNotificationSentToOwners:
false, // reset this flag
lowCallAndSMSBalanceNotificationSentToOwners: false, // reset this flag
notEnabledSmsNotificationSentToOwners: false,
notEnabledSmsOrCallNotificationSentToOwners: false,
},
id: project.id!,
props: {
@@ -129,7 +134,7 @@ export default class NotificationService {
}
}
public static async rechargeIfBalanceIsLow(
public async rechargeIfBalanceIsLow(
projectId: ObjectID,
options?: {
autoRechargeSmsOrCallByBalanceInUSD: number;
@@ -192,3 +197,5 @@ export default class NotificationService {
return project?.smsOrCallCurrentBalanceInUSDCents || 0;
}
}
export default new NotificationService();

View File

@@ -1,5 +1,5 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDuty';
import Model from 'Model/Models/OnCallDutyPolicyCustomField';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {

View File

@@ -0,0 +1,625 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDutyPolicyEscalationRule';
import DatabaseService, {
OnCreate,
OnDelete,
OnUpdate,
} from './DatabaseService';
import CreateBy from '../Types/Database/CreateBy';
import BadDataException from 'Common/Types/Exception/BadDataException';
import QueryHelper from '../Types/Database/QueryHelper';
import DeleteBy from '../Types/Database/DeleteBy';
import ObjectID from 'Common/Types/ObjectID';
import LIMIT_MAX, { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
import SortOrder from 'Common/Types/Database/SortOrder';
import UpdateBy from '../Types/Database/UpdateBy';
import Query from '../Types/Database/Query';
import PositiveNumber from 'Common/Types/PositiveNumber';
import DatabaseCommonInteractionProps from 'Common/Types/Database/DatabaseCommonInteractionProps';
import OnCallDutyPolicyEscalationRuleUser from 'Model/Models/OnCallDutyPolicyEscalationRuleUser';
import OnCallDutyPolicyEscalationRuleUserService from './OnCallDutyPolicyEscalationRuleUserService';
import OnCallDutyPolicyEscalationRuleTeam from 'Model/Models/OnCallDutyPolicyEscalationRuleTeam';
import OnCallDutyPolicyEscalationRuleTeamService from './OnCallDutyPolicyEscalationRuleTeamService';
import TeamMemberService from './TeamMemberService';
import UserNotificationEventType from 'Common/Types/UserNotification/UserNotificationEventType';
import UserNotificationRuleService from './UserNotificationRuleService';
import OnCallDutyPolicyExecutionLogTimeline from 'Model/Models/OnCallDutyPolicyExecutionLogTimeline';
import OnCallDutyPolicyExecutionLogTimelineService from './OnCallDutyPolicyExecutionLogTimelineService';
import OnCallDutyExecutionLogTimelineStatus from 'Common/Types/OnCallDutyPolicy/OnCalDutyExecutionLogTimelineStatus';
import User from 'Model/Models/User';
import OneUptimeDate from 'Common/Types/Date';
import OnCallDutyPolicyExecutionLogService from './OnCallDutyPolicyExecutionLogService';
import { IsBillingEnabled } from '../Config';
import { PlanSelect } from 'Common/Types/Billing/SubscriptionPlan';
export class Service extends DatabaseService<Model> {
public async startRuleExecution(
ruleId: ObjectID,
options: {
projectId: ObjectID;
triggeredByIncidentId?: ObjectID | undefined;
userNotificationEventType: UserNotificationEventType;
onCallPolicyExecutionLogId: ObjectID;
onCallPolicyId: ObjectID;
}
): Promise<void> {
// add log timeline.
const rule: Model | null = await this.findOneById({
id: ruleId,
select: {
_id: true,
order: true,
escalateAfterInMinutes: true,
},
props: {
isRoot: true,
},
});
if (!rule) {
throw new BadDataException(
`On Call Duty Policy Escalation Rule with id ${ruleId.toString()} not found`
);
}
await OnCallDutyPolicyExecutionLogService.updateOneById({
id: options.onCallPolicyExecutionLogId,
data: {
lastEscalationRuleExecutedAt: OneUptimeDate.getCurrentDate(),
lastExecutedEscalationRuleId: ruleId,
lastExecutedEscalationRuleOrder: rule.order!,
executeNextEscalationRuleInMinutes:
rule.escalateAfterInMinutes || 0,
},
props: {
isRoot: true,
},
});
const getNewLog: Function =
(): OnCallDutyPolicyExecutionLogTimeline => {
const log: OnCallDutyPolicyExecutionLogTimeline =
new OnCallDutyPolicyExecutionLogTimeline();
log.projectId = options.projectId;
log.onCallDutyPolicyExecutionLogId =
options.onCallPolicyExecutionLogId;
log.onCallDutyPolicyId = options.onCallPolicyId;
log.onCallDutyPolicyEscalationRuleId = ruleId;
log.userNotificationEventType =
options.userNotificationEventType;
if (options.triggeredByIncidentId) {
log.triggeredByIncidentId = options.triggeredByIncidentId;
}
return log;
};
if (
UserNotificationEventType.IncidentCreated ===
options.userNotificationEventType &&
!options.triggeredByIncidentId
) {
throw new BadDataException(
'triggeredByIncidentId is required when userNotificationEventType is IncidentCreated'
);
}
const usersInRule: Array<OnCallDutyPolicyEscalationRuleUser> =
await OnCallDutyPolicyEscalationRuleUserService.findBy({
query: {
onCallDutyPolicyEscalationRuleId: ruleId,
},
props: {
isRoot: true,
},
skip: 0,
limit: LIMIT_PER_PROJECT,
select: {
userId: true,
},
});
const teamsInRule: Array<OnCallDutyPolicyEscalationRuleTeam> =
await OnCallDutyPolicyEscalationRuleTeamService.findBy({
query: {
onCallDutyPolicyEscalationRuleId: ruleId,
},
props: {
isRoot: true,
},
skip: 0,
limit: LIMIT_PER_PROJECT,
select: {
teamId: true,
},
});
// get unique users and notify all the users.
const startUserNotifcationRuleExecution: Function = async (
userId: ObjectID,
teamId: ObjectID | undefined
): Promise<void> => {
// no users in this rule. Skipping.
let log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
log.statusMessage = 'Sending notification to user.';
log.status = OnCallDutyExecutionLogTimelineStatus.Executing;
log.alertSentToUserId = userId;
if (teamId) {
log.userBelongsToTeamId = teamId;
}
log = await OnCallDutyPolicyExecutionLogTimelineService.create({
data: log,
props: {
isRoot: true,
},
});
await UserNotificationRuleService.startUserNotificationRulesExecution(
userId,
{
userNotificationEventType:
options.userNotificationEventType!,
triggeredByIncidentId:
options.triggeredByIncidentId || undefined,
onCallPolicyExecutionLogId:
options.onCallPolicyExecutionLogId,
onCallPolicyId: options.onCallPolicyId,
onCallPolicyEscalationRuleId: ruleId,
userBelongsToTeamId: teamId,
onCallDutyPolicyExecutionLogTimelineId: log.id!,
projectId: options.projectId,
}
);
};
const uniqueUserIds: Array<ObjectID> = [];
for (const teamInRule of teamsInRule) {
const usersInTeam: Array<User> =
await TeamMemberService.getUsersInTeam(teamInRule.teamId!);
for (const user of usersInTeam) {
if (
!uniqueUserIds.find((userId: ObjectID) => {
return user.id?.toString() === userId.toString();
})
) {
uniqueUserIds.push(user.id!);
await startUserNotifcationRuleExecution(
user.id!,
teamInRule.teamId!
);
} else {
// no users in this rule. Skipping.
const log: OnCallDutyPolicyExecutionLogTimeline =
getNewLog();
log.statusMessage =
'Skipped because notification sent to this user already.';
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
log.alertSentToUserId = user.id!;
log.userBelongsToTeamId = teamInRule.teamId!;
await OnCallDutyPolicyExecutionLogTimelineService.create({
data: log,
props: {
isRoot: true,
},
});
}
}
}
for (const userRule of usersInRule) {
if (
!uniqueUserIds.find((userId: ObjectID) => {
return userRule.userId?.toString() === userId.toString();
})
) {
uniqueUserIds.push(userRule.userId!);
await startUserNotifcationRuleExecution(
userRule.userId!,
undefined
);
} else {
// no users in this rule. Skipping.
const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
log.statusMessage =
'Skipped because notification sent to this user already.';
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
log.alertSentToUserId = userRule.userId!;
await OnCallDutyPolicyExecutionLogTimelineService.create({
data: log,
props: {
isRoot: true,
},
});
}
}
if (uniqueUserIds.length === 0) {
// no users in this rule. Skipping.
const log: OnCallDutyPolicyExecutionLogTimeline = getNewLog();
log.statusMessage = 'Skipped because no users in this rule.';
log.status = OnCallDutyExecutionLogTimelineStatus.Skipped;
await OnCallDutyPolicyExecutionLogTimelineService.create({
data: log,
props: {
isRoot: true,
},
});
}
}
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
protected override async onCreateSuccess(
onCreate: OnCreate<Model>,
createdItem: Model
): Promise<Model> {
if (!createdItem.projectId) {
throw new BadDataException('projectId is required');
}
if (!createdItem.id) {
throw new BadDataException('id is required');
}
// add people in escalation rule.
if (
onCreate.createBy.miscDataProps &&
(onCreate.createBy.miscDataProps['teams'] ||
onCreate.createBy.miscDataProps['users'])
) {
await this.addUsersAndTeams(
createdItem.projectId,
createdItem.id,
createdItem.onCallDutyPolicyId!,
(onCreate.createBy.miscDataProps['users'] as Array<ObjectID>) ||
[],
(onCreate.createBy.miscDataProps['teams'] as Array<ObjectID>) ||
[],
onCreate.createBy.props
);
}
return createdItem;
}
public async addUsersAndTeams(
projectId: ObjectID,
escalationRuleId: ObjectID,
onCallDutyPolicyId: ObjectID,
usersIds: Array<ObjectID>,
teamIds: Array<ObjectID>,
props: DatabaseCommonInteractionProps
): Promise<void> {
for (const userId of usersIds) {
await this.addUser(
projectId,
escalationRuleId,
onCallDutyPolicyId,
userId,
props
);
}
for (const teamId of teamIds) {
await this.addTeam(
projectId,
escalationRuleId,
onCallDutyPolicyId,
teamId,
props
);
}
}
public async addTeam(
projectId: ObjectID,
escalationRuleId: ObjectID,
onCallDutyPolicyId: ObjectID,
teamId: ObjectID,
props: DatabaseCommonInteractionProps
): Promise<void> {
const teamInRule: OnCallDutyPolicyEscalationRuleTeam =
new OnCallDutyPolicyEscalationRuleTeam();
teamInRule.projectId = projectId;
teamInRule.onCallDutyPolicyId = onCallDutyPolicyId;
teamInRule.onCallDutyPolicyEscalationRuleId = escalationRuleId;
teamInRule.teamId = teamId;
await OnCallDutyPolicyEscalationRuleTeamService.create({
data: teamInRule,
props,
});
}
public async addUser(
projectId: ObjectID,
escalationRuleId: ObjectID,
onCallDutyPolicyId: ObjectID,
userId: ObjectID,
props: DatabaseCommonInteractionProps
): Promise<void> {
const userInRule: OnCallDutyPolicyEscalationRuleUser =
new OnCallDutyPolicyEscalationRuleUser();
userInRule.projectId = projectId;
userInRule.onCallDutyPolicyId = onCallDutyPolicyId;
userInRule.onCallDutyPolicyEscalationRuleId = escalationRuleId;
userInRule.userId = userId;
await OnCallDutyPolicyEscalationRuleUserService.create({
data: userInRule,
props,
});
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>
): Promise<OnCreate<Model>> {
if (
IsBillingEnabled &&
createBy.props.currentPlan === PlanSelect.Free
) {
// then check no of policies and if it is more than one, return error
const count: PositiveNumber = await this.countBy({
query: {
projectId: createBy.data.projectId!,
onCallDutyPolicyId:
createBy.data.onCallDutyPolicyId! ||
createBy.data.onCallDutyPolicy?._id!,
},
props: {
isRoot: true,
},
});
if (count.toNumber() >= 1) {
throw new BadDataException(
'You can only create one escalation rule in free plan.'
);
}
}
if (!createBy.data.onCallDutyPolicyId) {
throw new BadDataException(
'Status Page Resource onCallDutyPolicyId is required'
);
}
if (!createBy.data.order) {
const query: Query<Model> = {
onCallDutyPolicyId: createBy.data.onCallDutyPolicyId,
};
const count: PositiveNumber = await this.countBy({
query: query,
props: {
isRoot: true,
},
});
createBy.data.order = count.toNumber() + 1;
}
await this.rearrangeOrder(
createBy.data.order,
createBy.data.onCallDutyPolicyId,
true
);
return {
createBy: createBy,
carryForward: null,
};
}
protected override async onBeforeDelete(
deleteBy: DeleteBy<Model>
): Promise<OnDelete<Model>> {
if (!deleteBy.query._id && !deleteBy.props.isRoot) {
throw new BadDataException(
'_id should be present when deleting status page resource. Please try the delete with objectId'
);
}
let resource: Model | null = null;
if (!deleteBy.props.isRoot) {
resource = await this.findOneBy({
query: deleteBy.query,
props: {
isRoot: true,
},
select: {
order: true,
onCallDutyPolicyId: true,
},
});
}
return {
deleteBy,
carryForward: resource,
};
}
protected override async onDeleteSuccess(
onDelete: OnDelete<Model>,
_itemIdsBeforeDelete: ObjectID[]
): Promise<OnDelete<Model>> {
const deleteBy: DeleteBy<Model> = onDelete.deleteBy;
const resource: Model | null = onDelete.carryForward;
if (!deleteBy.props.isRoot && resource) {
if (resource && resource.order && resource.onCallDutyPolicyId) {
await this.rearrangeOrder(
resource.order,
resource.onCallDutyPolicyId,
false
);
}
}
return {
deleteBy: deleteBy,
carryForward: null,
};
}
protected override async onBeforeUpdate(
updateBy: UpdateBy<Model>
): Promise<OnUpdate<Model>> {
if (
updateBy.data.order &&
!updateBy.props.isRoot &&
updateBy.query._id
) {
const resource: Model | null = await this.findOneBy({
query: {
_id: updateBy.query._id!,
},
props: {
isRoot: true,
},
select: {
order: true,
onCallDutyPolicyId: true,
_id: true,
},
});
const currentOrder: number = resource?.order!;
const newOrder: number = updateBy.data.order as number;
const resources: Array<Model> = await this.findBy({
query: {
onCallDutyPolicyId: resource?.onCallDutyPolicyId!,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
select: {
order: true,
onCallDutyPolicyId: true,
_id: true,
},
});
if (currentOrder > newOrder) {
// moving up.
for (const resource of resources) {
if (
resource.order! >= newOrder &&
resource.order! < currentOrder
) {
// increment order.
await this.updateOneBy({
query: {
_id: resource._id!,
},
data: {
order: resource.order! + 1,
},
props: {
isRoot: true,
},
});
}
}
}
if (newOrder > currentOrder) {
// moving down.
for (const resource of resources) {
if (
resource.order! < newOrder &&
resource.order! >= currentOrder
) {
// increment order.
await this.updateOneBy({
query: {
_id: resource._id!,
},
data: {
order: resource.order! - 1,
},
props: {
isRoot: true,
},
});
}
}
}
}
return { updateBy, carryForward: null };
}
private async rearrangeOrder(
currentOrder: number,
onCallDutyPolicyId: ObjectID,
increaseOrder: boolean = true
): Promise<void> {
// get status page resource with this order.
const resources: Array<Model> = await this.findBy({
query: {
order: QueryHelper.greaterThanEqualTo(currentOrder),
onCallDutyPolicyId: onCallDutyPolicyId,
},
limit: LIMIT_MAX,
skip: 0,
props: {
isRoot: true,
},
select: {
_id: true,
order: true,
},
sort: {
order: SortOrder.Ascending,
},
});
let newOrder: number = currentOrder;
for (const resource of resources) {
if (increaseOrder) {
newOrder = resource.order! + 1;
} else {
newOrder = resource.order! - 1;
}
await this.updateOneBy({
query: {
_id: resource._id!,
},
data: {
order: newOrder,
},
props: {
isRoot: true,
},
});
}
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDutyPolicyEscalationRuleTeam';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDutyPolicyEscalationRuleUser';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
}
export default new Service();

View File

@@ -0,0 +1,98 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDutyPolicyExecutionLog';
import DatabaseService, { OnCreate } from './DatabaseService';
import CreateBy from '../Types/Database/CreateBy';
import OnCallDutyPolicyStatus from 'Common/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus';
import OnCallDutyPolicyEscalationRule from 'Model/Models/OnCallDutyPolicyEscalationRule';
import OnCallDutyPolicyEscalationRuleService from './OnCallDutyPolicyEscalationRuleService';
import UserNotificationEventType from 'Common/Types/UserNotification/UserNotificationEventType';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
protected override async onBeforeCreate(
createBy: CreateBy<Model>
): Promise<OnCreate<Model>> {
if (!createBy.data.status) {
createBy.data.status = OnCallDutyPolicyStatus.Scheduled;
}
createBy.data.onCallPolicyExecutionRepeatCount = 1;
return { createBy, carryForward: null };
}
protected override async onCreateSuccess(
_onCreate: OnCreate<Model>,
createdItem: Model
): Promise<Model> {
// get execution rules in this policy adn execute the first rule.
const executionRule: OnCallDutyPolicyEscalationRule | null =
await OnCallDutyPolicyEscalationRuleService.findOneBy({
query: {
projectId: createdItem.projectId!,
onCallDutyPolicyId: createdItem.onCallDutyPolicyId!,
order: 1,
},
props: {
isRoot: true,
},
select: {
_id: true,
},
});
if (executionRule) {
await this.updateOneById({
id: createdItem.id!,
data: {
status: OnCallDutyPolicyStatus.Started,
statusMessage: 'Execution started...',
},
props: {
isRoot: true,
},
});
await OnCallDutyPolicyEscalationRuleService.startRuleExecution(
executionRule.id!,
{
projectId: createdItem.projectId!,
triggeredByIncidentId: createdItem.triggeredByIncidentId,
userNotificationEventType:
UserNotificationEventType.IncidentCreated,
onCallPolicyExecutionLogId: createdItem.id!,
onCallPolicyId: createdItem.onCallDutyPolicyId!,
}
);
await this.updateOneById({
id: createdItem.id!,
data: {
status: OnCallDutyPolicyStatus.Executing,
statusMessage: 'First escalation rule executed....',
},
props: {
isRoot: true,
},
});
} else {
await this.updateOneById({
id: createdItem.id!,
data: {
status: OnCallDutyPolicyStatus.Error,
statusMessage:
'No Escalation Rules in Policy. Please add escalation rules to this policy.',
},
props: {
isRoot: true,
},
});
}
return createdItem;
}
}
export default new Service();

View File

@@ -0,0 +1,10 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import Model from 'Model/Models/OnCallDutyPolicyExecutionLogTimeline';
import DatabaseService from './DatabaseService';
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
}
export default new Service();

View File

@@ -0,0 +1,74 @@
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
import DatabaseService from './DatabaseService';
import ObjectID from 'Common/Types/ObjectID';
import OnCallDutyPolicyExecutionLog from 'Model/Models/OnCallDutyPolicyExecutionLog';
import OnCallDutyPolicy from 'Model/Models/OnCallDutyPolicy';
import BadDataException from 'Common/Types/Exception/BadDataException';
import OnCallDutyPolicyExecutionLogService from './OnCallDutyPolicyExecutionLogService';
import UserNotificationEventType from 'Common/Types/UserNotification/UserNotificationEventType';
import OnCallDutyPolicyStatus from 'Common/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus';
export class Service extends DatabaseService<OnCallDutyPolicy> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(OnCallDutyPolicy, postgresDatabase);
}
public async executePolicy(
policyId: ObjectID,
options: {
triggeredByIncidentId?: ObjectID | undefined;
userNotificationEventType: UserNotificationEventType;
}
): Promise<void> {
// execute this policy
if (
UserNotificationEventType.IncidentCreated ===
options.userNotificationEventType &&
!options.triggeredByIncidentId
) {
throw new BadDataException(
'triggeredByIncidentId is required when userNotificationEventType is IncidentCreated'
);
}
const policy: OnCallDutyPolicy | null = await this.findOneById({
id: policyId,
select: {
_id: true,
projectId: true,
},
props: {
isRoot: true,
},
});
if (!policy) {
throw new BadDataException(
`On Call Duty Policy with id ${policyId.toString()} not found`
);
}
// add policy log.
const log: OnCallDutyPolicyExecutionLog =
new OnCallDutyPolicyExecutionLog();
log.projectId = policy.projectId!;
log.onCallDutyPolicyId = policyId;
log.userNotificationEventType = options.userNotificationEventType;
log.statusMessage = 'Scheduled.';
log.status = OnCallDutyPolicyStatus.Scheduled;
if (options.triggeredByIncidentId) {
log.triggeredByIncidentId = options.triggeredByIncidentId;
}
await OnCallDutyPolicyExecutionLogService.create({
data: log,
props: {
isRoot: true,
},
});
}
}
export default new Service();

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