mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 08:42:13 +02:00
Compare commits
786 Commits
monitoring
...
7.0.346
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7f81ae4009 | ||
|
|
cd8f090a5e | ||
|
|
35f483c650 | ||
|
|
8238ce4c5d | ||
|
|
39ab39b024 | ||
|
|
7e3f911225 | ||
|
|
8a8f975369 | ||
|
|
bef9411dcc | ||
|
|
e861f4b53c | ||
|
|
757a66bafa | ||
|
|
217ec6bcfc | ||
|
|
dd4f518a79 | ||
|
|
c87e1513d9 | ||
|
|
b4e4eb7043 | ||
|
|
26a4ba606e | ||
|
|
88cf88d125 | ||
|
|
499dec5b95 | ||
|
|
9a107188aa | ||
|
|
6822dc4f3e | ||
|
|
6977aec52d | ||
|
|
c9a3c23302 | ||
|
|
066f055a74 | ||
|
|
1da7b9747f | ||
|
|
e29af13b73 | ||
|
|
3e4074ef4b | ||
|
|
0f8330d110 | ||
|
|
4cba9d6042 | ||
|
|
556283e7f7 | ||
|
|
696a3b5fee | ||
|
|
cdd2f241c7 | ||
|
|
2a9978b539 | ||
|
|
e1917f1fd7 | ||
|
|
cb547790cf | ||
|
|
c754101194 | ||
|
|
a1b772bda1 | ||
|
|
a0e4b6b5c7 | ||
|
|
02cb4474a3 | ||
|
|
2db09a3aba | ||
|
|
e09efd5917 | ||
|
|
b45a47e167 | ||
|
|
fab4be14dc | ||
|
|
b717f0e09e | ||
|
|
89fc67831c | ||
|
|
a504ac95d8 | ||
|
|
a4f2206c83 | ||
|
|
271535d89f | ||
|
|
13f0723405 | ||
|
|
2159332317 | ||
|
|
3757ecb104 | ||
|
|
a40986d51b | ||
|
|
d5aa9529fa | ||
|
|
edc7362fcd | ||
|
|
e9de7fae51 | ||
|
|
8877536c14 | ||
|
|
5f0be6298c | ||
|
|
3d533db7c0 | ||
|
|
46b14a4792 | ||
|
|
a0b203d9b8 | ||
|
|
b55b20a55f | ||
|
|
b91104e7bd | ||
|
|
478b4dc381 | ||
|
|
8d7c88d4d0 | ||
|
|
9c35c26558 | ||
|
|
16166a70f8 | ||
|
|
42b80bab3c | ||
|
|
2724f4eeed | ||
|
|
b6f67f8faa | ||
|
|
a0bfa75e55 | ||
|
|
1e0b19efd4 | ||
|
|
e83d63c07e | ||
|
|
7eb0b79d7b | ||
|
|
2156c8f5d5 | ||
|
|
9564e57208 | ||
|
|
2ba91d6ddf | ||
|
|
668c88db52 | ||
|
|
e4faa3c995 | ||
|
|
d86f3a0a33 | ||
|
|
4dda09b406 | ||
|
|
ef605f1248 | ||
|
|
632365da7f | ||
|
|
6ca3d003f7 | ||
|
|
889b6e00c4 | ||
|
|
dfa8591562 | ||
|
|
85d073f110 | ||
|
|
55f6faaa60 | ||
|
|
6939ee1f0d | ||
|
|
316ef6ff53 | ||
|
|
9fe2395796 | ||
|
|
7b2a31ef96 | ||
|
|
7971bb2abb | ||
|
|
5eacc2a18e | ||
|
|
70d18ba49e | ||
|
|
3c9628abdb | ||
|
|
9793d95b80 | ||
|
|
881b190fd8 | ||
|
|
e30565bce3 | ||
|
|
f9517412e5 | ||
|
|
ed6d2faa8d | ||
|
|
a1ce939ffc | ||
|
|
b34cd86f05 | ||
|
|
45e752cabf | ||
|
|
fa89f9d1a5 | ||
|
|
9db08a9347 | ||
|
|
24c4d37b2c | ||
|
|
1f866ee325 | ||
|
|
70a0087344 | ||
|
|
3dea55f035 | ||
|
|
f47a6e7c6b | ||
|
|
788e8363ef | ||
|
|
c9d1c95b38 | ||
|
|
b3a18d69cb | ||
|
|
3b9e982c35 | ||
|
|
b28a832ba7 | ||
|
|
38b96e86c3 | ||
|
|
dafcd001f7 | ||
|
|
7882897466 | ||
|
|
3e62082ac2 | ||
|
|
e8d790925b | ||
|
|
83061b1ca8 | ||
|
|
554f353990 | ||
|
|
d857de0406 | ||
|
|
e4d4bbb680 | ||
|
|
4e8631cec9 | ||
|
|
1f96504c34 | ||
|
|
c0153f0ecb | ||
|
|
42f8a90eeb | ||
|
|
090d68f4e1 | ||
|
|
dcd04ddaa1 | ||
|
|
906438c325 | ||
|
|
53ce3537e9 | ||
|
|
550d7f2621 | ||
|
|
b1707a28f8 | ||
|
|
3eb15af79c | ||
|
|
bddd932eb8 | ||
|
|
8a73a7c7ab | ||
|
|
a7b6f70ed4 | ||
|
|
3dea88a97b | ||
|
|
5728c1a18c | ||
|
|
7da678e82b | ||
|
|
7b7cbbe6b8 | ||
|
|
658b359c2c | ||
|
|
ff9f97f095 | ||
|
|
558f963648 | ||
|
|
f5883d4840 | ||
|
|
bfdecac3ba | ||
|
|
43a765479a | ||
|
|
07b33b68ab | ||
|
|
e83b118904 | ||
|
|
fb798290a5 | ||
|
|
46c33b4d1e | ||
|
|
3492e7f949 | ||
|
|
5a5b861f69 | ||
|
|
17938ddb3f | ||
|
|
3ea065a620 | ||
|
|
2f6f8044b8 | ||
|
|
7a17eb12dc | ||
|
|
dd8d9b3e3f | ||
|
|
22fc04f06a | ||
|
|
9a121ec62e | ||
|
|
7909bc95ee | ||
|
|
cad11997f4 | ||
|
|
908a7a2695 | ||
|
|
d5b4bdbf6b | ||
|
|
bc482345ce | ||
|
|
a04416e7e7 | ||
|
|
a04eb341e1 | ||
|
|
687c1bbb67 | ||
|
|
4462ee9bc2 | ||
|
|
2379a6fd86 | ||
|
|
99462978cc | ||
|
|
ae7c32a32d | ||
|
|
6e4b23293f | ||
|
|
21a017a8ba | ||
|
|
5a99e66427 | ||
|
|
786e88eef5 | ||
|
|
bb45041dec | ||
|
|
0f92ba3e63 | ||
|
|
25b065eef4 | ||
|
|
dcd35b4686 | ||
|
|
a9fc2305eb | ||
|
|
7f741cec1b | ||
|
|
c03e8f2d67 | ||
|
|
4691444545 | ||
|
|
970e6c4af2 | ||
|
|
31e0376e62 | ||
|
|
cc24dad2cd | ||
|
|
74a36c6918 | ||
|
|
ab0472005e | ||
|
|
e171a8c845 | ||
|
|
5de055a350 | ||
|
|
3c04194dfd | ||
|
|
aee54309d8 | ||
|
|
5831fdfa3e | ||
|
|
5267cdfbeb | ||
|
|
6094b577ef | ||
|
|
b1f734166f | ||
|
|
52060d1393 | ||
|
|
9a1589259f | ||
|
|
12ae9a1b74 | ||
|
|
ed7395db70 | ||
|
|
6a63556fd2 | ||
|
|
4ecfce4a5d | ||
|
|
6f827a68c0 | ||
|
|
8afdf966f3 | ||
|
|
e9e5533372 | ||
|
|
e8acdad270 | ||
|
|
d11116544c | ||
|
|
4741028cc2 | ||
|
|
56af44885d | ||
|
|
cc30864ada | ||
|
|
5291f78895 | ||
|
|
731f4da92a | ||
|
|
da6615ad6f | ||
|
|
251c763245 | ||
|
|
ac29692485 | ||
|
|
2e0e8f6956 | ||
|
|
74e1532079 | ||
|
|
2657bca277 | ||
|
|
9704adba03 | ||
|
|
a1960cb749 | ||
|
|
b288117b4f | ||
|
|
c22f3f3191 | ||
|
|
3b4e0a8dbc | ||
|
|
6ef9445b46 | ||
|
|
55856e9ff0 | ||
|
|
8b8585f86c | ||
|
|
ad427fa6b4 | ||
|
|
3d4519e2bd | ||
|
|
d0f0454a0c | ||
|
|
e0601e75fa | ||
|
|
a4951a264b | ||
|
|
b8485a1c3e | ||
|
|
54b4f47b6a | ||
|
|
c558909fd0 | ||
|
|
da3f02f855 | ||
|
|
f1ea93719c | ||
|
|
fc59f65fca | ||
|
|
bddf072511 | ||
|
|
f5a4cc3c1d | ||
|
|
a7e1430898 | ||
|
|
d0cb4b5b17 | ||
|
|
f5055d744e | ||
|
|
8d308b0a7c | ||
|
|
1515cd7478 | ||
|
|
604a5c0c9f | ||
|
|
ba46931979 | ||
|
|
7d620595d2 | ||
|
|
d186adbbbb | ||
|
|
3bc6794948 | ||
|
|
f5e0f90e11 | ||
|
|
536e0e3cf8 | ||
|
|
b82c2acf67 | ||
|
|
bd46971ad8 | ||
|
|
61cbae6a3f | ||
|
|
d9c13333ed | ||
|
|
6716339317 | ||
|
|
49b4388491 | ||
|
|
6300416593 | ||
|
|
c7aa6123b2 | ||
|
|
df17c47dd4 | ||
|
|
5e8962917b | ||
|
|
112b72d2ed | ||
|
|
3d3bf1d092 | ||
|
|
e5f7fc4cef | ||
|
|
bf82694b6e | ||
|
|
d1fa52c8dc | ||
|
|
577d1dceea | ||
|
|
9b4e3172c3 | ||
|
|
b7db3a42b5 | ||
|
|
a8292e5183 | ||
|
|
bf2b95fda7 | ||
|
|
3f1550096c | ||
|
|
860beafd74 | ||
|
|
66839a01d6 | ||
|
|
cf4fbdc8fc | ||
|
|
f2a1a0596d | ||
|
|
40e72a4c00 | ||
|
|
30cae266b0 | ||
|
|
d54708b2c4 | ||
|
|
f33d35a45b | ||
|
|
de1f64aa6b | ||
|
|
a325b66034 | ||
|
|
031ed59108 | ||
|
|
8e78d74568 | ||
|
|
1c3b462a8f | ||
|
|
ee25e8f218 | ||
|
|
573c074aef | ||
|
|
53b55ac7f6 | ||
|
|
f054b131e4 | ||
|
|
f80ae8e806 | ||
|
|
5464fed1a8 | ||
|
|
b4311d02d4 | ||
|
|
7778182f02 | ||
|
|
b5fb766f3d | ||
|
|
d236131171 | ||
|
|
f88c0d5161 | ||
|
|
9eab1cd1c1 | ||
|
|
a68cefd27c | ||
|
|
71ce42476b | ||
|
|
e795470ea7 | ||
|
|
f87f721487 | ||
|
|
962c79e3dc | ||
|
|
2ef0c9334d | ||
|
|
f18bb3a3de | ||
|
|
d724932660 | ||
|
|
4de9a308bd | ||
|
|
1760731fab | ||
|
|
88e554d26b | ||
|
|
50dac60b65 | ||
|
|
c2fb75cdc5 | ||
|
|
560acb7626 | ||
|
|
394571144d | ||
|
|
35fef64623 | ||
|
|
fdaca5f804 | ||
|
|
716fe16487 | ||
|
|
7d63433f65 | ||
|
|
ea122c0e77 | ||
|
|
f0d71bc65b | ||
|
|
c33b2b0946 | ||
|
|
0475c18b0f | ||
|
|
8396d7cbd7 | ||
|
|
66e34014b9 | ||
|
|
908c108116 | ||
|
|
8130bb3bb7 | ||
|
|
0813f1425f | ||
|
|
3f9ca54c61 | ||
|
|
03c49bc5cc | ||
|
|
7007834394 | ||
|
|
e7ee37c218 | ||
|
|
5590b4fde2 | ||
|
|
1750692328 | ||
|
|
03ceda4f77 | ||
|
|
110f596cf6 | ||
|
|
63288ab589 | ||
|
|
c9480bea8f | ||
|
|
3a78307c2e | ||
|
|
89ed205b50 | ||
|
|
490edf1859 | ||
|
|
5fb42b9c6d | ||
|
|
d5e07fc788 | ||
|
|
c3c871f9cc | ||
|
|
72635b8c8f | ||
|
|
057d895aaf | ||
|
|
407fc1240a | ||
|
|
2bc307c564 | ||
|
|
c42790e6f2 | ||
|
|
ecdbea2aab | ||
|
|
7cb98456b1 | ||
|
|
4f80317b14 | ||
|
|
7a589d65a3 | ||
|
|
acd5d04ee9 | ||
|
|
998c85e393 | ||
|
|
70478bd1fa | ||
|
|
4c06feeb50 | ||
|
|
2acd6d5ce0 | ||
|
|
56e7c0c7d0 | ||
|
|
7948070be6 | ||
|
|
a9139fcca0 | ||
|
|
99b3dc65a7 | ||
|
|
599c7a175e | ||
|
|
0a03dc652c | ||
|
|
53f72c2192 | ||
|
|
53334ad3dc | ||
|
|
4d7ddf7be1 | ||
|
|
9dfdd0841f | ||
|
|
7f662291e4 | ||
|
|
9bbd32424e | ||
|
|
41b5fe3a19 | ||
|
|
d35195a591 | ||
|
|
ee229d3711 | ||
|
|
9eb12a5348 | ||
|
|
0bb8343f0b | ||
|
|
d5c13f5c26 | ||
|
|
9e57fe1531 | ||
|
|
8b10e0d9f0 | ||
|
|
45d7dc90b3 | ||
|
|
da2683391d | ||
|
|
ea50830dae | ||
|
|
985a7ca973 | ||
|
|
2c649bed07 | ||
|
|
78fad54d6a | ||
|
|
05c583fd81 | ||
|
|
b99912abd6 | ||
|
|
c3a5a8a4e8 | ||
|
|
ad451fd9c9 | ||
|
|
ce31e0cfff | ||
|
|
545dcea3e8 | ||
|
|
29accb2e6f | ||
|
|
8cb8a1ed72 | ||
|
|
a8beed5c5c | ||
|
|
8d59fdc732 | ||
|
|
a7fe18fd65 | ||
|
|
e80835c380 | ||
|
|
bbd60075fa | ||
|
|
622bb87b89 | ||
|
|
3d3c9876eb | ||
|
|
ea588be0f7 | ||
|
|
0fe1779ce4 | ||
|
|
71f2d3b87a | ||
|
|
8d0670d05c | ||
|
|
1b6eccfb36 | ||
|
|
9a7c2cedf5 | ||
|
|
55b9a6bf9f | ||
|
|
9ddca843c8 | ||
|
|
2a1786147b | ||
|
|
1bc572c4be | ||
|
|
f961796c7c | ||
|
|
ff1f564527 | ||
|
|
6ef61221bf | ||
|
|
1b7d17fb9e | ||
|
|
04f7d1f8bf | ||
|
|
2edbe0df08 | ||
|
|
a96dc90104 | ||
|
|
3e8b966dc8 | ||
|
|
1ee94f10c4 | ||
|
|
74866edadb | ||
|
|
e402ebc14c | ||
|
|
4297cead16 | ||
|
|
da021bbd10 | ||
|
|
ab48de6e9b | ||
|
|
314b905e8f | ||
|
|
db60c0fefb | ||
|
|
713d9464a2 | ||
|
|
84cc4a35d4 | ||
|
|
6a64b8658a | ||
|
|
b8ee827068 | ||
|
|
8fea1b6e3d | ||
|
|
96934f5f22 | ||
|
|
a2ad4d30e7 | ||
|
|
0623588019 | ||
|
|
f1d087da44 | ||
|
|
5dca4a0fd3 | ||
|
|
7d085274de | ||
|
|
1da9184a14 | ||
|
|
12c429597c | ||
|
|
314a9ef61c | ||
|
|
5961504577 | ||
|
|
a7757e547c | ||
|
|
6a4e2cfcb7 | ||
|
|
6744c92cf3 | ||
|
|
7c4f2c3279 | ||
|
|
d68b066127 | ||
|
|
236fdbe8ab | ||
|
|
92a5710055 | ||
|
|
f2715f7637 | ||
|
|
4339abe9d6 | ||
|
|
341f30e6a5 | ||
|
|
17967a691d | ||
|
|
333160db8a | ||
|
|
bb5ac117d8 | ||
|
|
4277b8c1c4 | ||
|
|
8bd9bf4136 | ||
|
|
b5ac6c7f01 | ||
|
|
829a97ffbb | ||
|
|
bc50e4f330 | ||
|
|
28c01a9d9f | ||
|
|
94bcbc7c6a | ||
|
|
6fb2b3d3ac | ||
|
|
d0ae06119f | ||
|
|
c68b41089a | ||
|
|
68d35d94de | ||
|
|
72d5b4c186 | ||
|
|
e3c613c1a1 | ||
|
|
ded0e2638b | ||
|
|
bb609e2ccc | ||
|
|
ecbd725fb2 | ||
|
|
3b5c2b2cc6 | ||
|
|
38000fdbec | ||
|
|
f07d68c049 | ||
|
|
99a782e0e9 | ||
|
|
05138909ca | ||
|
|
c495f3295e | ||
|
|
e2c99bd4e2 | ||
|
|
9e695e5117 | ||
|
|
7c6100ff69 | ||
|
|
22361ea3a1 | ||
|
|
ff9706b3e4 | ||
|
|
0b02f6027f | ||
|
|
ac44e21db7 | ||
|
|
e036492296 | ||
|
|
4b49297e2a | ||
|
|
6e09a95431 | ||
|
|
8110cca424 | ||
|
|
11bc9654ab | ||
|
|
5d08a20a7d | ||
|
|
1ed51a6dc2 | ||
|
|
3027f11164 | ||
|
|
7baafd0db6 | ||
|
|
d0f7831505 | ||
|
|
457a457eee | ||
|
|
f7ef0a8e96 | ||
|
|
d3d0fa1593 | ||
|
|
edc4e472e9 | ||
|
|
39c6e36e2f | ||
|
|
eeb5cf1cce | ||
|
|
c018f95e70 | ||
|
|
125c6417cf | ||
|
|
19be9f42b6 | ||
|
|
4b17d3a125 | ||
|
|
d7c8edd598 | ||
|
|
b0f4083297 | ||
|
|
b840f78d1d | ||
|
|
83289cc80e | ||
|
|
2a7f18fa60 | ||
|
|
aed03ffcb3 | ||
|
|
673f97404b | ||
|
|
8459e2873c | ||
|
|
3b0904a01d | ||
|
|
3f53053e1f | ||
|
|
9a1e27db5c | ||
|
|
82849c28ce | ||
|
|
08bd171b2f | ||
|
|
844611d176 | ||
|
|
aaa3b9af3e | ||
|
|
6c10f81226 | ||
|
|
c2fe4d3e5e | ||
|
|
fd3bc4dd86 | ||
|
|
05d20e200f | ||
|
|
7a2e44a404 | ||
|
|
0eb28ee669 | ||
|
|
77ac490b71 | ||
|
|
a018b9fa94 | ||
|
|
d16cf40914 | ||
|
|
e0e6678f65 | ||
|
|
387f3a366e | ||
|
|
e446583376 | ||
|
|
85a1ee8ae7 | ||
|
|
2a5c7cfbfe | ||
|
|
fdbfcef3c0 | ||
|
|
db50d12d8a | ||
|
|
0a07ad6cd3 | ||
|
|
0970f453e4 | ||
|
|
742ee7c3cf | ||
|
|
05199efd12 | ||
|
|
c931698fd6 | ||
|
|
39455e86eb | ||
|
|
057369ad4a | ||
|
|
c4ef932e13 | ||
|
|
8523da6628 | ||
|
|
42f94a468a | ||
|
|
6ee03152f8 | ||
|
|
571b5d6ece | ||
|
|
ce415d16e4 | ||
|
|
6f88062add | ||
|
|
bf31b15930 | ||
|
|
0426a86f62 | ||
|
|
ad907aa854 | ||
|
|
641b27101f | ||
|
|
f0e77de240 | ||
|
|
639c4b13ae | ||
|
|
e9af3e0b48 | ||
|
|
41b4092428 | ||
|
|
5f54f76698 | ||
|
|
75e7a720f7 | ||
|
|
63211a69d8 | ||
|
|
0efaec6b7b | ||
|
|
39a00e9fc2 | ||
|
|
22ccdf444f | ||
|
|
6372caeadf | ||
|
|
95c6cee3e2 | ||
|
|
ab25a98372 | ||
|
|
5618f02992 | ||
|
|
932101677b | ||
|
|
b3beca8c14 | ||
|
|
bbbfb45cde | ||
|
|
bc0085c330 | ||
|
|
dc0108939c | ||
|
|
092449fdd3 | ||
|
|
ce44710365 | ||
|
|
c55bdfc80d | ||
|
|
5897dfe598 | ||
|
|
2f60006f9c | ||
|
|
d5721524d0 | ||
|
|
258efa9f1b | ||
|
|
5627eae96b | ||
|
|
98e7a6a5f2 | ||
|
|
681d3cc276 | ||
|
|
f41fd6f17f | ||
|
|
9015e74371 | ||
|
|
61a149c839 | ||
|
|
020af0084c | ||
|
|
856ba620cf | ||
|
|
369a65d46b | ||
|
|
7375e6e528 | ||
|
|
adea15b069 | ||
|
|
97217de1b8 | ||
|
|
5733917fee | ||
|
|
4e80778275 | ||
|
|
57e03bc3db | ||
|
|
4bb76db00c | ||
|
|
57913a674d | ||
|
|
449e194aad | ||
|
|
6de0854892 | ||
|
|
7ec5e50b54 | ||
|
|
f67e3a54a0 | ||
|
|
9b6a7915af | ||
|
|
06ca30fcc7 | ||
|
|
f8e3a3544f | ||
|
|
eb7002960d | ||
|
|
4229561790 | ||
|
|
6241d701da | ||
|
|
3c16c2c535 | ||
|
|
a9e315ff15 | ||
|
|
cff210d5df | ||
|
|
726bbf9c0d | ||
|
|
a3daff2a83 | ||
|
|
435c8f083b | ||
|
|
759ffe72c8 | ||
|
|
cd9f68d67c | ||
|
|
f5102f3e55 | ||
|
|
ac9eb27691 | ||
|
|
f3eb085986 | ||
|
|
86e80e6084 | ||
|
|
2ad76f0a83 | ||
|
|
e9e39ed1e4 | ||
|
|
9492674578 | ||
|
|
9f60b59ec9 | ||
|
|
c01600b32a | ||
|
|
0a243381d6 | ||
|
|
397bbfd3bf | ||
|
|
bc2d5d5cac | ||
|
|
cdf025d326 | ||
|
|
e2f0dda07c | ||
|
|
6ec237ec9d | ||
|
|
df97a2a67e | ||
|
|
8c8acb083a | ||
|
|
c64161a52d | ||
|
|
d0fd03c180 | ||
|
|
307141b835 | ||
|
|
833f0504d0 | ||
|
|
9439fb337e | ||
|
|
89d45ea99a | ||
|
|
adbda5ff9a | ||
|
|
4b5ea139d4 | ||
|
|
51d28b0af5 | ||
|
|
06375f478e | ||
|
|
b72dcc691a | ||
|
|
4090fc9bd1 | ||
|
|
008655b6eb | ||
|
|
73bf0a26c7 | ||
|
|
fb3153cf2e | ||
|
|
193508c0c7 | ||
|
|
64fa6e68ea | ||
|
|
c6de2b7514 | ||
|
|
489757dc96 | ||
|
|
3c9216755a | ||
|
|
5c78bbb456 | ||
|
|
965d731b25 | ||
|
|
18595722f0 | ||
|
|
1dfa269d2d | ||
|
|
c833806441 | ||
|
|
8a3099d85d | ||
|
|
04bf2bd1e4 | ||
|
|
f5e79ebd2e | ||
|
|
e4bb7b4019 | ||
|
|
31b0d6cb06 | ||
|
|
d5ef79de33 | ||
|
|
e7fd6dae3a | ||
|
|
6eec2b54f7 | ||
|
|
8dbb768056 | ||
|
|
01d26b08a2 | ||
|
|
6e432d67e7 | ||
|
|
d77381652a | ||
|
|
26d69b4a07 | ||
|
|
d6fd7a47e5 | ||
|
|
2beb2414e6 | ||
|
|
05540db978 | ||
|
|
1a40e9af8e | ||
|
|
63c89f5b1a | ||
|
|
f7b1f5fa9a | ||
|
|
e1f3b454ce | ||
|
|
fa04df806c | ||
|
|
749d1f0228 | ||
|
|
fde6c94351 | ||
|
|
3810821fc2 | ||
|
|
74aa7c60b4 | ||
|
|
39d56d13d5 | ||
|
|
2148ec7462 | ||
|
|
303c68476e | ||
|
|
cb797be1be | ||
|
|
d314c6fdbd | ||
|
|
82ca306fbe | ||
|
|
095a29b39d | ||
|
|
e04c2f328c | ||
|
|
24b35de5b2 | ||
|
|
278aea59d5 | ||
|
|
ed42c36bbf | ||
|
|
b4e1404828 | ||
|
|
48edfd9812 | ||
|
|
e494fabd48 | ||
|
|
dec65d701a | ||
|
|
ed8f9ea839 | ||
|
|
e3421a72df | ||
|
|
6868fc299e | ||
|
|
4362923ff6 | ||
|
|
e25995c617 | ||
|
|
72ebe62b86 | ||
|
|
ce32efd51d | ||
|
|
0c1425f430 | ||
|
|
27f38db033 | ||
|
|
9059fa530e | ||
|
|
7f32989720 | ||
|
|
527026d7b4 | ||
|
|
34101de6d0 | ||
|
|
5d82d7d619 | ||
|
|
1f7b124594 | ||
|
|
6d5d9416f8 | ||
|
|
d0d2162a51 | ||
|
|
69d93e4330 | ||
|
|
0cb2a98047 | ||
|
|
5fc4fa60ed | ||
|
|
24c30f884e | ||
|
|
4f823062c5 | ||
|
|
95f324fa80 | ||
|
|
6cab95c41b | ||
|
|
46bbc2cf96 | ||
|
|
b354cd0f25 | ||
|
|
173d2c7cde | ||
|
|
cf795c1633 | ||
|
|
ab31200f45 | ||
|
|
d5d4da389f | ||
|
|
b288dbb694 | ||
|
|
ccdc3f92dd | ||
|
|
af3a6b2f3f | ||
|
|
99da78d7db | ||
|
|
254bae0956 | ||
|
|
2c1f094acd | ||
|
|
49563e9cbe | ||
|
|
bf506e23d7 | ||
|
|
f9645979c2 | ||
|
|
cf2ff65de5 | ||
|
|
6a248478d2 | ||
|
|
bc593b18e0 | ||
|
|
6182d84d57 | ||
|
|
87ee6674c7 | ||
|
|
78f2b0b4c5 | ||
|
|
70bcc80b5e | ||
|
|
8bffd8a9b7 | ||
|
|
0e6a365046 | ||
|
|
ad70f1e09d | ||
|
|
4ff2b5a2da | ||
|
|
39801c9c0d | ||
|
|
75bb276349 | ||
|
|
72ca3ac51e | ||
|
|
d1decf9143 | ||
|
|
ddaea04182 | ||
|
|
d0ca7d9067 | ||
|
|
837de39cf7 | ||
|
|
4fb07bfa83 | ||
|
|
b292c61341 | ||
|
|
46cf642b8f | ||
|
|
9e1fa1e008 | ||
|
|
1631836e29 | ||
|
|
c1b2e1ef83 | ||
|
|
0806fbe36e | ||
|
|
1ba205b4d6 | ||
|
|
3381931fed | ||
|
|
57e3a50e41 | ||
|
|
4238dbd651 | ||
|
|
3beb60362d | ||
|
|
856f46cfce | ||
|
|
4de9193e28 | ||
|
|
bf0f2d2f79 | ||
|
|
f0483c9df6 | ||
|
|
fa524ed2e1 | ||
|
|
9e272ff85b | ||
|
|
7b3249155e | ||
|
|
fe655b0e3a | ||
|
|
9e987fd899 | ||
|
|
f428ae12aa | ||
|
|
7d75f9eed2 | ||
|
|
5cd0fc9853 | ||
|
|
73c1eb2b78 | ||
|
|
ddda137c12 | ||
|
|
0d44b0ca13 | ||
|
|
001a4b153b | ||
|
|
4556a7e322 | ||
|
|
bf7707b2a9 | ||
|
|
a834045b00 | ||
|
|
155af6e9a8 | ||
|
|
59ae6d7e56 | ||
|
|
d4c3e287a6 | ||
|
|
3c5e169b58 | ||
|
|
f4000b1dd3 | ||
|
|
89fd950af9 | ||
|
|
4fca7fc0ee |
32
.github/workflows/compile.yml
vendored
32
.github/workflows/compile.yml
vendored
@@ -25,20 +25,6 @@ jobs:
|
||||
- run: cd CommonUI && npm install --force
|
||||
- run: cd Accounts && npm install && npm run compile
|
||||
|
||||
compile-alert:
|
||||
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 Alert && npm install && npm run compile
|
||||
|
||||
compile-api-reference:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
@@ -53,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:
|
||||
@@ -205,7 +205,7 @@ jobs:
|
||||
- run: cd CommonServer && npm install
|
||||
- run: cd Licensing && npm install && npm run compile
|
||||
|
||||
compile-mail:
|
||||
compile-notification:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
@@ -217,7 +217,7 @@ jobs:
|
||||
- run: cd Common && npm install
|
||||
- run: cd Model && npm install
|
||||
- run: cd CommonServer && npm install
|
||||
- run: cd Mail && npm install && npm run compile
|
||||
- run: cd Notification && npm install && npm run compile
|
||||
|
||||
compile-model:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
26
.github/workflows/docker-build.yml
vendored
26
.github/workflows/docker-build.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Accounts/Dockerfile .
|
||||
|
||||
docker-build-alert:
|
||||
docker-build-link-shortner:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
@@ -35,10 +35,10 @@ jobs:
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
|
||||
# build image for mail service
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Alert/Dockerfile .
|
||||
run: sudo docker build -f ./LinkShortner/Dockerfile .
|
||||
|
||||
docker-build-api-reference:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -191,7 +191,7 @@ jobs:
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Licensing/Dockerfile .
|
||||
|
||||
docker-build-mail:
|
||||
docker-build-notification:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
@@ -204,22 +204,8 @@ jobs:
|
||||
|
||||
# build image for mail service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Mail/Dockerfile .
|
||||
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
|
||||
|
||||
6
.github/workflows/playwright.yml.skip
vendored
6
.github/workflows/playwright.yml.skip
vendored
@@ -8,6 +8,8 @@ jobs:
|
||||
test:
|
||||
timeout-minutes: 60
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
BASE_URL: http://localhost
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
@@ -15,10 +17,12 @@ jobs:
|
||||
node-version: 16
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Run Server in Docker
|
||||
run: npm run dev
|
||||
- name: Install Playwright Browsers
|
||||
run: npx playwright install --with-deps
|
||||
- name: Run Playwright tests
|
||||
run: npx playwright test
|
||||
run: cd Playwright && npm install && npx playwright install && npx playwright test
|
||||
- uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
|
||||
174
.github/workflows/release.yml
vendored
174
.github/workflows/release.yml
vendored
@@ -7,16 +7,30 @@ on:
|
||||
|
||||
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 }}"
|
||||
|
||||
github-release:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
env:
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: release
|
||||
- run: echo "${{needs.generate-build-number.outputs.build_number}}"
|
||||
- name: "Build Changelog"
|
||||
id: build_changelog
|
||||
uses: mikepenz/release-changelog-builder-action@v3.7.1
|
||||
@@ -27,13 +41,38 @@ jobs:
|
||||
body: |
|
||||
${{steps.build_changelog.outputs.changelog}}
|
||||
|
||||
|
||||
|
||||
test-server-docker-image-deploy:
|
||||
nginx-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: release
|
||||
- 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 --tag oneuptime/nginx:release --push -f ./Nginx/Dockerfile .
|
||||
|
||||
|
||||
test-server-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@v3
|
||||
with:
|
||||
@@ -51,11 +90,12 @@ jobs:
|
||||
|
||||
|
||||
workflow-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -71,12 +111,35 @@ jobs:
|
||||
- run: sudo docker buildx create --use
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/workflow:$ONEUPTIME_VERSION --tag oneuptime/workflow:release --push -f ./Workflow/Dockerfile .
|
||||
|
||||
workers-docker-image-deploy:
|
||||
link-shortner-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: release
|
||||
- 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/link-shortner:$ONEUPTIME_VERSION --tag oneuptime/link-shortner:release --push -f ./LinkShortner/Dockerfile .
|
||||
|
||||
workers-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@v3
|
||||
with:
|
||||
@@ -92,12 +155,13 @@ jobs:
|
||||
- run: sudo docker buildx create --use
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/workers:$ONEUPTIME_VERSION --tag oneuptime/workers:release --push -f ./Workers/Dockerfile .
|
||||
|
||||
staus-page-docker-image-deploy:
|
||||
status-page-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -114,11 +178,12 @@ jobs:
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/status-page:$ONEUPTIME_VERSION --tag oneuptime/status-page:release --push -f ./StatusPage/Dockerfile .
|
||||
|
||||
realtime-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -136,11 +201,12 @@ jobs:
|
||||
|
||||
|
||||
probe-api-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -156,34 +222,15 @@ jobs:
|
||||
- run: sudo docker buildx create --use
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/probe-api:$ONEUPTIME_VERSION --tag oneuptime/probe-api:release --push -f ./ProbeAPI/Dockerfile .
|
||||
|
||||
nginx-docker-image-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: release
|
||||
- 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 --tag oneuptime/nginx:release --push -f ./Nginx/Dockerfile .
|
||||
|
||||
|
||||
mail-docker-image-deploy:
|
||||
notification-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -196,15 +243,16 @@ jobs:
|
||||
# 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/mail:$ONEUPTIME_VERSION --tag oneuptime/mail:release --push -f ./Mail/Dockerfile .
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/notification:$ONEUPTIME_VERSION --tag oneuptime/notification:release --push -f ./Notification/Dockerfile .
|
||||
|
||||
|
||||
licensing-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -221,11 +269,12 @@ jobs:
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/licensing:$ONEUPTIME_VERSION --tag oneuptime/licensing:release --push -f ./Licensing/Dockerfile .
|
||||
|
||||
integrations-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -243,11 +292,12 @@ jobs:
|
||||
|
||||
|
||||
probe-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -264,11 +314,12 @@ jobs:
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/probe:$ONEUPTIME_VERSION --tag oneuptime/probe:release --push -f ./Probe/Dockerfile .
|
||||
|
||||
identity-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -286,11 +337,12 @@ jobs:
|
||||
|
||||
|
||||
home-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -308,11 +360,12 @@ jobs:
|
||||
|
||||
|
||||
helm-chart-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -330,11 +383,12 @@ jobs:
|
||||
|
||||
|
||||
haraka-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -351,11 +405,12 @@ jobs:
|
||||
- run: sudo docker buildx build --platform linux/amd64,linux/arm64 --tag oneuptime/haraka:$ONEUPTIME_VERSION --tag oneuptime/haraka:release --push -f ./Haraka/Dockerfile .
|
||||
|
||||
file-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -373,11 +428,12 @@ jobs:
|
||||
|
||||
|
||||
dashboard-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -397,11 +453,12 @@ jobs:
|
||||
|
||||
|
||||
dashboard-api-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -421,11 +478,12 @@ jobs:
|
||||
|
||||
|
||||
api-reference-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -443,37 +501,13 @@ jobs:
|
||||
|
||||
|
||||
|
||||
|
||||
alert-docker-image-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: release
|
||||
- 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/alert:$ONEUPTIME_VERSION --tag oneuptime/alert:release --push -f ./Alert/Dockerfile .
|
||||
|
||||
|
||||
|
||||
|
||||
accounts-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
|
||||
159
.github/workflows/test-release.yml
vendored
159
.github/workflows/test-release.yml
vendored
@@ -6,13 +6,45 @@ on:
|
||||
- "master"
|
||||
|
||||
jobs:
|
||||
|
||||
test-server-test-docker-image-deploy:
|
||||
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: 6.0.${{github.run_number}}
|
||||
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 .
|
||||
|
||||
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
|
||||
@@ -26,12 +58,33 @@ jobs:
|
||||
- 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:
|
||||
link-shortner-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: 6.0.${{github.run_number}}
|
||||
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/link-shortner:$ONEUPTIME_VERSION-test --tag oneuptime/link-shortner:test --push -f ./LinkShortner/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
|
||||
@@ -46,11 +99,12 @@ jobs:
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -64,12 +118,13 @@ jobs:
|
||||
- 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 .
|
||||
|
||||
staus-page-test-docker-image-deploy:
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -84,11 +139,12 @@ jobs:
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -104,11 +160,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -123,11 +180,12 @@ jobs:
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -140,33 +198,15 @@ jobs:
|
||||
- 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:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_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 .
|
||||
|
||||
|
||||
mail-test-docker-image-deploy:
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -177,15 +217,16 @@ jobs:
|
||||
# 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/mail:$ONEUPTIME_VERSION-test --tag oneuptime/mail:test --push -f ./Mail/Dockerfile .
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -200,11 +241,12 @@ jobs:
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -222,11 +264,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -242,11 +285,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -262,11 +306,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -282,11 +327,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -301,11 +347,12 @@ jobs:
|
||||
- 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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -321,11 +368,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -343,11 +391,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -365,11 +414,12 @@ jobs:
|
||||
|
||||
|
||||
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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
@@ -384,36 +434,17 @@ jobs:
|
||||
- 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 .
|
||||
|
||||
|
||||
|
||||
|
||||
alert-test-docker-image-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
DOCKERHUB_PASSWORD: ${{secrets.DOCKERHUB_PASSWORD}}
|
||||
DOCKERHUB_USERNAME: ${{secrets.DOCKERHUB_USERNAME}}
|
||||
ONEUPTIME_VERSION: 6.0.${{github.run_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/alert:$ONEUPTIME_VERSION-test --tag oneuptime/alert:test --push -f ./Alert/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: 6.0.${{github.run_number}}
|
||||
ONEUPTIME_VERSION: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
|
||||
2
.github/workflows/test.common-server.yaml
vendored
2
.github/workflows/test.common-server.yaml
vendored
@@ -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
4
.gitignore
vendored
@@ -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
|
||||
|
||||
50
.vscode/launch.json
vendored
50
.vscode/launch.json
vendored
@@ -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",
|
||||
@@ -113,9 +141,9 @@
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Mail",
|
||||
"name": "Mail: Debug with Docker",
|
||||
"port": 9110,
|
||||
"localRoot": "${workspaceFolder}/Notification",
|
||||
"name": "Notification: Debug with Docker",
|
||||
"port": 9111,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
"request": "attach",
|
||||
"skipFiles": [
|
||||
@@ -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",
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
PORT=3003
|
||||
@@ -1 +0,0 @@
|
||||
PORT={{ .Env.ACCOUNTS_PORT }}
|
||||
@@ -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 }}
|
||||
|
||||
1
Accounts/dev-env/README.md
Normal file
1
Accounts/dev-env/README.md
Normal 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.
|
||||
@@ -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"
|
||||
}
|
||||
203
Accounts/package-lock.json
generated
203
Accounts/package-lock.json
generated
@@ -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",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"compile": "tsc",
|
||||
"start": "node --require ts-node/register Serve.ts",
|
||||
"audit": "npm audit --audit-level=low",
|
||||
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"configure": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"dep-check": "depcheck ./ --skip-missing=true'"
|
||||
},
|
||||
"browserslist": {
|
||||
|
||||
@@ -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')}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,70 +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: {
|
||||
password: true,
|
||||
},
|
||||
validation: {
|
||||
minLength: 6,
|
||||
toMatchField: 'password',
|
||||
},
|
||||
fieldType: FormFieldSchemaType.Password,
|
||||
placeholder: 'Confirm Password',
|
||||
title: 'Confirm Password',
|
||||
overideFieldKey: 'confirmPassword',
|
||||
required: true,
|
||||
},
|
||||
]}
|
||||
fields={formFields}
|
||||
apiUrl={apiUrl}
|
||||
formType={FormType.Create}
|
||||
submitButtonText={'Sign Up'}
|
||||
|
||||
@@ -68,7 +68,7 @@ const VerifyEmail: FunctionComponent = () => {
|
||||
<div className="d-flex flex-column h-100">
|
||||
<div className="auth-content my-auto">
|
||||
<div
|
||||
className="mt-4 text-center"
|
||||
className="mt-4 text-center flex justify-center"
|
||||
style={{ marginBottom: '40px' }}
|
||||
>
|
||||
<img
|
||||
@@ -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>
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
PORT={{ .Env.ALERT_PORT }}
|
||||
7749
Alert/package-lock.json
generated
7749
Alert/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1 +0,0 @@
|
||||
PORT={{ .Env.API_DOCS_PORT }}
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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> =
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "oneuptime-homepage",
|
||||
"version": "3.0.0",
|
||||
"scripts": {
|
||||
"preinstall": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"configure": "npx npm-force-resolutions || echo 'No package-lock.json file. Skipping force resolutions'",
|
||||
"start": "node --require ts-node/register Index.ts",
|
||||
"compile": "tsc",
|
||||
"dev": "npx nodemon",
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
3
Clickhouse/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Clickhouse
|
||||
|
||||
This folder is for clickhouse related files.
|
||||
@@ -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 }}
|
||||
@@ -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
|
||||
@@ -45,6 +49,7 @@ export type DbTypes =
|
||||
| URL
|
||||
| Phone
|
||||
| JSONObject
|
||||
| ObjectID
|
||||
| JSONArray
|
||||
| Buffer;
|
||||
|
||||
@@ -201,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 {
|
||||
|
||||
@@ -28,7 +28,7 @@ export default class FileModel extends BaseModel {
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.File,
|
||||
canReadOnPopulate: true,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
@@ -46,7 +46,7 @@ export default class FileModel extends BaseModel {
|
||||
type: TableColumnType.ShortText,
|
||||
title: 'Name',
|
||||
description: 'Any friendly name of this object',
|
||||
canReadOnPopulate: true,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
@@ -63,7 +63,7 @@ export default class FileModel extends BaseModel {
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
canReadOnPopulate: true,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
@@ -81,7 +81,7 @@ export default class FileModel extends BaseModel {
|
||||
required: true,
|
||||
unique: true,
|
||||
type: TableColumnType.Slug,
|
||||
canReadOnPopulate: true,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
@@ -99,7 +99,7 @@ export default class FileModel extends BaseModel {
|
||||
required: true,
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Slug,
|
||||
canReadOnPopulate: true,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
|
||||
298
Common/Tests/Types/Billing/SubscriptionPlan.test.ts
Normal file
298
Common/Tests/Types/Billing/SubscriptionPlan.test.ts
Normal file
@@ -0,0 +1,298 @@
|
||||
import SubscriptionPlan, {
|
||||
PlanSelect,
|
||||
} from '../../../Types/Billing/SubscriptionPlan';
|
||||
import { JSONObject } from '../../../Types/JSON';
|
||||
import BadDataException from '../../../Types/Exception/BadDataException';
|
||||
|
||||
describe('SubscriptionPlan', () => {
|
||||
const monthlyPlanId: string = 'monthly_plan_id';
|
||||
const yearlyPlanId: string = 'yearly_plan_id';
|
||||
const name: string = 'Test Plan';
|
||||
const monthlySubscriptionAmountInUSD: number = 0;
|
||||
const yearlySubscriptionAmountInUSD: number = 0;
|
||||
const order: number = 1;
|
||||
const trialPeriodInDays: number = 30;
|
||||
const env: JSONObject = {
|
||||
SUBSCRIPTION_PLAN_1: 'Free,monthly_plan_id,yearly_plan_id,0,0,1,7',
|
||||
SUBSCRIPTION_PLAN_2:
|
||||
'Growth,growth_monthly_plan_id,growth_yearly_plan_id,9,99,2,14',
|
||||
};
|
||||
|
||||
describe('constructor', () => {
|
||||
it('should create a new SubscriptionPlan object', () => {
|
||||
const plan: SubscriptionPlan = new SubscriptionPlan(
|
||||
monthlyPlanId,
|
||||
yearlyPlanId,
|
||||
name,
|
||||
monthlySubscriptionAmountInUSD,
|
||||
yearlySubscriptionAmountInUSD,
|
||||
order,
|
||||
trialPeriodInDays
|
||||
);
|
||||
expect(plan.getMonthlyPlanId()).toEqual(monthlyPlanId);
|
||||
expect(plan.getYearlyPlanId()).toEqual(yearlyPlanId);
|
||||
expect(plan.getName()).toEqual(name);
|
||||
expect(plan.getPlanOrder()).toEqual(order);
|
||||
expect(plan.getTrialPeriod()).toEqual(trialPeriodInDays);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getMonthlyPlanId', () => {
|
||||
it('should return the monthly plan ID', () => {
|
||||
const getMonthlyPlanId: string = 'monthly_plan_id';
|
||||
expect(getMonthlyPlanId).toEqual(monthlyPlanId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getYearlyPlanId', () => {
|
||||
it('should return the yearly plan ID', () => {
|
||||
const getYearlyPlanId: string = 'yearly_plan_id';
|
||||
expect(getYearlyPlanId).toEqual(yearlyPlanId);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getPlanOrder', () => {
|
||||
it('should return the plan order', () => {
|
||||
const getPlanOrder: number = 1;
|
||||
expect(getPlanOrder).toEqual(order);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getTrialPeriod', () => {
|
||||
it('should return the trial period in days', () => {
|
||||
const getTrialPeriod: number = 30;
|
||||
expect(getTrialPeriod).toEqual(trialPeriodInDays);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getName', () => {
|
||||
it('should return the plan name', () => {
|
||||
const getName: string = 'Test Plan';
|
||||
expect(getName).toEqual(name);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isFreePlan', () => {
|
||||
it('should return true if plan is free with monthlyId', () => {
|
||||
const isFreePlan: boolean = SubscriptionPlan.isFreePlan(
|
||||
'monthly_plan_id',
|
||||
env
|
||||
);
|
||||
expect(isFreePlan).toBe(true);
|
||||
});
|
||||
it('should return true if plan is free with yearlyId', () => {
|
||||
const isFreePlan: boolean = SubscriptionPlan.isFreePlan(
|
||||
'yearly_plan_id',
|
||||
env
|
||||
);
|
||||
expect(isFreePlan).toBe(true);
|
||||
});
|
||||
});
|
||||
describe('isCustomPricingPlan', () => {
|
||||
it('should return false if plan is not custom pricing', () => {
|
||||
const isCustomPricingPlan: boolean =
|
||||
SubscriptionPlan.isCustomPricingPlan(monthlyPlanId, env);
|
||||
expect(isCustomPricingPlan).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getSubscriptionPlans', () => {
|
||||
it('should return an array of SubscriptionPlan objects', () => {
|
||||
const subscriptionPlans: SubscriptionPlan[] =
|
||||
SubscriptionPlan.getSubscriptionPlans(env);
|
||||
|
||||
expect(subscriptionPlans.length).toBe(2);
|
||||
expect(subscriptionPlans?.[0]?.getName()).toBe('Free');
|
||||
expect(subscriptionPlans?.[0]?.getYearlyPlanId()).toBe(
|
||||
'yearly_plan_id'
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('isValidPlanId', () => {
|
||||
it('should return true if plan ID is valid', () => {
|
||||
const isValidPlanId: boolean = SubscriptionPlan.isValidPlanId(
|
||||
'growth_monthly_plan_id',
|
||||
env
|
||||
);
|
||||
expect(isValidPlanId).toBe(true);
|
||||
});
|
||||
});
|
||||
describe('getPlanSelect', () => {
|
||||
it('should return the plan name if valid planId is passed', () => {
|
||||
new SubscriptionPlan(
|
||||
monthlyPlanId,
|
||||
'yearly_plan_id',
|
||||
PlanSelect.Free,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
30
|
||||
);
|
||||
const result: PlanSelect = SubscriptionPlan.getPlanSelect(
|
||||
monthlyPlanId,
|
||||
env
|
||||
);
|
||||
expect(result).toBe(PlanSelect.Free);
|
||||
});
|
||||
it('should throw an error if invalid PlanId is passed', () => {
|
||||
SubscriptionPlan.getSubscriptionPlanById = jest
|
||||
.fn()
|
||||
.mockReturnValue(undefined);
|
||||
expect(() => {
|
||||
SubscriptionPlan.getPlanSelect('invalid-plan-id', env);
|
||||
}).toThrow(BadDataException);
|
||||
});
|
||||
});
|
||||
describe('getYearlySubscriptionAmountInUSD', () => {
|
||||
it('should return the yearly subscription amount', () => {
|
||||
const getYearlySubscriptionAmountInUSD: number = 0;
|
||||
expect(getYearlySubscriptionAmountInUSD).toEqual(
|
||||
yearlySubscriptionAmountInUSD
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('getMonthlySubscriptionAmountInUSD', () => {
|
||||
it('should return the yearly subscription amount', () => {
|
||||
const getMonthlySubscriptionAmountInUSD: number = 0;
|
||||
expect(getMonthlySubscriptionAmountInUSD).toEqual(
|
||||
monthlySubscriptionAmountInUSD
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('isFeatureAccessibleOnCurrentPlan', () => {
|
||||
it('should return false if the feature is not accessible on current plan', () => {
|
||||
const env: JSONObject = {
|
||||
SUBSCRIPTION_PLAN_1:
|
||||
'Free,monthly_plan_id,yearly_plan_id,0,0,1,7',
|
||||
SUBSCRIPTION_PLAN_2:
|
||||
'Growth,growth_monthly_plan_id,growth_yearly_plan_id,9,99,2,14',
|
||||
};
|
||||
const featureSubscriptionPlan: SubscriptionPlan =
|
||||
new SubscriptionPlan(
|
||||
'growth_monthly_plan_id',
|
||||
'growth_yearly_plan_id',
|
||||
PlanSelect.Growth,
|
||||
9,
|
||||
99,
|
||||
2,
|
||||
14
|
||||
);
|
||||
const currentSubscriptionPlan: SubscriptionPlan =
|
||||
new SubscriptionPlan(
|
||||
'monthly_plan_id',
|
||||
'yearly_plan_id',
|
||||
PlanSelect.Free,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
7
|
||||
);
|
||||
const result: boolean =
|
||||
SubscriptionPlan.isFeatureAccessibleOnCurrentPlan(
|
||||
PlanSelect.Growth,
|
||||
PlanSelect.Free,
|
||||
env
|
||||
);
|
||||
expect(featureSubscriptionPlan.getPlanOrder()).toBeGreaterThan(
|
||||
currentSubscriptionPlan.getPlanOrder()
|
||||
);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
it('should return true if the feature is on the current plan', () => {
|
||||
const env: JSONObject = {
|
||||
SUBSCRIPTION_PLAN_1:
|
||||
'Free,monthly_plan_id,yearly_plan_id,0,0,3,7',
|
||||
SUBSCRIPTION_PLAN_2:
|
||||
'Growth,growth_monthly_plan_id,growth_yearly_plan_id,9,99,2,14',
|
||||
};
|
||||
const featureSubscriptionPlan: SubscriptionPlan =
|
||||
new SubscriptionPlan(
|
||||
'growth_monthly_plan_id',
|
||||
'growth_yearly_plan_id',
|
||||
PlanSelect.Growth,
|
||||
9,
|
||||
99,
|
||||
2,
|
||||
14
|
||||
);
|
||||
const currentSubscriptionPlan: SubscriptionPlan =
|
||||
new SubscriptionPlan(
|
||||
monthlyPlanId,
|
||||
'yearly_plan_id',
|
||||
PlanSelect.Free,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
7
|
||||
);
|
||||
const result: boolean =
|
||||
SubscriptionPlan.isFeatureAccessibleOnCurrentPlan(
|
||||
PlanSelect.Growth,
|
||||
PlanSelect.Free,
|
||||
env
|
||||
);
|
||||
expect(featureSubscriptionPlan.getPlanOrder()).toBeLessThan(
|
||||
currentSubscriptionPlan.getPlanOrder()
|
||||
);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
});
|
||||
describe('getSubscriptionPlanFromPlanSelect', () => {
|
||||
it('should return the correct SubscriptionPlan when a valid planSelect is provided', () => {
|
||||
const plan: SubscriptionPlan =
|
||||
SubscriptionPlan.getSubscriptionPlanFromPlanSelect(
|
||||
PlanSelect.Growth,
|
||||
env
|
||||
);
|
||||
expect(plan).toEqual(plan);
|
||||
expect(plan.getName()).toEqual(PlanSelect.Growth);
|
||||
});
|
||||
it('should throw a BadDataException when an invalid planSelect is provided', () => {
|
||||
const planSelect: PlanSelect = PlanSelect.Scale;
|
||||
SubscriptionPlan.getSubscriptionPlans = jest
|
||||
.fn()
|
||||
.mockReturnValue([]);
|
||||
expect(() => {
|
||||
SubscriptionPlan.getSubscriptionPlanFromPlanSelect(
|
||||
planSelect,
|
||||
env
|
||||
);
|
||||
}).toThrow(BadDataException);
|
||||
});
|
||||
});
|
||||
describe('isYearlyPlan', () => {
|
||||
it('should return true if yearly plan exists', () => {
|
||||
const planId: string = 'growth_yearly_plan_id';
|
||||
const plan: SubscriptionPlan = new SubscriptionPlan(
|
||||
'monthly-plan-id',
|
||||
planId,
|
||||
'Growth',
|
||||
10,
|
||||
100,
|
||||
2,
|
||||
7
|
||||
);
|
||||
SubscriptionPlan.getSubscriptionPlanById(planId, env);
|
||||
expect(plan?.getYearlyPlanId()).toBe(planId);
|
||||
});
|
||||
});
|
||||
describe('isUnpaid', () => {
|
||||
it('should return true if the subscription status is unpaid', () => {
|
||||
const subscriptionStatus: string =
|
||||
'incomplete' ||
|
||||
'ncomplete_expired' ||
|
||||
'past_due' ||
|
||||
'canceled' ||
|
||||
'unpaid';
|
||||
const result: boolean =
|
||||
SubscriptionPlan.isUnpaid(subscriptionStatus);
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
it('should return false if the subscription status is active', () => {
|
||||
const subscriptionStatus: string = 'active';
|
||||
const result: boolean =
|
||||
SubscriptionPlan.isUnpaid(subscriptionStatus);
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ enum HTTPMethod {
|
||||
POST = 'POST',
|
||||
DELETE = 'DELETE',
|
||||
PUT = 'PUT',
|
||||
HEAD = 'HEAD',
|
||||
}
|
||||
|
||||
export default HTTPMethod;
|
||||
|
||||
@@ -23,7 +23,9 @@ export default class Hostname extends DatabaseProperty {
|
||||
if (Hostname.isValid(value)) {
|
||||
this._route = value;
|
||||
} else {
|
||||
throw new BadDataException('Hostname is not in valid format.');
|
||||
throw new BadDataException(
|
||||
'Hostname ' + value + ' is not in valid format.'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export default class Route extends DatabaseProperty {
|
||||
}
|
||||
public set route(v: string) {
|
||||
const matchRouteCharacters: RegExp =
|
||||
/^[a-zA-Z_\d\-!#$&'()*+,./:;=?@[\]]*$/;
|
||||
/^[a-zA-Z_\d\-!#$%&'()*+,./:;=?@[\]]*$/;
|
||||
if (v && !matchRouteCharacters.test(v)) {
|
||||
throw new BadDataException(`Invalid route: ${v}`);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ export default class StatusCode {
|
||||
return this.statusCode.toNumber();
|
||||
}
|
||||
|
||||
public static isValidStausCode(statusCode: number | string): boolean {
|
||||
public static isValidStatusCode(statusCode: number | string): boolean {
|
||||
try {
|
||||
if (typeof statusCode === Typeof.String) {
|
||||
statusCode = parseInt(statusCode as string);
|
||||
|
||||
@@ -99,7 +99,7 @@ export default class URL extends DatabaseProperty {
|
||||
let urlString: string = `${this.protocol}${
|
||||
this.hostname || this.email
|
||||
}`;
|
||||
if (!this.email) {
|
||||
if (!this.email && !urlString.startsWith('mailto:')) {
|
||||
if (this.route && this.route.toString().startsWith('/')) {
|
||||
if (urlString.endsWith('/')) {
|
||||
urlString = urlString.substring(0, urlString.length - 1);
|
||||
|
||||
@@ -26,4 +26,29 @@ export default class ArrayUtil {
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
public static distinctByFieldName(
|
||||
array: Array<any>,
|
||||
fieldName: string
|
||||
): Array<any> {
|
||||
// Get the distinct values by field name of the array
|
||||
const distinctValues: Array<any> = array
|
||||
.map((item: any) => {
|
||||
return item[fieldName];
|
||||
})
|
||||
.filter((value: any, index: number, self: Array<any>) => {
|
||||
return self.indexOf(value) === index;
|
||||
});
|
||||
|
||||
// Create a new array with the distinct values
|
||||
const distinctArray: Array<any> = [];
|
||||
for (const value of distinctValues) {
|
||||
const item: any = array.find((item: any) => {
|
||||
return item[fieldName] === value;
|
||||
});
|
||||
distinctArray.push(item);
|
||||
}
|
||||
|
||||
return distinctArray;
|
||||
}
|
||||
}
|
||||
|
||||
30
Common/Types/Call/CallRequest.ts
Normal file
30
Common/Types/Call/CallRequest.ts
Normal 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;
|
||||
}
|
||||
9
Common/Types/Call/CallStatus.ts
Normal file
9
Common/Types/Call/CallStatus.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
enum CallStatus {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
LowBalance = 'Low Balance',
|
||||
MissedCall = 'Missed Call',
|
||||
Busy = 'Busy',
|
||||
}
|
||||
|
||||
export default CallStatus;
|
||||
@@ -17,3 +17,9 @@ export interface BillingAccessControl {
|
||||
update: PlanSelect;
|
||||
delete: PlanSelect;
|
||||
}
|
||||
|
||||
export interface ColumnBillingAccessControl {
|
||||
create: PlanSelect;
|
||||
read: PlanSelect;
|
||||
update: PlanSelect;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -17,8 +17,9 @@ export interface TableColumnMetadata {
|
||||
encrypted?: boolean;
|
||||
manyToOneRelationColumn?: string;
|
||||
type: TableColumnType;
|
||||
canReadOnPopulate?: boolean;
|
||||
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 => {
|
||||
|
||||
@@ -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,82 @@ 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
|
||||
): Array<string> {
|
||||
date = this.fromString(date);
|
||||
|
||||
let formatstring: string = 'MMM DD YYYY, HH:mm';
|
||||
|
||||
if (onlyShowDate) {
|
||||
formatstring = 'MMM DD, YYYY';
|
||||
}
|
||||
|
||||
// convert this date into GMT, EST, PST, IST, ACT with moment
|
||||
const timezoneDates: Array<string> = [];
|
||||
|
||||
timezoneDates.push(
|
||||
moment(date).tz('UTC').format(formatstring) +
|
||||
' ' +
|
||||
(onlyShowDate ? '' : 'GMT')
|
||||
);
|
||||
timezoneDates.push(
|
||||
moment(date).tz('America/New_York').format(formatstring) +
|
||||
' ' +
|
||||
(onlyShowDate ? '' : 'EST')
|
||||
);
|
||||
timezoneDates.push(
|
||||
moment(date).tz('America/Los_Angeles').format(formatstring) +
|
||||
' ' +
|
||||
(onlyShowDate ? '' : 'PST')
|
||||
);
|
||||
timezoneDates.push(
|
||||
moment(date).tz('Asia/Kolkata').format(formatstring) +
|
||||
' ' +
|
||||
(onlyShowDate ? '' : 'IST')
|
||||
);
|
||||
timezoneDates.push(
|
||||
moment(date).tz('Australia/Sydney').format(formatstring) +
|
||||
' ' +
|
||||
(onlyShowDate ? '' : 'AEST')
|
||||
);
|
||||
|
||||
return timezoneDates;
|
||||
}
|
||||
|
||||
public static getDateAsFormattedHTMLInMultipleTimezones(
|
||||
date: string | Date,
|
||||
onlyShowDate?: boolean
|
||||
): string {
|
||||
return this.getDateAsFormattedArrayInMultipleTimezones(
|
||||
date,
|
||||
onlyShowDate
|
||||
).join('<br/>');
|
||||
}
|
||||
|
||||
public static getDateAsFormattedStringInMultipleTimezones(
|
||||
date: string | Date,
|
||||
onlyShowDate?: boolean
|
||||
): string {
|
||||
return this.getDateAsFormattedArrayInMultipleTimezones(
|
||||
date,
|
||||
onlyShowDate
|
||||
).join('\n');
|
||||
}
|
||||
|
||||
public static getDateAsLocalFormattedString(
|
||||
date: string | Date,
|
||||
onlyShowDate?: boolean
|
||||
@@ -385,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();
|
||||
}
|
||||
@@ -431,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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
'|'
|
||||
);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -17,6 +17,23 @@ enum EmailTemplateType {
|
||||
StatusPageWelcomeEmail = 'StatusPageWelcomeEmail.hbs',
|
||||
SubscriberScheduledMaintenanceEventNoteCreated = 'SubscriberScheduledMaintenanceEventNoteCreated.hbs',
|
||||
SMTPTest = 'SMTPTest.hbs',
|
||||
MonitorOwnerAdded = 'MonitorOwnerAdded.hbs',
|
||||
MonitorOwnerResourceCreated = 'MonitorOwnerResourceCreated.hbs',
|
||||
MonitorOwnerStatusChanged = 'MonitorOwnerStatusChanged.hbs',
|
||||
IncidentOwnerAdded = 'IncidentOwnerAdded.hbs',
|
||||
IncidentOwnerStateChanged = 'IncidentOwnerStateChanged.hbs',
|
||||
IncidentOwnerNotePosted = 'IncidentOwnerNotePosted.hbs',
|
||||
IncidentOwnerResourceCreated = 'IncidentOwnerResourceCreated.hbs',
|
||||
ScheduledMaintenanceOwnerNotePosted = 'ScheduledMaintenanceOwnerNotePosted.hbs',
|
||||
ScheduledMaintenanceOwnerAdded = 'ScheduledMaintenanceOwnerAdded.hbs',
|
||||
ScheduledMaintenanceOwnerStateChanged = 'ScheduledMaintenanceOwnerStateChanged.hbs',
|
||||
ScheduledMaintenanceOwnerResourceCreated = 'ScheduledMaintenanceOwnerResourceCreated.hbs',
|
||||
StatusPageOwnerResourceCreated = 'StatusPageOwnerResourceCreated.hbs',
|
||||
StatusPageOwnerAdded = 'StatusPageOwnerAdded.hbs',
|
||||
StatusPageOwnerAnnouncementPosted = 'StatusPageOwnerAnnouncementPosted.hbs',
|
||||
SimpleMessage = 'SimpleMessage.hbs',
|
||||
VerificationCode = 'VerificationCode.hbs',
|
||||
AcknowledgeIncident = 'AcknowledgeIncident.hbs',
|
||||
}
|
||||
|
||||
export default EmailTemplateType;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { FindOperator } from 'typeorm';
|
||||
import DatabaseProperty from '../Database/DatabaseProperty';
|
||||
import BadDataException from '../Exception/BadDataException';
|
||||
import { JSONObject } from '../JSON';
|
||||
import { JSONObject, ObjectType } from '../JSON';
|
||||
import Typeof from '../Typeof';
|
||||
import IPType from './IPType';
|
||||
|
||||
@@ -73,11 +73,11 @@ export default class IP extends DatabaseProperty {
|
||||
}
|
||||
|
||||
public static override fromJSON(json: JSONObject): IP {
|
||||
if (json && json['_type'] !== 'IP') {
|
||||
if (json && json['_type'] !== ObjectType.IP) {
|
||||
throw new BadDataException('Invalid JSON for IP');
|
||||
}
|
||||
|
||||
if (json && json['value'] && typeof json['value'] === Typeof.String) {
|
||||
if (json && json['value'] && typeof json['value'] !== Typeof.String) {
|
||||
throw new BadDataException('Invalid JSON for IP');
|
||||
}
|
||||
|
||||
@@ -87,7 +87,7 @@ export default class IP extends DatabaseProperty {
|
||||
public override toJSON(): JSONObject {
|
||||
return {
|
||||
value: this.toString(),
|
||||
_type: 'IP',
|
||||
_type: ObjectType.IP,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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',
|
||||
@@ -37,6 +38,7 @@ export enum ObjectType {
|
||||
Color = 'Color',
|
||||
Domain = 'Domain',
|
||||
Version = 'Version',
|
||||
IP = 'IP',
|
||||
Route = 'Route',
|
||||
URL = 'URL',
|
||||
Permission = 'Permission',
|
||||
@@ -121,6 +123,7 @@ export type JSONValue =
|
||||
| Array<JSONValue>
|
||||
| Array<Permission>
|
||||
| Array<JSONValue>
|
||||
| CallRequest
|
||||
| undefined
|
||||
| null;
|
||||
|
||||
|
||||
@@ -159,9 +159,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;
|
||||
}
|
||||
|
||||
|
||||
6
Common/Types/Mail/MailStatus.ts
Normal file
6
Common/Types/Mail/MailStatus.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
enum MailStatus {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export default MailStatus;
|
||||
@@ -1,6 +1,6 @@
|
||||
export enum CheckOn {
|
||||
ResponseTime = 'Response Time (in ms)',
|
||||
ResponseStatusCode = 'Response Staus Code',
|
||||
ResponseStatusCode = 'Response Status Code',
|
||||
ResponseHeader = 'Response Header',
|
||||
ResponseHeaderValue = 'Response Header Value',
|
||||
ResponseBody = 'Response Body',
|
||||
|
||||
@@ -4,4 +4,7 @@ export interface CriteriaIncident {
|
||||
title: string;
|
||||
description: string;
|
||||
incidentSeverityId?: ObjectID | undefined;
|
||||
autoResolveIncident?: boolean | undefined;
|
||||
id: string;
|
||||
onCallPolicyIds?: Array<ObjectID> | undefined;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -10,10 +10,11 @@ import Dictionary from '../Dictionary';
|
||||
import ObjectID from '../ObjectID';
|
||||
import MonitorType from './MonitorType';
|
||||
import JSONFunctions from '../JSONFunctions';
|
||||
import Hostname from '../API/Hostname';
|
||||
|
||||
export interface MonitorStepType {
|
||||
id: string;
|
||||
monitorDestination?: URL | IP | undefined;
|
||||
monitorDestination?: URL | IP | Hostname | undefined;
|
||||
monitorCriteria: MonitorCriteria;
|
||||
requestType: HTTPMethod;
|
||||
requestHeaders?: Dictionary<string> | undefined;
|
||||
@@ -83,7 +84,9 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
return this;
|
||||
}
|
||||
|
||||
public setMonitorDestination(monitorDestination: URL | IP): MonitorStep {
|
||||
public setMonitorDestination(
|
||||
monitorDestination: URL | IP | Hostname
|
||||
): MonitorStep {
|
||||
this.data!.monitorDestination = monitorDestination;
|
||||
return this;
|
||||
}
|
||||
@@ -176,12 +179,13 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
|
||||
json = json['value'] as JSONObject;
|
||||
|
||||
let monitorDestination: URL | IP | undefined = undefined;
|
||||
let monitorDestination: URL | IP | Hostname | undefined = undefined;
|
||||
|
||||
if (
|
||||
json &&
|
||||
json['monitorDestination'] &&
|
||||
(json['monitorDestination'] as JSONObject)['_type'] === 'URL'
|
||||
(json['monitorDestination'] as JSONObject)['_type'] ===
|
||||
ObjectType.URL
|
||||
) {
|
||||
monitorDestination = URL.fromJSON(
|
||||
json['monitorDestination'] as JSONObject
|
||||
@@ -191,7 +195,19 @@ export default class MonitorStep extends DatabaseProperty {
|
||||
if (
|
||||
json &&
|
||||
json['monitorDestination'] &&
|
||||
(json['monitorDestination'] as JSONObject)['_type'] === 'IP'
|
||||
(json['monitorDestination'] as JSONObject)['_type'] ===
|
||||
ObjectType.Hostname
|
||||
) {
|
||||
monitorDestination = Hostname.fromJSON(
|
||||
json['monitorDestination'] as JSONObject
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
json &&
|
||||
json['monitorDestination'] &&
|
||||
(json['monitorDestination'] as JSONObject)['_type'] ===
|
||||
ObjectType.IP
|
||||
) {
|
||||
monitorDestination = IP.fromJSON(
|
||||
json['monitorDestination'] as JSONObject
|
||||
|
||||
7
Common/Types/NotificationRule/NotificationRuleType.ts
Normal file
7
Common/Types/NotificationRule/NotificationRuleType.ts
Normal 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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
enum OnCallDutyExecutionLogTimelineStatus {
|
||||
Skipped = 'Skipped',
|
||||
Started = 'Started',
|
||||
Executing = 'Executing',
|
||||
SuccessfullyAcknowledged = 'Successfully Acknowledged',
|
||||
NotificationSent = 'Notification Sent',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export default OnCallDutyExecutionLogTimelineStatus;
|
||||
@@ -0,0 +1,7 @@
|
||||
enum OnCallDutyPolicyStatus {
|
||||
SuccessfullyAcknowledged = 'Successfully Acknowledged',
|
||||
FailedToAcknowledge = 'Failed to Acknowledge',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export default OnCallDutyPolicyStatus;
|
||||
9
Common/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts
Normal file
9
Common/Types/OnCallDutyPolicy/OnCallDutyPolicyStatus.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
enum OnCallDutyPolicyStatus {
|
||||
Scheduled = 'Scheduled',
|
||||
Started = 'Started',
|
||||
Executing = 'Executing',
|
||||
Completed = 'Execution Completed',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export default OnCallDutyPolicyStatus;
|
||||
@@ -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,6 +78,50 @@ enum Permission {
|
||||
CanEditMonitorProbe = 'CanEditMonitorProbe',
|
||||
CanReadMonitorProbe = 'CanReadMonitorProbe',
|
||||
|
||||
CanReadSmsLog = 'CanReadSmsLog',
|
||||
CanReadEmailLog = 'CanReadEmailLog',
|
||||
CanReadCallLog = 'CanReadCallLog',
|
||||
|
||||
CanCreateIncidentOwnerTeam = 'CanCreateIncidentOwnerTeam',
|
||||
CanDeleteIncidentOwnerTeam = 'CanDeleteIncidentOwnerTeam',
|
||||
CanEditIncidentOwnerTeam = 'CanEditIncidentOwnerTeam',
|
||||
CanReadIncidentOwnerTeam = 'CanReadIncidentOwnerTeam',
|
||||
|
||||
CanCreateIncidentOwnerUser = 'CanCreateIncidentOwner',
|
||||
CanDeleteIncidentOwnerUser = 'CanDeleteIncidentOwnerUser',
|
||||
CanEditIncidentOwnerUser = 'CanEditIncidentOwnerUser',
|
||||
CanReadIncidentOwnerUser = 'CanReadIncidentOwnerUser',
|
||||
|
||||
CanCreateScheduledMaintenanceOwnerTeam = 'CanCreateScheduledMaintenanceOwnerTeam',
|
||||
CanDeleteScheduledMaintenanceOwnerTeam = 'CanDeleteScheduledMaintenanceOwnerTeam',
|
||||
CanEditScheduledMaintenanceOwnerTeam = 'CanEditScheduledMaintenanceOwnerTeam',
|
||||
CanReadScheduledMaintenanceOwnerTeam = 'CanReadScheduledMaintenanceOwnerTeam',
|
||||
|
||||
CanCreateScheduledMaintenanceOwnerUser = 'CanCreateScheduledMaintenanceOwner',
|
||||
CanDeleteScheduledMaintenanceOwnerUser = 'CanDeleteScheduledMaintenanceOwnerUser',
|
||||
CanEditScheduledMaintenanceOwnerUser = 'CanEditScheduledMaintenanceOwnerUser',
|
||||
CanReadScheduledMaintenanceOwnerUser = 'CanReadScheduledMaintenanceOwnerUser',
|
||||
|
||||
CanCreateStatusPageOwnerTeam = 'CanCreateStatusPageOwnerTeam',
|
||||
CanDeleteStatusPageOwnerTeam = 'CanDeleteStatusPageOwnerTeam',
|
||||
CanEditStatusPageOwnerTeam = 'CanEditStatusPageOwnerTeam',
|
||||
CanReadStatusPageOwnerTeam = 'CanReadStatusPageOwnerTeam',
|
||||
|
||||
CanCreateStatusPageOwnerUser = 'CanCreateStatusPageOwner',
|
||||
CanDeleteStatusPageOwnerUser = 'CanDeleteStatusPageOwnerUser',
|
||||
CanEditStatusPageOwnerUser = 'CanEditStatusPageOwnerUser',
|
||||
CanReadStatusPageOwnerUser = 'CanReadStatusPageOwnerUser',
|
||||
|
||||
CanCreateMonitorOwnerTeam = 'CanCreateMonitorOwnerTeam',
|
||||
CanDeleteMonitorOwnerTeam = 'CanDeleteMonitorOwnerTeam',
|
||||
CanEditMonitorOwnerTeam = 'CanEditMonitorOwnerTeam',
|
||||
CanReadMonitorOwnerTeam = 'CanReadMonitorOwnerTeam',
|
||||
|
||||
CanCreateMonitorOwnerUser = 'CanCreateMonitorOwner',
|
||||
CanDeleteMonitorOwnerUser = 'CanDeleteMonitorOwnerUser',
|
||||
CanEditMonitorOwnerUser = 'CanEditMonitorOwnerUser',
|
||||
CanReadMonitorOwnerUser = 'CanReadMonitorOwnerUser',
|
||||
|
||||
CanCreateStatusPageCustomField = 'CanCreateStatusPageCustomField',
|
||||
CanDeleteStatusPageCustomField = 'CanDeleteStatusPageCustomField',
|
||||
CanEditStatusPageCustomField = 'CanEditStatusPageCustomField',
|
||||
@@ -206,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',
|
||||
@@ -251,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',
|
||||
@@ -404,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,
|
||||
},
|
||||
@@ -420,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,
|
||||
},
|
||||
@@ -609,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',
|
||||
@@ -1401,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,
|
||||
@@ -1496,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',
|
||||
@@ -1628,6 +1908,24 @@ export class PermissionHelper {
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanReadSmsLog,
|
||||
title: 'Can Read SMS Log',
|
||||
description:
|
||||
'This permission can read SMS Log of this project.',
|
||||
isAssignableToTenant: true,
|
||||
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',
|
||||
@@ -1661,6 +1959,270 @@ export class PermissionHelper {
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateScheduledMaintenanceOwnerTeam,
|
||||
title: 'Can Create Scheduled Maintenance Team Owner',
|
||||
description:
|
||||
'This permission can create Scheduled Maintenance Team Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteScheduledMaintenanceOwnerTeam,
|
||||
title: 'Can Delete Scheduled Maintenance Team Owner',
|
||||
description:
|
||||
'This permission can delete Scheduled Maintenance Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditScheduledMaintenanceOwnerTeam,
|
||||
title: 'Can Edit Scheduled Maintenance Team Owner',
|
||||
description:
|
||||
'This permission can edit Scheduled Maintenance Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadScheduledMaintenanceOwnerTeam,
|
||||
title: 'Can Read Scheduled Maintenance Team Owner',
|
||||
description:
|
||||
'This permission can read Scheduled Maintenance Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateScheduledMaintenanceOwnerUser,
|
||||
title: 'Can Create Scheduled Maintenance User Owner',
|
||||
description:
|
||||
'This permission can create Scheduled Maintenance User Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteScheduledMaintenanceOwnerUser,
|
||||
title: 'Can Delete Scheduled Maintenance User Owner',
|
||||
description:
|
||||
'This permission can delete Scheduled Maintenance User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditScheduledMaintenanceOwnerUser,
|
||||
title: 'Can Edit Scheduled Maintenance User Owner',
|
||||
description:
|
||||
'This permission can edit Scheduled Maintenance User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadScheduledMaintenanceOwnerUser,
|
||||
title: 'Can Read Scheduled Maintenance User Owner',
|
||||
description:
|
||||
'This permission can read Scheduled Maintenance User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateIncidentOwnerTeam,
|
||||
title: 'Can Create Incident Team Owner',
|
||||
description:
|
||||
'This permission can create Incident Team Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteIncidentOwnerTeam,
|
||||
title: 'Can Delete Incident Team Owner',
|
||||
description:
|
||||
'This permission can delete Incident Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditIncidentOwnerTeam,
|
||||
title: 'Can Edit Incident Team Owner',
|
||||
description:
|
||||
'This permission can edit Incident Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadIncidentOwnerTeam,
|
||||
title: 'Can Read Incident Team Owner',
|
||||
description:
|
||||
'This permission can read Incident Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateIncidentOwnerUser,
|
||||
title: 'Can Create Incident User Owner',
|
||||
description:
|
||||
'This permission can create Incident User Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteIncidentOwnerUser,
|
||||
title: 'Can Delete Incident User Owner',
|
||||
description:
|
||||
'This permission can delete Incident User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditIncidentOwnerUser,
|
||||
title: 'Can Edit Incident User Owner',
|
||||
description:
|
||||
'This permission can edit Incident User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadIncidentOwnerUser,
|
||||
title: 'Can Read Incident User Owner',
|
||||
description:
|
||||
'This permission can read Incident User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateStatusPageOwnerTeam,
|
||||
title: 'Can Create Status Page Team Owner',
|
||||
description:
|
||||
'This permission can create Status Page Team Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteStatusPageOwnerTeam,
|
||||
title: 'Can Delete Status Page Team Owner',
|
||||
description:
|
||||
'This permission can delete Status Page Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditStatusPageOwnerTeam,
|
||||
title: 'Can Edit Status Page Team Owner',
|
||||
description:
|
||||
'This permission can edit Status Page Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadStatusPageOwnerTeam,
|
||||
title: 'Can Read Status Page Team Owner',
|
||||
description:
|
||||
'This permission can read Status Page Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateStatusPageOwnerUser,
|
||||
title: 'Can Create Status Page User Owner',
|
||||
description:
|
||||
'This permission can create Status Page User Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteStatusPageOwnerUser,
|
||||
title: 'Can Delete Status Page User Owner',
|
||||
description:
|
||||
'This permission can delete Status Page User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditStatusPageOwnerUser,
|
||||
title: 'Can Edit Status Page User Owner',
|
||||
description:
|
||||
'This permission can edit Status Page User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadStatusPageOwnerUser,
|
||||
title: 'Can Read Status Page User Owner',
|
||||
description:
|
||||
'This permission can read Status Page User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateMonitorOwnerTeam,
|
||||
title: 'Can Create Monitor Team Owner',
|
||||
description:
|
||||
'This permission can create Monitor Team Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteMonitorOwnerTeam,
|
||||
title: 'Can Delete Monitor Team Owner',
|
||||
description:
|
||||
'This permission can delete Monitor Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditMonitorOwnerTeam,
|
||||
title: 'Can Edit Monitor Team Owner',
|
||||
description:
|
||||
'This permission can edit Monitor Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadMonitorOwnerTeam,
|
||||
title: 'Can Read Monitor Team Owner',
|
||||
description:
|
||||
'This permission can read Monitor Team Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateMonitorOwnerUser,
|
||||
title: 'Can Create Monitor User Owner',
|
||||
description:
|
||||
'This permission can create Monitor User Owner this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanDeleteMonitorOwnerUser,
|
||||
title: 'Can Delete Monitor User Owner',
|
||||
description:
|
||||
'This permission can delete Monitor User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanEditMonitorOwnerUser,
|
||||
title: 'Can Edit Monitor User Owner',
|
||||
description:
|
||||
'This permission can edit Monitor User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
{
|
||||
permission: Permission.CanReadMonitorOwnerUser,
|
||||
title: 'Can Read Monitor User Owner',
|
||||
description:
|
||||
'This permission can read Monitor User Owner of this project.',
|
||||
isAssignableToTenant: true,
|
||||
isAccessControlPermission: false,
|
||||
},
|
||||
|
||||
{
|
||||
permission: Permission.CanCreateProjectIncident,
|
||||
title: 'Can Create Incident',
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
@@ -5,4 +5,5 @@ export default interface ProbeApiIngestResponse {
|
||||
ingestedMonitorStepId?: ObjectID | undefined;
|
||||
nextMonitorStepId?: ObjectID | undefined;
|
||||
criteriaMetId?: string | undefined;
|
||||
rootCause: string | null;
|
||||
}
|
||||
|
||||
@@ -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
9
Common/Types/SMS/SMS.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import Phone from '../Phone';
|
||||
|
||||
export interface SMSMessage {
|
||||
message: string;
|
||||
}
|
||||
|
||||
export default interface SMS extends SMSMessage {
|
||||
to: Phone;
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
7
Common/Types/SmsStatus.ts
Normal file
7
Common/Types/SmsStatus.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
enum SmsStatus {
|
||||
Success = 'Success',
|
||||
Error = 'Error',
|
||||
LowBalance = 'Low Balance',
|
||||
}
|
||||
|
||||
export default SmsStatus;
|
||||
@@ -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',
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
enum UserNotificationEventType {
|
||||
IncidentCreated = 'Incident Created',
|
||||
}
|
||||
|
||||
export default UserNotificationEventType;
|
||||
@@ -0,0 +1,9 @@
|
||||
enum UserNotificationExecutionStatus {
|
||||
Scheduled = 'Scheduled',
|
||||
Started = 'Strated',
|
||||
Executing = 'Executing',
|
||||
Completed = 'Completed',
|
||||
Error = 'Error',
|
||||
}
|
||||
|
||||
export default UserNotificationExecutionStatus;
|
||||
9
Common/Types/UserNotification/UserNotificationStatus.ts
Normal file
9
Common/Types/UserNotification/UserNotificationStatus.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
enum UserNotificationStatus {
|
||||
Sent = 'Sent',
|
||||
Acknowledged = 'Acknowledged',
|
||||
Error = 'Error',
|
||||
Sending = 'Sending',
|
||||
Skipped = 'Skipped',
|
||||
}
|
||||
|
||||
export default UserNotificationStatus;
|
||||
@@ -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 {
|
||||
|
||||
@@ -18,6 +18,7 @@ export enum ComponentInputType {
|
||||
Email = 'Email',
|
||||
CronTab = 'CronTab',
|
||||
Query = 'Database Query',
|
||||
Select = 'Database Select',
|
||||
BaseModel = 'Database Record',
|
||||
BaseModelArray = 'Database Records',
|
||||
JSONArray = 'List of JSON',
|
||||
|
||||
@@ -33,7 +33,7 @@ export default class BaseModelComponent {
|
||||
placeholder: 'Example: {"columnName": "value", ...}',
|
||||
},
|
||||
{
|
||||
type: ComponentInputType.Query,
|
||||
type: ComponentInputType.Select,
|
||||
name: 'Select Fields',
|
||||
description: `Select on ${model.singularName}`,
|
||||
required: true,
|
||||
@@ -92,7 +92,7 @@ export default class BaseModelComponent {
|
||||
placeholder: 'Example: {"columnName": "value", ...}',
|
||||
},
|
||||
{
|
||||
type: ComponentInputType.Query,
|
||||
type: ComponentInputType.Select,
|
||||
name: 'Select Fields',
|
||||
description: `Select on ${model.singularName}`,
|
||||
required: true,
|
||||
@@ -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,
|
||||
@@ -288,10 +288,19 @@ export default class BaseModelComponent {
|
||||
iconProp: IconProp.Bolt,
|
||||
tableName: model.tableName!,
|
||||
componentType: ComponentType.Trigger,
|
||||
arguments: [],
|
||||
arguments: [
|
||||
{
|
||||
type: ComponentInputType.Select,
|
||||
name: 'Select Fields',
|
||||
description: `Select on ${model.singularName}`,
|
||||
required: true,
|
||||
id: 'select',
|
||||
placeholder: 'Example: {"columnName": true, ...}',
|
||||
},
|
||||
],
|
||||
returnValues: [
|
||||
{
|
||||
id: 'data',
|
||||
id: 'model',
|
||||
name: `${model.singularName}`,
|
||||
description: `${model.singularName} created in the database`,
|
||||
type: ComponentInputType.BaseModel,
|
||||
@@ -422,10 +431,19 @@ export default class BaseModelComponent {
|
||||
iconProp: IconProp.Bolt,
|
||||
tableName: model.tableName!,
|
||||
componentType: ComponentType.Trigger,
|
||||
arguments: [],
|
||||
arguments: [
|
||||
{
|
||||
type: ComponentInputType.Select,
|
||||
name: 'Select Fields',
|
||||
description: `Select on ${model.singularName}`,
|
||||
required: true,
|
||||
id: 'select',
|
||||
placeholder: 'Example: {"columnName": true, ...}',
|
||||
},
|
||||
],
|
||||
returnValues: [
|
||||
{
|
||||
id: 'data',
|
||||
id: 'model',
|
||||
name: `${model.singularName}`,
|
||||
description: `Updated ${model.singularName}`,
|
||||
type: ComponentInputType.BaseModel,
|
||||
|
||||
@@ -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>
|
||||
>(
|
||||
|
||||
@@ -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';
|
||||
|
||||
51
Common/package-lock.json
generated
51
Common/package-lock.json
generated
@@ -919,14 +919,6 @@
|
||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/types": {
|
||||
"version": "7.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.22.0.tgz",
|
||||
"integrity": "sha512-LhCL+wb1Jch+OesB2CIt6xpfO1Ab6CRvoNYRRzVumWPLns1T3ZJkarYfhbLaOEIb38EIbPgREdxn2AJT560U4Q==",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@sinonjs/commons": {
|
||||
"version": "1.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
|
||||
@@ -3589,11 +3581,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/posthog-js": {
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.38.1.tgz",
|
||||
"integrity": "sha512-9YK+QPnilKkDOq3G2hMsHfzu3c30pOIQUzg239u1GHm4BuOBCYtyUwSW5D5zUeEyXz6w3BcA+GkeTw0k+Nttog==",
|
||||
"version": "1.57.2",
|
||||
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.57.2.tgz",
|
||||
"integrity": "sha512-ER4gkYZasrd2Zwmt/yLeZ5G/nZJ6tpaYBCpx3CvocDx+3F16WdawJlYMT0IyLKHXDniC5+AsjzFd6fi8uyYlJA==",
|
||||
"dependencies": {
|
||||
"@sentry/types": "7.22.0",
|
||||
"fflate": "^0.4.1",
|
||||
"rrweb-snapshot": "^1.1.14"
|
||||
}
|
||||
@@ -4104,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",
|
||||
@@ -4597,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"
|
||||
@@ -5391,11 +5382,6 @@
|
||||
"@jridgewell/sourcemap-codec": "1.4.14"
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "7.22.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.22.0.tgz",
|
||||
"integrity": "sha512-LhCL+wb1Jch+OesB2CIt6xpfO1Ab6CRvoNYRRzVumWPLns1T3ZJkarYfhbLaOEIb38EIbPgREdxn2AJT560U4Q=="
|
||||
},
|
||||
"@sinonjs/commons": {
|
||||
"version": "1.8.6",
|
||||
"resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.6.tgz",
|
||||
@@ -7409,11 +7395,10 @@
|
||||
}
|
||||
},
|
||||
"posthog-js": {
|
||||
"version": "1.38.1",
|
||||
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.38.1.tgz",
|
||||
"integrity": "sha512-9YK+QPnilKkDOq3G2hMsHfzu3c30pOIQUzg239u1GHm4BuOBCYtyUwSW5D5zUeEyXz6w3BcA+GkeTw0k+Nttog==",
|
||||
"version": "1.57.2",
|
||||
"resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.57.2.tgz",
|
||||
"integrity": "sha512-ER4gkYZasrd2Zwmt/yLeZ5G/nZJ6tpaYBCpx3CvocDx+3F16WdawJlYMT0IyLKHXDniC5+AsjzFd6fi8uyYlJA==",
|
||||
"requires": {
|
||||
"@sentry/types": "7.22.0",
|
||||
"fflate": "^0.4.1",
|
||||
"rrweb-snapshot": "^1.1.14"
|
||||
}
|
||||
@@ -7789,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",
|
||||
@@ -8082,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": {
|
||||
|
||||
@@ -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 }}
|
||||
MAIL_HOSTNAME={{ .Env.MAIL_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 }}
|
||||
MAIL_ROUTE={{ .Env.MAIL_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 }}
|
||||
@@ -20,7 +20,6 @@ import Query from '../Types/Database/Query';
|
||||
import Select from '../Types/Database/Select';
|
||||
import Sort from '../Types/Database/Sort';
|
||||
import { LIMIT_PER_PROJECT } from 'Common/Types/Database/LimitMax';
|
||||
import Populate from '../Types/Database/Populate';
|
||||
import PartialEntity from 'Common/Types/Database/PartialEntity';
|
||||
import { UserPermission } from 'Common/Types/Permission';
|
||||
import { IsBillingEnabled } from '../Config';
|
||||
@@ -287,7 +286,6 @@ export default class BaseAPI<
|
||||
|
||||
let query: Query<BaseModel> = {};
|
||||
let select: Select<BaseModel> = {};
|
||||
let populate: Populate<BaseModel> = {};
|
||||
let sort: Sort<BaseModel> = {};
|
||||
|
||||
if (req.body) {
|
||||
@@ -299,12 +297,6 @@ export default class BaseAPI<
|
||||
req.body['select']
|
||||
) as Select<BaseModel>;
|
||||
|
||||
if (req.body['populate']) {
|
||||
populate = JSONFunctions.deserialize(
|
||||
req.body['populate']
|
||||
) as Populate<BaseModel>;
|
||||
}
|
||||
|
||||
sort = JSONFunctions.deserialize(
|
||||
req.body['sort']
|
||||
) as Sort<BaseModel>;
|
||||
@@ -319,7 +311,6 @@ export default class BaseAPI<
|
||||
skip: skip,
|
||||
limit: limit,
|
||||
sort: sort,
|
||||
populate,
|
||||
props: databaseProps,
|
||||
});
|
||||
|
||||
@@ -371,24 +362,16 @@ export default class BaseAPI<
|
||||
const objectId: ObjectID = new ObjectID(req.params['id'] as string);
|
||||
await this.onBeforeGet(req, res);
|
||||
let select: Select<BaseModel> = {};
|
||||
let populate: Populate<BaseModel> = {};
|
||||
|
||||
if (req.body) {
|
||||
select = JSONFunctions.deserialize(
|
||||
req.body['select']
|
||||
) as Select<BaseModel>;
|
||||
|
||||
if (req.body['populate']) {
|
||||
populate = JSONFunctions.deserialize(
|
||||
req.body['populate']
|
||||
) as Populate<BaseModel>;
|
||||
}
|
||||
}
|
||||
|
||||
const item: BaseModel | null = await this.service.findOneById({
|
||||
id: objectId,
|
||||
select,
|
||||
populate,
|
||||
props: await this.getDatabaseCommonInteractionProps(req),
|
||||
});
|
||||
|
||||
|
||||
118
CommonServer/API/NotificationAPI.ts
Normal file
118
CommonServer/API/NotificationAPI.ts
Normal file
@@ -0,0 +1,118 @@
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
OneUptimeRequest,
|
||||
} from '../Utils/Express';
|
||||
import UserMiddleware from '../Middleware/UserAuthorization';
|
||||
import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import Response from '../Utils/Response';
|
||||
import NotificationService from '../Services/NotificationService';
|
||||
import ObjectID from 'Common/Types/ObjectID';
|
||||
import JSONFunctions from 'Common/Types/JSONFunctions';
|
||||
import Permission, { UserPermission } from 'Common/Types/Permission';
|
||||
import Exception from 'Common/Types/Exception/Exception';
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
router.post(
|
||||
'/notification/recharge',
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse) => {
|
||||
try {
|
||||
let amount: number | PositiveNumber =
|
||||
JSONFunctions.deserializeValue(req.body.amount) as
|
||||
| number
|
||||
| PositiveNumber;
|
||||
|
||||
if (amount instanceof PositiveNumber) {
|
||||
amount = amount.toNumber();
|
||||
}
|
||||
|
||||
if (typeof amount === 'string') {
|
||||
amount = parseInt(amount);
|
||||
}
|
||||
|
||||
const projectId: ObjectID = JSONFunctions.deserializeValue(
|
||||
req.body.projectId
|
||||
) as ObjectID;
|
||||
|
||||
if (!amount || typeof amount !== 'number') {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Invalid amount')
|
||||
);
|
||||
}
|
||||
|
||||
if (amount > 1000) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Amount cannot be greater than 1000')
|
||||
);
|
||||
}
|
||||
|
||||
if (amount < 20) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Amount cannot be less than 20')
|
||||
);
|
||||
}
|
||||
|
||||
if (!projectId || !projectId.toString()) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Invalid projectId')
|
||||
);
|
||||
}
|
||||
|
||||
// get permissions. if user has permission to recharge, then recharge
|
||||
|
||||
if (
|
||||
!(req as OneUptimeRequest).userTenantAccessPermission ||
|
||||
!(req as OneUptimeRequest).userTenantAccessPermission![
|
||||
projectId.toString()
|
||||
]
|
||||
) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Permission for this user not found')
|
||||
);
|
||||
}
|
||||
|
||||
const permissions: Array<Permission> = (
|
||||
req as OneUptimeRequest
|
||||
).userTenantAccessPermission![
|
||||
projectId.toString()
|
||||
]!.permissions.map((permission: UserPermission) => {
|
||||
return permission.permission;
|
||||
});
|
||||
|
||||
if (
|
||||
permissions.includes(Permission.ProjectOwner) ||
|
||||
permissions.includes(Permission.CanManageProjectBilling)
|
||||
) {
|
||||
await NotificationService.rechargeBalance(projectId, amount);
|
||||
} else {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException(
|
||||
'User does not have permission to recharge. You need any one of these permissions - ProjectOwner, CanManageProjectBilling'
|
||||
)
|
||||
);
|
||||
}
|
||||
} catch (err: any) {
|
||||
return Response.sendErrorResponse(req, res, err as Exception);
|
||||
}
|
||||
|
||||
return Response.sendEmptyResponse(req, res);
|
||||
}
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -4,7 +4,6 @@ import UserMiddleware from '../Middleware/UserAuthorization';
|
||||
import StatusPageService, {
|
||||
Service as StatusPageServiceType,
|
||||
} from '../Services/StatusPageService';
|
||||
import Populate from '../Types/Database/Populate';
|
||||
import Select from '../Types/Database/Select';
|
||||
import {
|
||||
ExpressRequest,
|
||||
@@ -61,6 +60,7 @@ import StatusPageSubscriberService from '../Services/StatusPageSubscriberService
|
||||
import PositiveNumber from 'Common/Types/PositiveNumber';
|
||||
import StatusPageSsoService from '../Services/StatusPageSsoService';
|
||||
import StatusPageSSO from 'Model/Models/StatusPageSso';
|
||||
import ArrayUtil from 'Common/Types/ArrayUtil';
|
||||
|
||||
export default class StatusPageAPI extends BaseAPI<
|
||||
StatusPage,
|
||||
@@ -228,6 +228,24 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
enableSubscribers: true,
|
||||
isPublicStatusPage: true,
|
||||
requireSsoForLogin: true,
|
||||
coverImageFile: {
|
||||
file: true,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
},
|
||||
faviconFile: {
|
||||
file: true,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
},
|
||||
logoFile: {
|
||||
file: true,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
},
|
||||
};
|
||||
|
||||
const hasEnabledSSO: PositiveNumber =
|
||||
@@ -241,32 +259,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
},
|
||||
});
|
||||
|
||||
const populate: Populate<StatusPage> = {
|
||||
coverImageFile: {
|
||||
file: true as any,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
} as any,
|
||||
faviconFile: {
|
||||
file: true as any,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
} as any,
|
||||
logoFile: {
|
||||
file: true as any,
|
||||
_id: true,
|
||||
type: true,
|
||||
name: true,
|
||||
} as any,
|
||||
};
|
||||
|
||||
const item: StatusPage | null =
|
||||
await this.service.findOneById({
|
||||
id: objectId,
|
||||
select,
|
||||
populate,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
@@ -286,7 +282,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
link: true,
|
||||
title: true,
|
||||
},
|
||||
populate: {},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
@@ -414,6 +409,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
projectId: true,
|
||||
isPublicStatusPage: true,
|
||||
overviewPageDescription: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -485,13 +481,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
showStatusHistoryChart: true,
|
||||
showCurrentStatus: true,
|
||||
order: true,
|
||||
},
|
||||
populate: {
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
},
|
||||
|
||||
sort: {
|
||||
order: SortOrder.Ascending,
|
||||
},
|
||||
@@ -540,16 +535,14 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
select: {
|
||||
monitorId: true,
|
||||
createdAt: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
populate: {
|
||||
monitorStatus: {
|
||||
name: true,
|
||||
color: true,
|
||||
priority: true,
|
||||
},
|
||||
} as any,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
@@ -575,11 +568,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
title: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
populate: {
|
||||
incidentSeverity: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -592,6 +580,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -600,22 +592,24 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
});
|
||||
}
|
||||
|
||||
const incidentsOnStausPage: Array<ObjectID> =
|
||||
const incidentsOnStatusPage: Array<ObjectID> =
|
||||
activeIncidents.map((incident: Incident) => {
|
||||
return incident.id!;
|
||||
});
|
||||
|
||||
let incidentPublicNotes: Array<IncidentPublicNote> = [];
|
||||
|
||||
if (incidentsOnStausPage.length > 0) {
|
||||
if (incidentsOnStatusPage.length > 0) {
|
||||
incidentPublicNotes =
|
||||
await IncidentPublicNoteService.findBy({
|
||||
query: {
|
||||
incidentId:
|
||||
QueryHelper.in(incidentsOnStausPage),
|
||||
incidentId: QueryHelper.in(
|
||||
incidentsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
note: true,
|
||||
incidentId: true,
|
||||
},
|
||||
@@ -633,20 +627,19 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
let incidentStateTimelines: Array<IncidentStateTimeline> =
|
||||
[];
|
||||
|
||||
if (incidentsOnStausPage.length > 0) {
|
||||
if (incidentsOnStatusPage.length > 0) {
|
||||
incidentStateTimelines =
|
||||
await IncidentStateTimelineService.findBy({
|
||||
query: {
|
||||
incidentId:
|
||||
QueryHelper.in(incidentsOnStausPage),
|
||||
incidentId: QueryHelper.in(
|
||||
incidentsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
createdAt: true,
|
||||
incidentId: true,
|
||||
},
|
||||
populate: {
|
||||
incidentState: {
|
||||
_id: true,
|
||||
name: true,
|
||||
@@ -656,6 +649,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
isAcknowledgedState: true,
|
||||
},
|
||||
},
|
||||
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending, // new note first
|
||||
},
|
||||
@@ -685,6 +679,8 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
title: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
showAnnouncementAt: true,
|
||||
endAnnouncementAt: true,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
@@ -710,11 +706,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
description: true,
|
||||
_id: true,
|
||||
endsAt: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
populate: {
|
||||
startsAt: true,
|
||||
currentScheduledMaintenanceState: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -726,6 +718,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -749,11 +745,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
populate: {
|
||||
currentScheduledMaintenanceState: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -765,6 +756,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -778,7 +773,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
}
|
||||
);
|
||||
|
||||
const scheduledMaintenanceEventsOnStausPage: Array<ObjectID> =
|
||||
const scheduledMaintenanceEventsOnStatusPage: Array<ObjectID> =
|
||||
scheduledMaintenanceEvents.map(
|
||||
(event: ScheduledMaintenance) => {
|
||||
return event.id!;
|
||||
@@ -788,16 +783,17 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
let scheduledMaintenanceEventsPublicNotes: Array<ScheduledMaintenancePublicNote> =
|
||||
[];
|
||||
|
||||
if (scheduledMaintenanceEventsOnStausPage.length > 0) {
|
||||
if (scheduledMaintenanceEventsOnStatusPage.length > 0) {
|
||||
scheduledMaintenanceEventsPublicNotes =
|
||||
await ScheduledMaintenancePublicNoteService.findBy({
|
||||
query: {
|
||||
scheduledMaintenanceId: QueryHelper.in(
|
||||
scheduledMaintenanceEventsOnStausPage
|
||||
scheduledMaintenanceEventsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
note: true,
|
||||
scheduledMaintenanceId: true,
|
||||
},
|
||||
@@ -815,13 +811,13 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
let scheduledMaintenanceStateTimelines: Array<ScheduledMaintenanceStateTimeline> =
|
||||
[];
|
||||
|
||||
if (scheduledMaintenanceEventsOnStausPage.length > 0) {
|
||||
if (scheduledMaintenanceEventsOnStatusPage.length > 0) {
|
||||
scheduledMaintenanceStateTimelines =
|
||||
await ScheduledMaintenanceStateTimelineService.findBy(
|
||||
{
|
||||
query: {
|
||||
scheduledMaintenanceId: QueryHelper.in(
|
||||
scheduledMaintenanceEventsOnStausPage
|
||||
scheduledMaintenanceEventsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
@@ -829,8 +825,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
createdAt: true,
|
||||
scheduledMaintenanceId: true,
|
||||
},
|
||||
populate: {
|
||||
scheduledMaintenanceState: {
|
||||
_id: true,
|
||||
color: true,
|
||||
@@ -840,6 +834,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
isOngoingState: true,
|
||||
},
|
||||
},
|
||||
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending, // new note first
|
||||
},
|
||||
@@ -894,6 +889,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
incidentStateTimelines,
|
||||
IncidentStateTimeline
|
||||
),
|
||||
statusPage: JSONFunctions.toJSONObject(
|
||||
statusPage,
|
||||
StatusPage
|
||||
),
|
||||
scheduledMaintenanceStateTimelines:
|
||||
JSONFunctions.toJSONArray(
|
||||
scheduledMaintenanceStateTimelines,
|
||||
@@ -1193,6 +1192,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
select: {
|
||||
_id: true,
|
||||
projectId: true,
|
||||
showScheduledEventHistoryInDays: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -1216,13 +1216,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
},
|
||||
populate: {
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1232,10 +1231,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
// check if status page has active scheduled events.
|
||||
const today: Date = OneUptimeDate.getCurrentDate();
|
||||
const last14Days: Date = OneUptimeDate.getSomeDaysAgo(14);
|
||||
const historyDays: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
statusPage.showScheduledEventHistoryInDays || 14
|
||||
);
|
||||
|
||||
let query: Query<ScheduledMaintenance> = {
|
||||
startsAt: QueryHelper.inBetween(last14Days, today),
|
||||
startsAt: QueryHelper.inBetween(historyDays, today),
|
||||
statusPages: [statusPageId] as any,
|
||||
projectId: statusPage.projectId!,
|
||||
};
|
||||
@@ -1258,11 +1259,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
},
|
||||
sort: {
|
||||
startsAt: SortOrder.Descending,
|
||||
},
|
||||
populate: {
|
||||
currentScheduledMaintenanceState: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -1274,6 +1270,10 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
startsAt: SortOrder.Descending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1297,11 +1297,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
endsAt: true,
|
||||
startsAt: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
populate: {
|
||||
currentScheduledMaintenanceState: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -1313,6 +1308,9 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Ascending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1326,7 +1324,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
}
|
||||
);
|
||||
|
||||
const scheduledMaintenanceEventsOnStausPage: Array<ObjectID> =
|
||||
const scheduledMaintenanceEventsOnStatusPage: Array<ObjectID> =
|
||||
scheduledMaintenanceEvents.map((event: ScheduledMaintenance) => {
|
||||
return event.id!;
|
||||
});
|
||||
@@ -1334,16 +1332,17 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
let scheduledMaintenanceEventsPublicNotes: Array<ScheduledMaintenancePublicNote> =
|
||||
[];
|
||||
|
||||
if (scheduledMaintenanceEventsOnStausPage.length > 0) {
|
||||
if (scheduledMaintenanceEventsOnStatusPage.length > 0) {
|
||||
scheduledMaintenanceEventsPublicNotes =
|
||||
await ScheduledMaintenancePublicNoteService.findBy({
|
||||
query: {
|
||||
scheduledMaintenanceId: QueryHelper.in(
|
||||
scheduledMaintenanceEventsOnStausPage
|
||||
scheduledMaintenanceEventsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
note: true,
|
||||
scheduledMaintenanceId: true,
|
||||
},
|
||||
@@ -1361,12 +1360,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
let scheduledMaintenanceStateTimelines: Array<ScheduledMaintenanceStateTimeline> =
|
||||
[];
|
||||
|
||||
if (scheduledMaintenanceEventsOnStausPage.length > 0) {
|
||||
if (scheduledMaintenanceEventsOnStatusPage.length > 0) {
|
||||
scheduledMaintenanceStateTimelines =
|
||||
await ScheduledMaintenanceStateTimelineService.findBy({
|
||||
query: {
|
||||
scheduledMaintenanceId: QueryHelper.in(
|
||||
scheduledMaintenanceEventsOnStausPage
|
||||
scheduledMaintenanceEventsOnStatusPage
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
@@ -1374,8 +1373,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
createdAt: true,
|
||||
scheduledMaintenanceId: true,
|
||||
},
|
||||
populate: {
|
||||
scheduledMaintenanceState: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -1384,6 +1381,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
isOngoingState: true,
|
||||
},
|
||||
},
|
||||
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending, // new note first
|
||||
},
|
||||
@@ -1437,6 +1435,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
select: {
|
||||
_id: true,
|
||||
projectId: true,
|
||||
showAnnouncementHistoryInDays: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -1451,11 +1450,13 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
// check if status page has actuve announcement.
|
||||
|
||||
const today: Date = OneUptimeDate.getCurrentDate();
|
||||
const last14Days: Date = OneUptimeDate.getSomeDaysAgo(14);
|
||||
const historyDays: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
statusPage.showAnnouncementHistoryInDays || 14
|
||||
);
|
||||
|
||||
let query: Query<StatusPageAnnouncement> = {
|
||||
statusPages: [statusPageId] as any,
|
||||
showAnnouncementAt: QueryHelper.inBetween(last14Days, today),
|
||||
showAnnouncementAt: QueryHelper.inBetween(historyDays, today),
|
||||
projectId: statusPage.projectId!,
|
||||
};
|
||||
|
||||
@@ -1497,13 +1498,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
},
|
||||
populate: {
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1545,6 +1545,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
select: {
|
||||
_id: true,
|
||||
projectId: true,
|
||||
showIncidentHistoryInDays: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -1568,13 +1569,12 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
displayTooltip: true,
|
||||
displayDescription: true,
|
||||
displayName: true,
|
||||
},
|
||||
populate: {
|
||||
monitor: {
|
||||
_id: true,
|
||||
currentMonitorStatusId: true,
|
||||
},
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
@@ -1590,12 +1590,14 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
);
|
||||
|
||||
const today: Date = OneUptimeDate.getCurrentDate();
|
||||
const last14Days: Date = OneUptimeDate.getSomeDaysAgo(14);
|
||||
const historyDays: Date = OneUptimeDate.getSomeDaysAgo(
|
||||
statusPage.showIncidentHistoryInDays || 14
|
||||
);
|
||||
|
||||
let incidentQuery: Query<Incident> = {
|
||||
monitors: monitorsOnStatusPage as any,
|
||||
projectId: statusPage.projectId!,
|
||||
createdAt: QueryHelper.inBetween(last14Days, today),
|
||||
createdAt: QueryHelper.inBetween(historyDays, today),
|
||||
};
|
||||
|
||||
if (incidentId) {
|
||||
@@ -1616,11 +1618,6 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
title: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
populate: {
|
||||
incidentSeverity: {
|
||||
name: true,
|
||||
color: true,
|
||||
@@ -1633,15 +1630,61 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
const activeIncidents: Array<Incident> =
|
||||
await IncidentService.findBy({
|
||||
query: {
|
||||
monitors: monitorsOnStatusPage as any,
|
||||
currentIncidentState: {
|
||||
isResolvedState: false,
|
||||
} as any,
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
title: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
incidentSeverity: {
|
||||
name: true,
|
||||
color: true,
|
||||
},
|
||||
currentIncidentState: {
|
||||
name: true,
|
||||
color: true,
|
||||
},
|
||||
monitors: {
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
incidents = [...activeIncidents, ...incidents];
|
||||
|
||||
// get distinct by id.
|
||||
|
||||
incidents = ArrayUtil.distinctByFieldName(incidents, '_id');
|
||||
}
|
||||
|
||||
const incidentsOnStausPage: Array<ObjectID> = incidents.map(
|
||||
const incidentsOnStatusPage: Array<ObjectID> = incidents.map(
|
||||
(incident: Incident) => {
|
||||
return incident.id!;
|
||||
}
|
||||
@@ -1649,13 +1692,14 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
let incidentPublicNotes: Array<IncidentPublicNote> = [];
|
||||
|
||||
if (incidentsOnStausPage.length > 0) {
|
||||
if (incidentsOnStatusPage.length > 0) {
|
||||
incidentPublicNotes = await IncidentPublicNoteService.findBy({
|
||||
query: {
|
||||
incidentId: QueryHelper.in(incidentsOnStausPage),
|
||||
incidentId: QueryHelper.in(incidentsOnStatusPage),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
createdAt: true,
|
||||
note: true,
|
||||
incidentId: true,
|
||||
},
|
||||
@@ -1672,26 +1716,25 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
let incidentStateTimelines: Array<IncidentStateTimeline> = [];
|
||||
|
||||
if (incidentsOnStausPage.length > 0) {
|
||||
if (incidentsOnStatusPage.length > 0) {
|
||||
incidentStateTimelines = await IncidentStateTimelineService.findBy({
|
||||
query: {
|
||||
incidentId: QueryHelper.in(incidentsOnStausPage),
|
||||
incidentId: QueryHelper.in(incidentsOnStatusPage),
|
||||
projectId: statusPage.projectId!,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
createdAt: true,
|
||||
incidentId: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending, // new note first
|
||||
},
|
||||
populate: {
|
||||
incidentState: {
|
||||
name: true,
|
||||
color: true,
|
||||
},
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending, // new note first
|
||||
},
|
||||
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
|
||||
122
CommonServer/API/UserCallAPI.ts
Normal file
122
CommonServer/API/UserCallAPI.ts
Normal 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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
123
CommonServer/API/UserEmailAPI.ts
Normal file
123
CommonServer/API/UserEmailAPI.ts
Normal 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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
161
CommonServer/API/UserOnCallLogTimelineAPI.ts
Normal file
161
CommonServer/API/UserOnCallLogTimelineAPI.ts
Normal 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()}`
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
118
CommonServer/API/UserSmsAPI.ts
Normal file
118
CommonServer/API/UserSmsAPI.ts
Normal 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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import Hostname from 'Common/Types/API/Hostname';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import SubscriptionPlan from 'Common/Types/Billing/SubscriptionPlan';
|
||||
import { JSONObject } from 'Common/Types/JSON';
|
||||
import URL from 'Common/Types/API/URL';
|
||||
|
||||
export const getAllEnvVars: Function = (): JSONObject => {
|
||||
return process.env;
|
||||
@@ -27,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';
|
||||
@@ -57,14 +58,18 @@ export const RealtimeHostname: Hostname = Hostname.fromString(
|
||||
process.env['REALTIME_HOSTNAME'] || 'realtime'
|
||||
);
|
||||
|
||||
export const MailHostname: Hostname = Hostname.fromString(
|
||||
process.env['MAIL_HOSTNAME'] || 'mail'
|
||||
export const NotificationHostname: Hostname = Hostname.fromString(
|
||||
process.env['NOTIFICATION_HOSTNAME'] || 'notification'
|
||||
);
|
||||
|
||||
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'
|
||||
);
|
||||
@@ -119,10 +124,14 @@ export const IdentityRoute: Route = new Route(
|
||||
|
||||
export const FileRoute: Route = new Route(process.env['FILE_ROUTE'] || '/file');
|
||||
|
||||
export const StausPageRoute: Route = new Route(
|
||||
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'
|
||||
);
|
||||
@@ -131,6 +140,10 @@ export const IntegrationRoute: Route = new Route(
|
||||
process.env['INTEGRATION_ROUTE'] || '/integration'
|
||||
);
|
||||
|
||||
export const NotificationRoute: Route = new Route(
|
||||
process.env['NOTIFICATION_ROUTE'] || '/notification'
|
||||
);
|
||||
|
||||
export const HelmRoute: Route = new Route(
|
||||
process.env['HELMCHART_ROUTE'] || '/helm-chart'
|
||||
);
|
||||
@@ -163,3 +176,5 @@ export const SubscriptionPlans: Array<SubscriptionPlan> =
|
||||
|
||||
export const AnalyticsKey: string = process.env['ANALYTICS_KEY'] || '';
|
||||
export const AnalyticsHost: string = process.env['ANALYTICS_HOST'] || '';
|
||||
|
||||
export const DashboardUrl: URL = new URL(HttpProtocol, Domain, DashboardRoute);
|
||||
|
||||
71
CommonServer/Middleware/NotificationMiddleware.ts
Normal file
71
CommonServer/Middleware/NotificationMiddleware.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,7 @@ import BadDataException from 'Common/Types/Exception/BadDataException';
|
||||
import SsoAuthorizationException from 'Common/Types/Exception/SsoAuthorizationException';
|
||||
import JSONWebTokenData from 'Common/Types/JsonWebTokenData';
|
||||
import logger from '../Utils/Logger';
|
||||
import Exception from 'Common/Types/Exception/Exception';
|
||||
|
||||
export default class UserMiddleware {
|
||||
/*
|
||||
@@ -120,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)) {
|
||||
@@ -175,121 +177,40 @@ export default class UserMiddleware {
|
||||
}
|
||||
|
||||
if (tenantId) {
|
||||
const project: Project | null = await ProjectService.findOneById({
|
||||
id: tenantId,
|
||||
select: {
|
||||
requireSsoForLogin: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
try {
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
await UserMiddleware.getUserTenantAccessPermissionWithTenantId(
|
||||
req,
|
||||
tenantId,
|
||||
new ObjectID(userId)
|
||||
);
|
||||
|
||||
if (!project) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException('Invalid tenantId')
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
project.requireSsoForLogin &&
|
||||
!UserMiddleware.doesSsoTokenForProjectExist(
|
||||
req,
|
||||
tenantId,
|
||||
new ObjectID(userId)
|
||||
)
|
||||
) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new SsoAuthorizationException()
|
||||
);
|
||||
}
|
||||
|
||||
// get project level permissions if projectid exists in request.
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
await AccessTokenService.getUserTenantAccessPermission(
|
||||
oneuptimeRequest.userAuthorization.userId,
|
||||
tenantId
|
||||
);
|
||||
|
||||
if (userTenantAccessPermission) {
|
||||
oneuptimeRequest.userTenantAccessPermission = {};
|
||||
oneuptimeRequest.userTenantAccessPermission[
|
||||
tenantId.toString()
|
||||
] = userTenantAccessPermission;
|
||||
if (userTenantAccessPermission) {
|
||||
oneuptimeRequest.userTenantAccessPermission = {};
|
||||
oneuptimeRequest.userTenantAccessPermission[
|
||||
tenantId.toString()
|
||||
] = userTenantAccessPermission;
|
||||
}
|
||||
} catch (error) {
|
||||
return Response.sendErrorResponse(req, res, error as Exception);
|
||||
}
|
||||
}
|
||||
|
||||
if (req.headers['is-multi-tenant-query']) {
|
||||
oneuptimeRequest.userTenantAccessPermission = {};
|
||||
|
||||
if (
|
||||
userGlobalAccessPermission &&
|
||||
userGlobalAccessPermission.projectIds &&
|
||||
userGlobalAccessPermission.projectIds.length > 0
|
||||
) {
|
||||
const projects: Array<Project> = await ProjectService.findBy({
|
||||
query: {
|
||||
_id: QueryHelper.in(
|
||||
userGlobalAccessPermission?.projectIds.map(
|
||||
(i: ObjectID) => {
|
||||
return i.toString();
|
||||
}
|
||||
) || []
|
||||
),
|
||||
},
|
||||
select: {
|
||||
requireSsoForLogin: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
for (const projectId of userGlobalAccessPermission?.projectIds ||
|
||||
[]) {
|
||||
// check if the force sso login is required. and if it is, then check then token.
|
||||
|
||||
if (
|
||||
projects.find((p: Project) => {
|
||||
return (
|
||||
p._id === projectId.toString() &&
|
||||
p.requireSsoForLogin
|
||||
);
|
||||
}) &&
|
||||
!UserMiddleware.doesSsoTokenForProjectExist(
|
||||
req,
|
||||
projectId,
|
||||
new ObjectID(userId)
|
||||
)
|
||||
) {
|
||||
// Add default permissions.
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
AccessTokenService.getDefaultUserTenantAccessPermission(
|
||||
projectId
|
||||
);
|
||||
oneuptimeRequest.userTenantAccessPermission[
|
||||
projectId.toString()
|
||||
] = userTenantAccessPermission;
|
||||
} else {
|
||||
// get project level permissions if projectid exists in request.
|
||||
const userTenantAccessPermission: UserTenantAccessPermission | null =
|
||||
await AccessTokenService.getUserTenantAccessPermission(
|
||||
oneuptimeRequest.userAuthorization.userId,
|
||||
projectId
|
||||
);
|
||||
|
||||
if (userTenantAccessPermission) {
|
||||
oneuptimeRequest.userTenantAccessPermission[
|
||||
projectId.toString()
|
||||
] = userTenantAccessPermission;
|
||||
}
|
||||
}
|
||||
const userTenantAccessPermission: Dictionary<UserTenantAccessPermission> | null =
|
||||
await UserMiddleware.getUserTenantAccessPermissionForMultiTenant(
|
||||
req,
|
||||
new ObjectID(userId),
|
||||
userGlobalAccessPermission.projectIds
|
||||
);
|
||||
if (userTenantAccessPermission) {
|
||||
oneuptimeRequest.userTenantAccessPermission =
|
||||
userTenantAccessPermission;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -343,4 +264,106 @@ export default class UserMiddleware {
|
||||
|
||||
return next();
|
||||
}
|
||||
|
||||
public static async getUserTenantAccessPermissionWithTenantId(
|
||||
req: ExpressRequest,
|
||||
tenantId: ObjectID,
|
||||
userId: ObjectID
|
||||
): Promise<UserTenantAccessPermission | null> {
|
||||
const project: Project | null = await ProjectService.findOneById({
|
||||
id: tenantId,
|
||||
select: {
|
||||
requireSsoForLogin: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!project) {
|
||||
throw new BadDataException('Invalid tenantId');
|
||||
}
|
||||
|
||||
if (
|
||||
project.requireSsoForLogin &&
|
||||
!UserMiddleware.doesSsoTokenForProjectExist(req, tenantId, userId)
|
||||
) {
|
||||
throw new SsoAuthorizationException();
|
||||
}
|
||||
|
||||
// get project level permissions if projectid exists in request.
|
||||
return await AccessTokenService.getUserTenantAccessPermission(
|
||||
userId,
|
||||
tenantId
|
||||
);
|
||||
}
|
||||
|
||||
public static async getUserTenantAccessPermissionForMultiTenant(
|
||||
req: ExpressRequest,
|
||||
userId: ObjectID,
|
||||
projectIds: ObjectID[]
|
||||
): Promise<Dictionary<UserTenantAccessPermission> | null> {
|
||||
if (!projectIds.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const projects: Array<Project> = await ProjectService.findBy({
|
||||
query: {
|
||||
_id: QueryHelper.in(
|
||||
projectIds.map((i: ObjectID) => {
|
||||
return i.toString();
|
||||
}) || []
|
||||
),
|
||||
},
|
||||
select: {
|
||||
requireSsoForLogin: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
let result: Dictionary<UserTenantAccessPermission> | null = null;
|
||||
for (const projectId of projectIds) {
|
||||
// check if the force sso login is required. and if it is, then check then token.
|
||||
|
||||
let userTenantAccessPermission: UserTenantAccessPermission | null;
|
||||
if (
|
||||
projects.find((p: Project) => {
|
||||
return (
|
||||
p._id === projectId.toString() && p.requireSsoForLogin
|
||||
);
|
||||
}) &&
|
||||
!UserMiddleware.doesSsoTokenForProjectExist(
|
||||
req,
|
||||
projectId,
|
||||
userId
|
||||
)
|
||||
) {
|
||||
// Add default permissions.
|
||||
userTenantAccessPermission =
|
||||
AccessTokenService.getDefaultUserTenantAccessPermission(
|
||||
projectId
|
||||
);
|
||||
} else {
|
||||
// get project level permissions if projectid exists in request.
|
||||
userTenantAccessPermission =
|
||||
await AccessTokenService.getUserTenantAccessPermission(
|
||||
userId,
|
||||
projectId
|
||||
);
|
||||
}
|
||||
|
||||
if (userTenantAccessPermission) {
|
||||
if (!result) {
|
||||
result = {};
|
||||
}
|
||||
result[projectId.toString()] = userTenantAccessPermission;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> {
|
||||
@@ -87,13 +87,11 @@ export default class AccessTokenService {
|
||||
},
|
||||
select: {
|
||||
permission: true,
|
||||
labels: true,
|
||||
},
|
||||
populate: {
|
||||
labels: {
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
|
||||
limit: LIMIT_MAX,
|
||||
skip: 0,
|
||||
props: {
|
||||
@@ -118,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.
|
||||
@@ -165,7 +163,7 @@ export default class AccessTokenService {
|
||||
return permissionToStore;
|
||||
}
|
||||
|
||||
public static getDefaultUserTenantAccessPermission(
|
||||
public getDefaultUserTenantAccessPermission(
|
||||
projectId: ObjectID
|
||||
): UserTenantAccessPermission {
|
||||
const userPermissions: Array<UserPermission> = [];
|
||||
@@ -191,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(
|
||||
@@ -200,9 +198,7 @@ export default class AccessTokenService {
|
||||
);
|
||||
|
||||
if (!json) {
|
||||
return await AccessTokenService.refreshUserGlobalAccessPermission(
|
||||
userId
|
||||
);
|
||||
return await this.refreshUserGlobalAccessPermission(userId);
|
||||
}
|
||||
|
||||
const accessPermission: UserGlobalAccessPermission =
|
||||
@@ -213,7 +209,7 @@ export default class AccessTokenService {
|
||||
return accessPermission;
|
||||
}
|
||||
|
||||
public static async refreshUserTenantAccessPermission(
|
||||
public async refreshUserTenantAccessPermission(
|
||||
userId: ObjectID,
|
||||
projectId: ObjectID
|
||||
): Promise<UserTenantAccessPermission | null> {
|
||||
@@ -252,13 +248,11 @@ export default class AccessTokenService {
|
||||
},
|
||||
select: {
|
||||
permission: true,
|
||||
labels: true,
|
||||
},
|
||||
populate: {
|
||||
labels: {
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
|
||||
limit: LIMIT_MAX,
|
||||
skip: 0,
|
||||
props: {
|
||||
@@ -283,7 +277,7 @@ export default class AccessTokenService {
|
||||
}
|
||||
|
||||
const permission: UserTenantAccessPermission =
|
||||
AccessTokenService.getDefaultUserTenantAccessPermission(projectId);
|
||||
this.getDefaultUserTenantAccessPermission(projectId);
|
||||
|
||||
permission.permissions = permission.permissions.concat(userPermissions);
|
||||
|
||||
@@ -296,7 +290,7 @@ export default class AccessTokenService {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public static async getUserTenantAccessPermission(
|
||||
public async getUserTenantAccessPermission(
|
||||
userId: ObjectID,
|
||||
projectId: ObjectID
|
||||
): Promise<UserTenantAccessPermission | null> {
|
||||
@@ -311,7 +305,7 @@ export default class AccessTokenService {
|
||||
}
|
||||
|
||||
if (!json) {
|
||||
return await AccessTokenService.refreshUserTenantAccessPermission(
|
||||
return await this.refreshUserTenantAccessPermission(
|
||||
userId,
|
||||
projectId
|
||||
);
|
||||
@@ -320,3 +314,5 @@ export default class AccessTokenService {
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
export default new AccessTokenService();
|
||||
|
||||
3
CommonServer/Services/BaseService.ts
Normal file
3
CommonServer/Services/BaseService.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export default class BaseService {
|
||||
public constructor() {}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
@@ -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,7 +348,15 @@ export class BillingService {
|
||||
await this.stripe.paymentMethods.detach(paymentMethodId);
|
||||
}
|
||||
|
||||
public static async getPaymentMethods(
|
||||
public async hasPaymentMethods(customerId: string): Promise<boolean> {
|
||||
if ((await this.getPaymentMethods(customerId)).length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async getPaymentMethods(
|
||||
customerId: string
|
||||
): Promise<Array<PaymentMethod>> {
|
||||
if (!this.isBillingEnabled()) {
|
||||
@@ -419,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,
|
||||
@@ -436,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.'
|
||||
@@ -451,7 +457,7 @@ export class BillingService {
|
||||
}
|
||||
}
|
||||
|
||||
public static async getSubscriptionStatus(
|
||||
public async getSubscriptionStatus(
|
||||
subscriptionId: string
|
||||
): Promise<SubscriptionStatus> {
|
||||
const subscription: Stripe.Subscription = await this.getSubscription(
|
||||
@@ -460,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()) {
|
||||
@@ -475,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,
|
||||
@@ -497,7 +501,48 @@ export class BillingService {
|
||||
});
|
||||
}
|
||||
|
||||
public static async payInvoice(
|
||||
public async genrateInvoiceAndChargeCustomer(
|
||||
customerId: string,
|
||||
itemText: string,
|
||||
amountInUsd: number
|
||||
): Promise<void> {
|
||||
const invoice: Stripe.Invoice = await this.stripe.invoices.create({
|
||||
customer: customerId,
|
||||
auto_advance: true, // do not automatically charge.
|
||||
collection_method: 'charge_automatically',
|
||||
});
|
||||
|
||||
if (!invoice || !invoice.id) {
|
||||
throw new APIException('Invoice not generated.');
|
||||
}
|
||||
|
||||
await this.stripe.invoiceItems.create({
|
||||
invoice: invoice.id,
|
||||
amount: amountInUsd * 100,
|
||||
description: itemText,
|
||||
customer: customerId,
|
||||
});
|
||||
|
||||
await this.stripe.invoices.finalizeInvoice(invoice.id!);
|
||||
|
||||
try {
|
||||
await this.payInvoice(customerId, invoice.id!);
|
||||
} catch (err) {
|
||||
// mark invoice as failed and do not collect payment.
|
||||
await this.voidInvoice(invoice.id!);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
public async voidInvoice(invoiceId: string): Promise<Stripe.Invoice> {
|
||||
const invoice: Stripe.Invoice = await this.stripe.invoices.voidInvoice(
|
||||
invoiceId
|
||||
);
|
||||
|
||||
return invoice;
|
||||
}
|
||||
|
||||
public async payInvoice(
|
||||
customerId: string,
|
||||
invoiceId: string
|
||||
): Promise<Invoice> {
|
||||
@@ -530,4 +575,4 @@ export class BillingService {
|
||||
}
|
||||
}
|
||||
|
||||
export default BillingService;
|
||||
export default new BillingService();
|
||||
|
||||
12
CommonServer/Services/CallLogService.ts
Normal file
12
CommonServer/Services/CallLogService.ts
Normal 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();
|
||||
52
CommonServer/Services/CallService.ts
Normal file
52
CommonServer/Services/CallService.ts
Normal 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();
|
||||
@@ -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();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user