mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 08:42:13 +02:00
Compare commits
553 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30940991e0 | ||
|
|
a6d3047007 | ||
|
|
2ae0d139ea | ||
|
|
1507583cf3 | ||
|
|
310e1b764c | ||
|
|
1d7a25f2bb | ||
|
|
3bc89a8cae | ||
|
|
ff54b5a26c | ||
|
|
07b9f38e90 | ||
|
|
f612940668 | ||
|
|
6046bda443 | ||
|
|
cd97a72ef2 | ||
|
|
c20fbcc7a4 | ||
|
|
f22e410860 | ||
|
|
3059ca848e | ||
|
|
ce8b8c3b58 | ||
|
|
78846a3f95 | ||
|
|
994f329a49 | ||
|
|
d621df58cd | ||
|
|
0e0ccd9651 | ||
|
|
cc0adea216 | ||
|
|
8ec0825a52 | ||
|
|
4d083f9663 | ||
|
|
81b3795b1c | ||
|
|
74cf9ae184 | ||
|
|
9ba4c0bfdd | ||
|
|
85e83c6822 | ||
|
|
65eedde511 | ||
|
|
7d45056ae4 | ||
|
|
f2db382087 | ||
|
|
3e99783119 | ||
|
|
de6bbbee8c | ||
|
|
0309c2d7e8 | ||
|
|
1c9bb0605b | ||
|
|
b8b98be7a0 | ||
|
|
6c037b0996 | ||
|
|
326b60c260 | ||
|
|
e13ab0b214 | ||
|
|
01f8a27dd2 | ||
|
|
081029b49a | ||
|
|
32d55fdc46 | ||
|
|
69aa680dd1 | ||
|
|
117c02d457 | ||
|
|
f74fcb3734 | ||
|
|
676d6598d7 | ||
|
|
af1edfef99 | ||
|
|
56cadf01fd | ||
|
|
6a0ef8d940 | ||
|
|
1e01942218 | ||
|
|
5dab4f8042 | ||
|
|
3e4a50d430 | ||
|
|
96d236b034 | ||
|
|
ade5e69aa0 | ||
|
|
4733c710b2 | ||
|
|
1c8922249e | ||
|
|
73c787836f | ||
|
|
ec6f3d84d7 | ||
|
|
1f2df5f3ee | ||
|
|
121a78ea8d | ||
|
|
832ab4ab24 | ||
|
|
445f3906ee | ||
|
|
c869acc0e5 | ||
|
|
0d2b2a272b | ||
|
|
d8ac1c39b7 | ||
|
|
e31dbe935c | ||
|
|
35e46cebfc | ||
|
|
891861f396 | ||
|
|
fbc38230b8 | ||
|
|
61561f9745 | ||
|
|
13e5f57160 | ||
|
|
7600085473 | ||
|
|
99641d6994 | ||
|
|
dea66cc8d8 | ||
|
|
1dd43a69a0 | ||
|
|
e539cb7ae3 | ||
|
|
5269f7a164 | ||
|
|
8e1d6b420f | ||
|
|
311f7dbb5b | ||
|
|
9ac64b5873 | ||
|
|
e54126e6bf | ||
|
|
a4acc59505 | ||
|
|
854bc297a6 | ||
|
|
69bfb48573 | ||
|
|
9ef7f720b1 | ||
|
|
2155dcad65 | ||
|
|
fb4da29ade | ||
|
|
d146d33059 | ||
|
|
978ac9155f | ||
|
|
cf9b4f0eba | ||
|
|
d26a2aa995 | ||
|
|
c8301e21eb | ||
|
|
1a24232a1c | ||
|
|
69c94835fe | ||
|
|
706a9145ac | ||
|
|
9bde6194a5 | ||
|
|
3dd8c62bc4 | ||
|
|
895a434d0e | ||
|
|
d3ec3a60df | ||
|
|
df15a2dcae | ||
|
|
5e4b24dcfb | ||
|
|
0eae73c4e5 | ||
|
|
deb3f81e5d | ||
|
|
dcb3fe6f69 | ||
|
|
4bbecb3013 | ||
|
|
52954f3702 | ||
|
|
12a7fff668 | ||
|
|
14e489a719 | ||
|
|
83f2935f41 | ||
|
|
28855d482e | ||
|
|
7c11ebdacf | ||
|
|
592c806465 | ||
|
|
7a3d0266c4 | ||
|
|
e9b7368cf1 | ||
|
|
f8c0004f85 | ||
|
|
b007cb8bbd | ||
|
|
541015766c | ||
|
|
5310087287 | ||
|
|
7649c6c566 | ||
|
|
1b2650f6df | ||
|
|
de3586d60e | ||
|
|
a0ca579c2f | ||
|
|
9bc7a115a1 | ||
|
|
aef7af0a9a | ||
|
|
e9f2e46e16 | ||
|
|
56fd18f7c9 | ||
|
|
ecccd8b536 | ||
|
|
dd2f0f37f2 | ||
|
|
600a5eafe3 | ||
|
|
9b07bf7a08 | ||
|
|
d341f6c2b0 | ||
|
|
06a030f518 | ||
|
|
b02fed6e5b | ||
|
|
310884bd73 | ||
|
|
0c625d52c2 | ||
|
|
82ab70f396 | ||
|
|
24d9c9dbc0 | ||
|
|
d9f1dc9fd2 | ||
|
|
4b503471bd | ||
|
|
b523434be3 | ||
|
|
f32b1950d9 | ||
|
|
e1c45a5c99 | ||
|
|
195655b4df | ||
|
|
9d7d65f0ef | ||
|
|
985b5410f6 | ||
|
|
d1dd57deec | ||
|
|
2ec6902537 | ||
|
|
cd130bc8ef | ||
|
|
3fcd1f694e | ||
|
|
b98b43b9f6 | ||
|
|
b59c76f771 | ||
|
|
4d2e386328 | ||
|
|
deddcbe152 | ||
|
|
e305284fe2 | ||
|
|
3163debdb8 | ||
|
|
f827237a80 | ||
|
|
c038e39620 | ||
|
|
b8c1190c9f | ||
|
|
7f5ff5068e | ||
|
|
943acc8567 | ||
|
|
81798211ea | ||
|
|
39596f6a42 | ||
|
|
36a181e77e | ||
|
|
032c03a877 | ||
|
|
500299fb2f | ||
|
|
b959e84032 | ||
|
|
30edc194f4 | ||
|
|
0a20894dd1 | ||
|
|
1045a7399f | ||
|
|
0f3ef0027b | ||
|
|
2f43bc5c65 | ||
|
|
8d9f7e125d | ||
|
|
3ac841ddc1 | ||
|
|
9fc8c6f7a2 | ||
|
|
62cd974235 | ||
|
|
a0d03238ee | ||
|
|
4303cf00cc | ||
|
|
747ea70de5 | ||
|
|
6dd4ef22df | ||
|
|
4b97c79ae2 | ||
|
|
d34b118c68 | ||
|
|
a3ff2e1067 | ||
|
|
e6ef2a7945 | ||
|
|
9bf8d5d941 | ||
|
|
f3ee93bd48 | ||
|
|
5b78fee225 | ||
|
|
dd73947b7f | ||
|
|
78998fb123 | ||
|
|
0bcfccffe0 | ||
|
|
3ab45f40ca | ||
|
|
bb2f610bc8 | ||
|
|
9b685133c4 | ||
|
|
33c4943794 | ||
|
|
a7f8aa4faa | ||
|
|
722fe30c8f | ||
|
|
500104eb81 | ||
|
|
41c3a14dfa | ||
|
|
113eda94fa | ||
|
|
c6ce43f7cc | ||
|
|
6d5bc60127 | ||
|
|
b7b7b28834 | ||
|
|
5a0b0d7c61 | ||
|
|
79bf7ce7ee | ||
|
|
4ab150bf75 | ||
|
|
951668c982 | ||
|
|
d7845407f0 | ||
|
|
8c5e3187ab | ||
|
|
d2ae1cd845 | ||
|
|
8cb64fbe66 | ||
|
|
092b858873 | ||
|
|
81d19722f6 | ||
|
|
1f7b268875 | ||
|
|
38b32a6090 | ||
|
|
373159cb29 | ||
|
|
ec86ef4c0e | ||
|
|
270231374b | ||
|
|
aac4281602 | ||
|
|
bdea1139a4 | ||
|
|
14fdfa6d17 | ||
|
|
3b22747dbf | ||
|
|
eb9e20dad5 | ||
|
|
5aa4b883ad | ||
|
|
ea38e2621f | ||
|
|
b2cb95e1fc | ||
|
|
b174b9795a | ||
|
|
9d1caa8336 | ||
|
|
52e8669960 | ||
|
|
f0505725a7 | ||
|
|
7897641ef7 | ||
|
|
761f5f35e9 | ||
|
|
241586ff4a | ||
|
|
f8fc1a9dae | ||
|
|
6bbcc0a301 | ||
|
|
0e6604aa11 | ||
|
|
ade84a23ff | ||
|
|
6ff883b54e | ||
|
|
3546d92143 | ||
|
|
e932eb1b1d | ||
|
|
cbca712af8 | ||
|
|
8490128833 | ||
|
|
b80e126540 | ||
|
|
5494a2244e | ||
|
|
23be5b1736 | ||
|
|
9f3a9bc915 | ||
|
|
84d322f476 | ||
|
|
f94fbcc2ae | ||
|
|
0e85162b50 | ||
|
|
a5927f3681 | ||
|
|
0d37587199 | ||
|
|
4674578c90 | ||
|
|
87d280edbd | ||
|
|
d44ddd6781 | ||
|
|
7271481fb7 | ||
|
|
7f05ae7415 | ||
|
|
1e84b3a0cb | ||
|
|
20c7b11ecc | ||
|
|
6666f6e817 | ||
|
|
621e1ce207 | ||
|
|
1c42c58591 | ||
|
|
6a1b0d8718 | ||
|
|
bc244bfde1 | ||
|
|
984cb41efc | ||
|
|
076386f0d4 | ||
|
|
cb11a46cc9 | ||
|
|
6c7f1b5eb9 | ||
|
|
95709f1996 | ||
|
|
eaebcc748d | ||
|
|
13c2f6e73d | ||
|
|
f746d353a7 | ||
|
|
de1760bda7 | ||
|
|
a28b870c23 | ||
|
|
eb216e52cf | ||
|
|
c19913ac58 | ||
|
|
b55bb4ceeb | ||
|
|
26ec1aa5b2 | ||
|
|
7b733c32e9 | ||
|
|
3d34118f9e | ||
|
|
69a3a898f5 | ||
|
|
74d21e7c33 | ||
|
|
aecf1c38a6 | ||
|
|
8b3041301a | ||
|
|
af77d191e3 | ||
|
|
ad58125663 | ||
|
|
63650ba791 | ||
|
|
1c5a434ee3 | ||
|
|
102e64224f | ||
|
|
854fe3084a | ||
|
|
b6c6186625 | ||
|
|
92bdd5cf03 | ||
|
|
c2e78d122a | ||
|
|
bfc061ad47 | ||
|
|
98302a887a | ||
|
|
743db411d5 | ||
|
|
9537a9a13a | ||
|
|
0931705d6a | ||
|
|
6bfd9b657a | ||
|
|
493aef5b05 | ||
|
|
185f70e893 | ||
|
|
db2ecde486 | ||
|
|
ff3b7edec8 | ||
|
|
968b050d13 | ||
|
|
4328f7fc40 | ||
|
|
6ae3c28b8b | ||
|
|
8be022e34f | ||
|
|
ce6938396a | ||
|
|
537e2d02e7 | ||
|
|
80b9e48771 | ||
|
|
e0c3437c45 | ||
|
|
e5df15a53e | ||
|
|
a0f6e979b8 | ||
|
|
e20624a635 | ||
|
|
800583ddde | ||
|
|
f0bc71bee4 | ||
|
|
ba0dd4f2b0 | ||
|
|
63b560ad93 | ||
|
|
ae0553a1e5 | ||
|
|
fd4e2737e5 | ||
|
|
15f18c6d4f | ||
|
|
a84e32fe1b | ||
|
|
c09d97310f | ||
|
|
782eb45eb3 | ||
|
|
fb37da0aca | ||
|
|
ae2608e66f | ||
|
|
29565bc24c | ||
|
|
da7860fc3f | ||
|
|
0375e8c568 | ||
|
|
60c53b32e6 | ||
|
|
4d1797e9fa | ||
|
|
1ff4bde7b9 | ||
|
|
fae6d89a18 | ||
|
|
aa429abe01 | ||
|
|
203763aa95 | ||
|
|
0b69ae195f | ||
|
|
0756a43d62 | ||
|
|
13eb3205a2 | ||
|
|
9dcd295fd0 | ||
|
|
1fb84ea302 | ||
|
|
53ea3d32dc | ||
|
|
5c9ec28a4e | ||
|
|
04c2293378 | ||
|
|
6c672c541a | ||
|
|
169db73704 | ||
|
|
e980f00f1c | ||
|
|
66a594ed99 | ||
|
|
52c35c1e4d | ||
|
|
caa4103b48 | ||
|
|
f6069ca4a7 | ||
|
|
f519748c44 | ||
|
|
27de0f0ddb | ||
|
|
5426c22740 | ||
|
|
a55d4d1e02 | ||
|
|
2f65b1ee82 | ||
|
|
730dc56316 | ||
|
|
101e697a12 | ||
|
|
1c1488bca5 | ||
|
|
0e74adbd08 | ||
|
|
35947b4010 | ||
|
|
b304ceddbb | ||
|
|
cba6c48673 | ||
|
|
63b40cde75 | ||
|
|
439f2e87a2 | ||
|
|
fc0869d9fe | ||
|
|
fb5646e8c2 | ||
|
|
7538a47be5 | ||
|
|
8568cc0c89 | ||
|
|
2457de9757 | ||
|
|
a6859631ae | ||
|
|
e737444c52 | ||
|
|
b4a2726c81 | ||
|
|
5fc60491ff | ||
|
|
a7558535a6 | ||
|
|
408d06edb9 | ||
|
|
87be913388 | ||
|
|
1a034abe96 | ||
|
|
19bdfd66b9 | ||
|
|
982d051329 | ||
|
|
b66b1db2cb | ||
|
|
12e67a065d | ||
|
|
1f3cdc08ac | ||
|
|
5ebcba9f46 | ||
|
|
15e49c1b45 | ||
|
|
b71a657dea | ||
|
|
72e573bbc4 | ||
|
|
2113ffefd9 | ||
|
|
8da42884c2 | ||
|
|
e14c54c6cc | ||
|
|
10a199f3f5 | ||
|
|
2df97392b2 | ||
|
|
fcd2ecd118 | ||
|
|
e2e5533229 | ||
|
|
cf01fce011 | ||
|
|
100152ecc1 | ||
|
|
7b68c0b3c0 | ||
|
|
a7ad9b752b | ||
|
|
2e3ed42723 | ||
|
|
864e44d1a2 | ||
|
|
08cdb33e6e | ||
|
|
27647f529f | ||
|
|
4021650ea5 | ||
|
|
6a9f76c656 | ||
|
|
c3bba74107 | ||
|
|
16b9d4794e | ||
|
|
22e16d5c5b | ||
|
|
ef340e5fa0 | ||
|
|
20aff38458 | ||
|
|
16a1051280 | ||
|
|
fe9d3d3020 | ||
|
|
a0c0041cbd | ||
|
|
d755c62a51 | ||
|
|
5756623f45 | ||
|
|
8247f504c4 | ||
|
|
f05b0a15ee | ||
|
|
1abf1df1ee | ||
|
|
f1afab0b52 | ||
|
|
a0d33bf9c1 | ||
|
|
7c16fa7b42 | ||
|
|
5ba526d12e | ||
|
|
92174be7fd | ||
|
|
ece451b660 | ||
|
|
5ca740b43c | ||
|
|
70aae7c59a | ||
|
|
bb543ef010 | ||
|
|
64bba9246b | ||
|
|
511987bd70 | ||
|
|
19162504c8 | ||
|
|
96f5173fb9 | ||
|
|
8704f47b44 | ||
|
|
45803a8cd2 | ||
|
|
c04c2a3563 | ||
|
|
e61e7f3ba0 | ||
|
|
e438050f6e | ||
|
|
9601bdec93 | ||
|
|
c631dcfd44 | ||
|
|
4cabd2562a | ||
|
|
09e997c104 | ||
|
|
eee787be1c | ||
|
|
c9b0d4fbec | ||
|
|
946f82f978 | ||
|
|
8fc3fe4a98 | ||
|
|
3d321a038b | ||
|
|
ef06d47619 | ||
|
|
c8a966a2f7 | ||
|
|
32ffdf9174 | ||
|
|
d482cb00a9 | ||
|
|
6286b8bf4c | ||
|
|
b264f4a6b9 | ||
|
|
ec7d5fe5c2 | ||
|
|
4b9d770030 | ||
|
|
a8100e9b01 | ||
|
|
b43e892295 | ||
|
|
663f151051 | ||
|
|
282373b654 | ||
|
|
43faeb6e32 | ||
|
|
8180fcf386 | ||
|
|
e2cbd4d0ac | ||
|
|
084c259197 | ||
|
|
6ecd709f29 | ||
|
|
b935cef5a0 | ||
|
|
1d5e838afa | ||
|
|
90ca4b68cf | ||
|
|
031bd26b09 | ||
|
|
1296f37081 | ||
|
|
ba1a707156 | ||
|
|
d670cca559 | ||
|
|
f7e31a4f04 | ||
|
|
bb7917551f | ||
|
|
53238aee40 | ||
|
|
187d41e25f | ||
|
|
56f79a91c1 | ||
|
|
4dd6b5f32e | ||
|
|
f48a5a650c | ||
|
|
09a2a31d2b | ||
|
|
5fd60094ab | ||
|
|
0cfc9fbb56 | ||
|
|
2fc6200c47 | ||
|
|
437e5e7004 | ||
|
|
22e2c1f25c | ||
|
|
4799ed0434 | ||
|
|
0848dfc5d6 | ||
|
|
88cf2c3cb0 | ||
|
|
ca3855d109 | ||
|
|
36570f3944 | ||
|
|
df10a1900d | ||
|
|
eca3408598 | ||
|
|
9d1a2c40c7 | ||
|
|
cd58b72a9c | ||
|
|
ceead6eaba | ||
|
|
45a665b004 | ||
|
|
2dd1cd8453 | ||
|
|
8152a7f7ea | ||
|
|
55d962eed7 | ||
|
|
ebf5c83358 | ||
|
|
69e5fba5ff | ||
|
|
139ee62106 | ||
|
|
2d89431dc1 | ||
|
|
d506e658f0 | ||
|
|
180d02c53d | ||
|
|
e500886b12 | ||
|
|
7f7bcbc0a3 | ||
|
|
397231f1df | ||
|
|
f575afa151 | ||
|
|
b26cf4e876 | ||
|
|
450488eb4f | ||
|
|
14d3228786 | ||
|
|
811fd24cd5 | ||
|
|
098fb5be78 | ||
|
|
837d065b81 | ||
|
|
fe2b001c6d | ||
|
|
b08c047da7 | ||
|
|
79ff8b1f82 | ||
|
|
7da47d6e16 | ||
|
|
6e6f3c6c38 | ||
|
|
b3b3d9a0b7 | ||
|
|
16f0fe145a | ||
|
|
eea7209aaf | ||
|
|
c4c93f1cc5 | ||
|
|
0d19f56519 | ||
|
|
85d0ded200 | ||
|
|
c5134f0dd7 | ||
|
|
9e117f34d4 | ||
|
|
72f994d079 | ||
|
|
4a6edfa660 | ||
|
|
a20c05adb2 | ||
|
|
a286aba432 | ||
|
|
a3f1302e37 | ||
|
|
9393388cc5 | ||
|
|
d249fe16d9 | ||
|
|
7f6223f4c8 | ||
|
|
dc5e2c0d40 | ||
|
|
26f6a14e93 | ||
|
|
588de5ad27 | ||
|
|
8734938a82 | ||
|
|
06e7228041 | ||
|
|
38ad431b17 | ||
|
|
e0f5d8f1f2 | ||
|
|
e947d21060 | ||
|
|
41d347a1a7 | ||
|
|
5dc6ab6bb2 | ||
|
|
3492e54a9b | ||
|
|
adf92f3dc9 | ||
|
|
02b9f77e7c | ||
|
|
396f435755 | ||
|
|
5796db03f9 | ||
|
|
4029d72967 | ||
|
|
8d2cf500a0 | ||
|
|
5bfc954076 | ||
|
|
769f468273 | ||
|
|
8d75128603 | ||
|
|
ba4795e4b3 | ||
|
|
65f9f7c830 | ||
|
|
99e56f9312 | ||
|
|
b380e6d770 | ||
|
|
9d0add605d | ||
|
|
d4737841ce |
42
.github/workflows/build.yml
vendored
42
.github/workflows/build.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -31,7 +31,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -46,7 +46,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -76,7 +76,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -91,7 +91,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -137,7 +137,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -154,7 +154,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -169,7 +169,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -185,7 +185,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -200,7 +200,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -215,7 +215,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -231,7 +231,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -246,7 +246,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -261,7 +261,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -276,7 +276,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -291,7 +291,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -306,7 +306,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
@@ -321,7 +321,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
|
||||
4
.github/workflows/common-jobs.yaml
vendored
4
.github/workflows/common-jobs.yaml
vendored
@@ -14,7 +14,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Helm
|
||||
run: |
|
||||
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- run: sudo apt-get update
|
||||
- run: sudo apt-get install -y curl gcc
|
||||
- run: sudo apt-get install -y build-essential
|
||||
|
||||
127
.github/workflows/compile.yml
vendored
127
.github/workflows/compile.yml
vendored
@@ -15,10 +15,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Accounts && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -27,10 +27,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd IsolatedVM && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -39,10 +39,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-app:
|
||||
@@ -50,10 +50,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd App && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -62,10 +62,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Home && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -74,10 +74,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Worker && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -86,10 +86,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Workflow && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -98,10 +98,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd APIReference && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -110,10 +110,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Docs && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -122,10 +122,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Copilot && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -134,10 +134,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd Nginx && npm install && npm run compile && npm run dep-check
|
||||
@@ -158,10 +158,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd AdminDashboard && npm install && npm run compile && npm run dep-check
|
||||
@@ -171,10 +171,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd Dashboard && npm install && npm run compile && npm run dep-check
|
||||
@@ -185,10 +185,11 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: sudo apt-get update
|
||||
- run: cd Common && npm install
|
||||
- run: cd E2E && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -197,10 +198,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Probe && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -209,10 +210,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd ProbeIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -221,10 +222,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd OpenTelemetryIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -234,10 +235,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd IncomingRequestIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -246,10 +247,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd FluentIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
@@ -259,10 +260,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd StatusPage && npm install && npm run compile && npm run dep-check
|
||||
@@ -272,9 +273,9 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd TestServer && npm install && npm run compile && npm run dep-check
|
||||
124
.github/workflows/release.yml
vendored
124
.github/workflows/release.yml
vendored
@@ -87,9 +87,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -147,9 +147,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -207,9 +207,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -267,9 +267,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -330,9 +330,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -390,9 +390,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -452,9 +452,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -512,9 +512,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -572,9 +572,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -632,9 +632,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -693,9 +693,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -753,9 +753,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -813,9 +813,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -874,9 +874,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -934,9 +934,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -995,9 +995,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1055,9 +1055,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1116,9 +1116,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1176,9 +1176,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1227,10 +1227,10 @@ jobs:
|
||||
PACKAGE_VERSION: 7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
- name: Preinstall
|
||||
run: npm run prerun
|
||||
- name: Publish Infrastructure Agent
|
||||
- name: Publish NPM Packages
|
||||
run: bash ./Scripts/NPM/PublishAllPackages.sh
|
||||
|
||||
|
||||
@@ -1271,9 +1271,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
# - name: Setup Git LFS
|
||||
# run: git lfs install
|
||||
@@ -1342,9 +1342,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1409,9 +1409,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1476,9 +1476,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1544,9 +1544,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1607,10 +1607,10 @@ jobs:
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: npm run prerun && bash ./Tests/Scripts/enable-billing-env-var.sh
|
||||
- name: Start Server with release tag
|
||||
run: npm run start
|
||||
@@ -1660,10 +1660,10 @@ jobs:
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: npm run prerun
|
||||
- name: Start Server with release tag
|
||||
run: npm run start
|
||||
@@ -1730,15 +1730,25 @@ jobs:
|
||||
uses: actions/setup-go@v4
|
||||
|
||||
- name: Install GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v5
|
||||
uses: goreleaser/goreleaser-action@v6.1.0
|
||||
with:
|
||||
install-only: true
|
||||
|
||||
- name: GoReleaser Version
|
||||
run: goreleaser -v
|
||||
|
||||
# This tool is used to generate .rpm and .deb packages
|
||||
- name: Install NFPM
|
||||
run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest
|
||||
|
||||
- name: Show GoReleaser version
|
||||
run: goreleaser -v
|
||||
|
||||
- name: Run GoReleaser
|
||||
run: cd InfrastructureAgent && export GORELEASER_CURRENT_TAG=7.0.${{needs.generate-build-number.outputs.build_number}} && goreleaser release --clean --snapshot
|
||||
|
||||
- name: Release MSI Images
|
||||
run: cd InfrastructureAgent && bash build-msi.sh 7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
|
||||
# Upload binaries to github release
|
||||
- name: Release
|
||||
|
||||
172
.github/workflows/test-release.yaml
vendored
172
.github/workflows/test-release.yaml
vendored
@@ -1,5 +1,9 @@
|
||||
name: Push Test Images to Docker Hub and GitHub Container Registry
|
||||
|
||||
concurrency:
|
||||
group: test-release
|
||||
cancel-in-progress: true
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@@ -56,9 +60,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
# - name: Setup Git LFS
|
||||
# run: git lfs install
|
||||
@@ -126,9 +130,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -188,9 +192,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -249,9 +253,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -310,9 +314,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -371,9 +375,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -432,9 +436,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -495,9 +499,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -558,9 +562,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -619,9 +623,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -680,9 +684,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -741,9 +745,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -802,9 +806,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -863,9 +867,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -924,9 +928,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -985,9 +989,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1046,9 +1050,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1107,9 +1111,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1171,9 +1175,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1234,9 +1238,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1295,9 +1299,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1356,9 +1360,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1418,9 +1422,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1480,9 +1484,9 @@ jobs:
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
@@ -1526,14 +1530,14 @@ jobs:
|
||||
|
||||
test-helm-chart:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [llm-docker-image-deploy, open-telemetry-ingest-docker-image-deploy, copilot-docker-image-deploy, docs-docker-image-deploy, worker-docker-image-deploy, workflow-docker-image-deploy, isolated-vm-docker-image-deploy, home-docker-image-deploy, api-reference-docker-image-deploy, test-server-docker-image-deploy, test-docker-image-deploy, probe-ingest-docker-image-deploy, probe-docker-image-deploy, haraka-docker-image-deploy, dashboard-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, accounts-docker-image-deploy, otel-collector-docker-image-deploy, status-page-docker-image-deploy, nginx-docker-image-deploy, e2e-docker-image-deploy, fluent-ingest-docker-image-deploy, incoming-request-ingest-docker-image-deploy]
|
||||
needs: [infrastructure-agent-deploy, llm-docker-image-deploy, open-telemetry-ingest-docker-image-deploy, copilot-docker-image-deploy, docs-docker-image-deploy, worker-docker-image-deploy, workflow-docker-image-deploy, isolated-vm-docker-image-deploy, home-docker-image-deploy, api-reference-docker-image-deploy, test-server-docker-image-deploy, test-docker-image-deploy, probe-ingest-docker-image-deploy, probe-docker-image-deploy, haraka-docker-image-deploy, dashboard-docker-image-deploy, admin-dashboard-docker-image-deploy, app-docker-image-deploy, accounts-docker-image-deploy, otel-collector-docker-image-deploy, status-page-docker-image-deploy, nginx-docker-image-deploy, e2e-docker-image-deploy, fluent-ingest-docker-image-deploy, incoming-request-ingest-docker-image-deploy]
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd HelmChart && cd Tests && bash index.sh
|
||||
|
||||
test-e2e-test-saas:
|
||||
@@ -1555,10 +1559,10 @@ jobs:
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: npm run prerun && bash ./Tests/Scripts/change-release-to-test-tag.sh
|
||||
- name: Start Server with release tag
|
||||
run: npm run start
|
||||
@@ -1608,10 +1612,10 @@ jobs:
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: npm run prerun && bash ./Tests/Scripts/change-release-to-test-tag.sh
|
||||
- name: Start Server with release tag
|
||||
run: npm run start
|
||||
@@ -1640,6 +1644,56 @@ jobs:
|
||||
# Optional. Defaults to repository settings.
|
||||
retention-days: 7
|
||||
|
||||
infrastructure-agent-deploy:
|
||||
needs: [generate-build-number]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.ref }}
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
|
||||
- name: Install GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v6.1.0
|
||||
with:
|
||||
install-only: true
|
||||
|
||||
- name: GoReleaser Version
|
||||
run: goreleaser -v
|
||||
|
||||
# This tool is used to generate .rpm and .deb packages
|
||||
- name: Install NFPM
|
||||
run: go install github.com/goreleaser/nfpm/v2/cmd/nfpm@latest
|
||||
|
||||
- name: Show GoReleaser version
|
||||
run: goreleaser -v
|
||||
|
||||
- name: Run GoReleaser
|
||||
run: cd InfrastructureAgent && export GORELEASER_CURRENT_TAG=7.0.${{needs.generate-build-number.outputs.build_number}} && goreleaser release --clean --snapshot
|
||||
|
||||
- name: Release MSI Images
|
||||
run: cd InfrastructureAgent && bash build-msi.sh 7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
|
||||
|
||||
- name: Upload Release Binaries
|
||||
uses: actions/upload-artifact@v4
|
||||
# Run this on failure
|
||||
with:
|
||||
# Name of the artifact to upload.
|
||||
# Optional. Default is 'artifact'
|
||||
name: binaries
|
||||
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
# Required.
|
||||
path: |
|
||||
./InfrastructureAgent/dist
|
||||
|
||||
|
||||
# Duration after which artifact will expire in days. 0 means using default retention.
|
||||
# Minimum 1 day.
|
||||
# Maximum 90 days unless changed from the repository settings page.
|
||||
# Optional. Defaults to repository settings.
|
||||
retention-days: 7
|
||||
|
||||
|
||||
6
.github/workflows/test.common.yaml
vendored
6
.github/workflows/test.common.yaml
vendored
@@ -14,10 +14,10 @@ jobs:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
BILLING_PRIVATE_KEY: ${{secrets.TEST_BILLING_PRIVATE_KEY}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && bash test-setup.sh
|
||||
- run: cd Common && npm install && rm -rf build && npm run test
|
||||
|
||||
58
.github/workflows/test.e2e.yaml
vendored
58
.github/workflows/test.e2e.yaml
vendored
@@ -1,58 +0,0 @@
|
||||
name: E2E Tests
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches-ignore:
|
||||
- 'hotfix-*' # excludes hotfix branches
|
||||
- 'release'
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
# Docker compose needs a lot of space to build images, so we need to free up some space first in the GitHub Actions runner
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
# this might remove tools that are actually needed,
|
||||
# if set to "true" but frees about 6 GB
|
||||
tool-cache: false
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
- run: npm run prerun && bash ./Tests/Scripts/enable-billing-env-var.sh
|
||||
- run: npm run dev
|
||||
- name: Wait for server to start
|
||||
run: bash ./Tests/Scripts/status-check.sh http://localhost
|
||||
- name: Run E2E Tests. Run docker container e2e in docker compose file
|
||||
run: export $(grep -v '^#' config.env | xargs) && docker compose -f docker-compose.dev.yml up --exit-code-from e2e --abort-on-container-exit e2e || (docker compose -f docker-compose.dev.yml logs e2e && exit 1)
|
||||
- name: Upload test results
|
||||
uses: actions/upload-artifact@v4
|
||||
# Run this on failure
|
||||
if: failure()
|
||||
with:
|
||||
# Name of the artifact to upload.
|
||||
# Optional. Default is 'artifact'
|
||||
name: test-results
|
||||
|
||||
# A file, directory or wildcard pattern that describes what to upload
|
||||
# Required.
|
||||
path: |
|
||||
./E2E
|
||||
|
||||
|
||||
# Duration after which artifact will expire in days. 0 means using default retention.
|
||||
# Minimum 1 day.
|
||||
# Maximum 90 days unless changed from the repository settings page.
|
||||
# Optional. Defaults to repository settings.
|
||||
retention-days: 7
|
||||
6
.github/workflows/test.fluent-ingest.yaml
vendored
6
.github/workflows/test.fluent-ingest.yaml
vendored
@@ -13,8 +13,8 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd FluentIngest && npm install && npm run test
|
||||
@@ -13,9 +13,9 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd IncomingRequestIngest && npm install && npm run test
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd OpenTelemetryIngest && npm install && npm run test
|
||||
|
||||
|
||||
6
.github/workflows/test.probe-ingest.yaml
vendored
6
.github/workflows/test.probe-ingest.yaml
vendored
@@ -13,9 +13,9 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd ProbeIngest && npm install && npm run test
|
||||
|
||||
|
||||
6
.github/workflows/test.probe.yaml
vendored
6
.github/workflows/test.probe.yaml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Probe && npm install
|
||||
- run: cd Probe && npm run test
|
||||
|
||||
18
.github/workflows/test.yaml
vendored
18
.github/workflows/test.yaml
vendored
@@ -13,10 +13,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd App && npm install && npm run test
|
||||
|
||||
test-home:
|
||||
@@ -24,10 +24,10 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Home && npm install && npm run test
|
||||
|
||||
test-worker:
|
||||
@@ -35,8 +35,8 @@ jobs:
|
||||
env:
|
||||
CI_PIPELINE_ID: ${{github.run_number}}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.3.0
|
||||
node-version: latest
|
||||
- run: cd Worker && npm install && npm run test
|
||||
22
.vscode/launch.json
vendored
22
.vscode/launch.json
vendored
@@ -93,7 +93,7 @@
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Worker",
|
||||
"localRoot": "${workspaceFolder}/Workflow",
|
||||
"name": "Workflow: Debug with Docker",
|
||||
"port": 8735,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
@@ -107,7 +107,7 @@
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Worker",
|
||||
"localRoot": "${workspaceFolder}/Docs",
|
||||
"name": "Docs: Debug with Docker",
|
||||
"port": 8738,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
@@ -121,7 +121,7 @@
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Worker",
|
||||
"localRoot": "${workspaceFolder}/APIReference",
|
||||
"name": "API Reference: Debug with Docker",
|
||||
"port": 8737,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
@@ -151,7 +151,7 @@
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Probe",
|
||||
"name": "Probe: Debug with Docker",
|
||||
"port": 9655,
|
||||
"port": 9229,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
"request": "attach",
|
||||
"skipFiles": [
|
||||
@@ -259,20 +259,6 @@
|
||||
"restart": true,
|
||||
"autoAttachChildProcesses": true
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/Workers",
|
||||
"name": "Workers: Debug with Docker",
|
||||
"port": 9654,
|
||||
"remoteRoot": "/usr/src/app",
|
||||
"request": "attach",
|
||||
"skipFiles": [
|
||||
"<node_internals>/**"
|
||||
],
|
||||
"type": "node",
|
||||
"restart": true,
|
||||
"autoAttachChildProcesses": true
|
||||
},
|
||||
{
|
||||
"address": "127.0.0.1",
|
||||
"localRoot": "${workspaceFolder}/StatusPage",
|
||||
|
||||
@@ -12,14 +12,14 @@
|
||||
</h2>
|
||||
|
||||
<script>
|
||||
function showPermissions(id){
|
||||
var permissionsblock = document.getElementById(id+"-permissions");
|
||||
var viewPermissionsBtn = document.getElementById(id+"-view-permissions");
|
||||
function showPermissions(id) {
|
||||
var permissionsblock = document.getElementById(id + "-permissions");
|
||||
var viewPermissionsBtn = document.getElementById(id + "-view-permissions");
|
||||
|
||||
if(permissionsblock.style.display === "none"){
|
||||
if (permissionsblock.style.display === "none") {
|
||||
permissionsblock.style.display = "block";
|
||||
viewPermissionsBtn.innerHTML = "Hide Permissions";
|
||||
}else{
|
||||
} else {
|
||||
permissionsblock.style.display = "none";
|
||||
viewPermissionsBtn.innerHTML = "View Permissions";
|
||||
}
|
||||
@@ -48,11 +48,16 @@
|
||||
<dt class="sr-only">Description</dt>
|
||||
<dd class="w-full flex-none text-sm [&>:first-child]:mt-0 [&>:last-child]:mb-0">
|
||||
<p>
|
||||
<%= pageData.columns[Object.keys(pageData.columns)[i]].description -%> <a class="text-gray-500 hover:underline cursor-pointer text-xs" id="<%= Object.keys(pageData.columns)[i] -%>-view-permissions" onclick="showPermissions('<%= Object.keys(pageData.columns)[i] -%>')">View Permissions</a>
|
||||
<%= pageData.columns[Object.keys(pageData.columns)[i]].description -%> <a
|
||||
class="text-gray-500 hover:underline cursor-pointer text-xs"
|
||||
id="<%= Object.keys(pageData.columns)[i] -%>-view-permissions"
|
||||
onclick="showPermissions('<%= Object.keys(pageData.columns)[i] -%>')">View
|
||||
Permissions</a>
|
||||
</p>
|
||||
</dd>
|
||||
|
||||
<dd class="font-mono text-xs" style="display: none;" id="<%= Object.keys(pageData.columns)[i] -%>-permissions">
|
||||
<dd class="font-mono text-xs" style="display: none;"
|
||||
id="<%= Object.keys(pageData.columns)[i] -%>-permissions">
|
||||
|
||||
<div class="mb-3 mt-3">
|
||||
<span class="text-gray-700 text-xs">Permissions to Create: </span>
|
||||
@@ -319,8 +324,7 @@
|
||||
|
||||
<div class="[&>:first-child]:mt-0 [&>:last-child]:mb-0 xl:sticky xl:top-24">
|
||||
<%- include('../partials/code', {title: "Example Item Request" , requestUrl:
|
||||
pageData.apiPath+"/3599ee69-43a7-42d7/get-item", code: pageData.itemRequest, requestType: "POST" })
|
||||
-%>
|
||||
pageData.apiPath+"/:id/get-item", code: pageData.itemRequest, requestType: "POST" }) -%>
|
||||
<%- include('../partials/code', {title: "Example Item Response" , code: pageData.itemResponse,
|
||||
requestType: "" }) -%>
|
||||
</div>
|
||||
@@ -469,11 +473,34 @@
|
||||
|
||||
</ul>
|
||||
</div>
|
||||
<div class="border border-gray-100 bg-gray-50 rounded-md p-4 text-sm mt-10">
|
||||
<h4 class="font-semibold text-gray-700 ">For clients that do not support PUT requests<h4>
|
||||
<p class="text-gray-500 text-xs mt-4">
|
||||
You can also update an object by sending a POST or GET request to these endpoints with the
|
||||
same
|
||||
request headers and body.
|
||||
</p>
|
||||
|
||||
<div class="flex items-center gap-x-3 mt-10"><span
|
||||
class="font-mono text-[0.625rem] font-semibold leading-6 rounded-lg px-1.5 ring-1 ring-inset ring-sky-300 bg-sky-400/10 text-sky-500 ">POST</span><span
|
||||
class="h-0.5 w-0.5 rounded-full bg-zinc-300 "></span><span
|
||||
class="font-mono text-xs text-zinc-400">
|
||||
<%= pageData.apiPath -%>/:id/update-item
|
||||
</span></div>
|
||||
<div class="flex items-center gap-x-3 mt-10"><span
|
||||
class="font-mono text-[0.625rem] font-semibold leading-6 rounded-lg px-1.5 ring-1 ring-inset ring-emerald-300 bg-emerald-400/10 text-emerald-500 ">GET</span><span
|
||||
class="h-0.5 w-0.5 rounded-full bg-zinc-300 "></span><span
|
||||
class="font-mono text-xs text-zinc-400">
|
||||
<%= pageData.apiPath -%>/:id/update-item
|
||||
</span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="[&>:first-child]:mt-0 [&>:last-child]:mb-0 xl:sticky xl:top-24">
|
||||
<%- include('../partials/code', {title: "Example Update Request" , requestUrl:
|
||||
pageData.apiPath+"/3599ee69-43a7-42d7", code: pageData.updateRequest, requestType: "PUT" }) -%>
|
||||
pageData.apiPath+"/:id", code: pageData.updateRequest, requestType: "PUT" }) -%>
|
||||
<%- include('../partials/code', {title: "Example Update Response" , code: pageData.updateResponse,
|
||||
requestType: "" }) -%>
|
||||
</div>
|
||||
@@ -498,11 +525,34 @@
|
||||
<p>This endpoint allows you to delete object by its ID. </p>
|
||||
|
||||
|
||||
<div class="border border-gray-100 bg-gray-50 rounded-md p-4 text-sm mt-10">
|
||||
<h4 class="font-semibold text-gray-700 ">For clients that do not support DELETE requests<h4>
|
||||
<p class="text-gray-500 text-xs mt-4">
|
||||
You can also delete an object by sending a POST or GET request to these endpoints with the
|
||||
same
|
||||
request headers and body.
|
||||
</p>
|
||||
|
||||
<div class="flex items-center gap-x-3 mt-10"><span
|
||||
class="font-mono text-[0.625rem] font-semibold leading-6 rounded-lg px-1.5 ring-1 ring-inset ring-sky-300 bg-sky-400/10 text-sky-500 ">POST</span><span
|
||||
class="h-0.5 w-0.5 rounded-full bg-zinc-300 "></span><span
|
||||
class="font-mono text-xs text-zinc-400">
|
||||
<%= pageData.apiPath -%>/:id/delete-item
|
||||
</span></div>
|
||||
<div class="flex items-center gap-x-3 mt-10"><span
|
||||
class="font-mono text-[0.625rem] font-semibold leading-6 rounded-lg px-1.5 ring-1 ring-inset ring-emerald-300 bg-emerald-400/10 text-emerald-500 ">GET</span><span
|
||||
class="h-0.5 w-0.5 rounded-full bg-zinc-300 "></span><span
|
||||
class="font-mono text-xs text-zinc-400">
|
||||
<%= pageData.apiPath -%>/:id/delete-item
|
||||
</span></div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
<div class="[&>:first-child]:mt-0 [&>:last-child]:mb-0 xl:sticky xl:top-24">
|
||||
<%- include('../partials/code', {title: "Example Delete Request" , requestUrl:
|
||||
pageData.apiPath+"/3599ee69-43a7-42d7", code: pageData.deleteRequest, requestType: "DELETE" }) -%>
|
||||
pageData.apiPath+"/:id", code: pageData.deleteRequest, requestType: "DELETE" }) -%>
|
||||
<%- include('../partials/code', {title: "Example Delete Response" , code: pageData.deleteResponse,
|
||||
requestType: "" }) -%>
|
||||
</div>
|
||||
|
||||
@@ -179,7 +179,7 @@ const RegisterPage: () => JSX.Element = () => {
|
||||
]);
|
||||
|
||||
if (error) {
|
||||
return <ErrorMessage error={error} />;
|
||||
return <ErrorMessage message={error} />;
|
||||
}
|
||||
|
||||
if (isLoading) {
|
||||
|
||||
@@ -137,7 +137,7 @@ const DashboardProjectPicker: FunctionComponent<ComponentProps> = (
|
||||
minLength: 6,
|
||||
},
|
||||
footerElement: getFooter(),
|
||||
fieldType: FormFieldSchemaType.RadioButton,
|
||||
fieldType: FormFieldSchemaType.OptionChooserButton,
|
||||
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
|
||||
getAllEnvVars(),
|
||||
).map((plan: SubscriptionPlan): RadioButton => {
|
||||
|
||||
@@ -41,7 +41,7 @@ const Logout: FunctionComponent = (): ReactElement => {
|
||||
]}
|
||||
>
|
||||
{!error ? <PageLoader isVisible={true} /> : <></>}
|
||||
{error ? <ErrorMessage error={error} /> : <></>}
|
||||
{error ? <ErrorMessage message={error} /> : <></>}
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ const Projects: FunctionComponent = (): ReactElement => {
|
||||
minLength: 6,
|
||||
},
|
||||
footerElement: getFooter(),
|
||||
fieldType: FormFieldSchemaType.RadioButton,
|
||||
fieldType: FormFieldSchemaType.OptionChooserButton,
|
||||
radioButtonOptions: SubscriptionPlan.getSubscriptionPlans(
|
||||
getAllEnvVars(),
|
||||
).map((plan: SubscriptionPlan): RadioButton => {
|
||||
|
||||
@@ -61,7 +61,7 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return <ErrorMessage error={error} />;
|
||||
return <ErrorMessage message={error} />;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -99,7 +99,7 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
},
|
||||
title: "Description",
|
||||
fieldType: FormFieldSchemaType.LongText,
|
||||
required: true,
|
||||
required: false,
|
||||
placeholder: "This probe is to monitor all the internal services.",
|
||||
},
|
||||
|
||||
@@ -170,6 +170,7 @@ const Settings: FunctionComponent = (): ReactElement => {
|
||||
field: {
|
||||
description: true,
|
||||
},
|
||||
noValueMessage: "-",
|
||||
title: "Description",
|
||||
type: FieldType.Text,
|
||||
},
|
||||
|
||||
@@ -496,6 +496,45 @@ import ScheduledMaintenanceTemplateOwnerUserService, {
|
||||
} from "Common/Server/Services/ScheduledMaintenanceTemplateOwnerUserService";
|
||||
import TableView from "Common/Models/DatabaseModels/TableView";
|
||||
|
||||
import IncidentFeed from "Common/Models/DatabaseModels/IncidentFeed";
|
||||
import AlertFeed from "Common/Models/DatabaseModels/AlertFeed";
|
||||
import ScheduledMaintenanceFeed from "Common/Models/DatabaseModels/ScheduledMaintenanceFeed";
|
||||
|
||||
import IncidentFeedService, {
|
||||
Service as IncidentFeedServiceType,
|
||||
} from "Common/Server/Services/IncidentFeedService";
|
||||
|
||||
import AlertFeedService, {
|
||||
Service as AlertFeedServiceType,
|
||||
} from "Common/Server/Services/AlertFeedService";
|
||||
|
||||
import ScheduledMaintenanceFeedService, {
|
||||
Service as ScheduledMaintenanceFeedServiceType,
|
||||
} from "Common/Server/Services/ScheduledMaintenanceFeedService";
|
||||
|
||||
import SlackAPI from "Common/Server/API/SlackAPI";
|
||||
|
||||
import WorkspaceProjectAuthToken from "Common/Models/DatabaseModels/WorkspaceProjectAuthToken";
|
||||
import WorkspaceProjectAuthTokenService, {
|
||||
Service as WorkspaceProjectAuthTokenServiceType,
|
||||
} from "Common/Server/Services/WorkspaceProjectAuthTokenService";
|
||||
|
||||
import WorkspaceUserAuthToken from "Common/Models/DatabaseModels/WorkspaceUserAuthToken";
|
||||
|
||||
import WorkspaceUserAuthTokenService, {
|
||||
Service as WorkspaceUserAuthTokenServiceType,
|
||||
} from "Common/Server/Services/WorkspaceUserAuthTokenService";
|
||||
|
||||
import WorkspaceSetting from "Common/Models/DatabaseModels/WorkspaceSetting";
|
||||
import WorkspaceSettingService, {
|
||||
Service as WorkspaceSettingServiceType,
|
||||
} from "Common/Server/Services/WorkspaceSettingService";
|
||||
|
||||
import WorkspaceNotificationRule from "Common/Models/DatabaseModels/WorkspaceNotificationRule";
|
||||
import WorkspaceNotificationRuleService, {
|
||||
Service as WorkspaceNotificationRuleServiceType,
|
||||
} from "Common/Server/Services/WorkspaceNotificationRuleService";
|
||||
|
||||
const BaseAPIFeatureSet: FeatureSet = {
|
||||
init: async (): Promise<void> => {
|
||||
const app: ExpressApplication = Express.getExpressApp();
|
||||
@@ -518,6 +557,19 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
// notification rule
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<
|
||||
WorkspaceNotificationRule,
|
||||
WorkspaceNotificationRuleServiceType
|
||||
>(
|
||||
WorkspaceNotificationRule,
|
||||
WorkspaceNotificationRuleService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<MonitorTest, MonitorTestServiceType>(
|
||||
@@ -526,6 +578,39 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
//service provider setting
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<WorkspaceSetting, WorkspaceSettingServiceType>(
|
||||
WorkspaceSetting,
|
||||
WorkspaceSettingService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<IncidentFeed, IncidentFeedServiceType>(
|
||||
IncidentFeed,
|
||||
IncidentFeedService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<AlertFeed, AlertFeedServiceType>(
|
||||
AlertFeed,
|
||||
AlertFeedService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<
|
||||
ScheduledMaintenanceFeed,
|
||||
ScheduledMaintenanceFeedServiceType
|
||||
>(ScheduledMaintenanceFeed, ScheduledMaintenanceFeedService).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<AlertNoteTemplate, AlertNoteTemplateServiceType>(
|
||||
@@ -534,6 +619,26 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<
|
||||
WorkspaceProjectAuthToken,
|
||||
WorkspaceProjectAuthTokenServiceType
|
||||
>(
|
||||
WorkspaceProjectAuthToken,
|
||||
WorkspaceProjectAuthTokenService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
// user auth token
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<WorkspaceUserAuthToken, WorkspaceUserAuthTokenServiceType>(
|
||||
WorkspaceUserAuthToken,
|
||||
WorkspaceUserAuthTokenService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<Alert, AlertServiceType>(Alert, AlertService).getRouter(),
|
||||
@@ -1328,6 +1433,7 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new ResellerPlanAPI().getRouter(),
|
||||
);
|
||||
app.use(`/${APP_NAME.toLocaleLowerCase()}`, new SlackAPI().getRouter());
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new GlobalConfigAPI().getRouter(),
|
||||
|
||||
@@ -36,6 +36,7 @@ import ProjectSSO from "Common/Models/DatabaseModels/ProjectSso";
|
||||
import TeamMember from "Common/Models/DatabaseModels/TeamMember";
|
||||
import User from "Common/Models/DatabaseModels/User";
|
||||
import xml2js from "xml2js";
|
||||
import Name from "Common/Types/Name";
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
@@ -45,106 +46,112 @@ const router: ExpressRouter = Express.getRouter();
|
||||
router.get(
|
||||
"/service-provider-login",
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
if (!req.query["email"]) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Email is required"),
|
||||
);
|
||||
}
|
||||
try {
|
||||
if (!req.query["email"]) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Email is required"),
|
||||
);
|
||||
}
|
||||
|
||||
const email: Email = new Email(req.query["email"] as string);
|
||||
const email: Email = new Email(req.query["email"] as string);
|
||||
|
||||
if (!email) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Email is required"),
|
||||
);
|
||||
}
|
||||
if (!email) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Email is required"),
|
||||
);
|
||||
}
|
||||
|
||||
// get sso config for this user.
|
||||
// get sso config for this user.
|
||||
|
||||
const user: User | null = await UserService.findOneBy({
|
||||
query: { email: email },
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!user) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
);
|
||||
}
|
||||
|
||||
const userId: ObjectID = user.id!;
|
||||
|
||||
if (!userId) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
);
|
||||
}
|
||||
|
||||
const projectUserBelongsTo: Array<ObjectID> = (
|
||||
await TeamMemberService.findBy({
|
||||
query: { userId: userId },
|
||||
const user: User | null = await UserService.findOneBy({
|
||||
query: { email: email },
|
||||
select: {
|
||||
projectId: true,
|
||||
_id: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
})
|
||||
).map((teamMember: TeamMember) => {
|
||||
return teamMember.projectId!;
|
||||
});
|
||||
});
|
||||
|
||||
if (projectUserBelongsTo.length === 0) {
|
||||
return Response.sendErrorResponse(
|
||||
if (!user) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
);
|
||||
}
|
||||
|
||||
const userId: ObjectID = user.id!;
|
||||
|
||||
if (!userId) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
);
|
||||
}
|
||||
|
||||
const projectUserBelongsTo: Array<ObjectID> = (
|
||||
await TeamMemberService.findBy({
|
||||
query: { userId: userId },
|
||||
select: {
|
||||
projectId: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
})
|
||||
).map((teamMember: TeamMember) => {
|
||||
return teamMember.projectId!;
|
||||
});
|
||||
|
||||
if (projectUserBelongsTo.length === 0) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
);
|
||||
}
|
||||
|
||||
const projectSSOList: Array<ProjectSSO> = await ProjectSSOService.findBy({
|
||||
query: {
|
||||
projectId: QueryHelper.any(projectUserBelongsTo),
|
||||
isEnabled: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
select: {
|
||||
name: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
projectId: true,
|
||||
project: {
|
||||
name: true,
|
||||
} as Select<Project>,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.sendEntityArrayResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("No SSO config found for this user"),
|
||||
projectSSOList,
|
||||
projectSSOList.length,
|
||||
ProjectSSO,
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
|
||||
Response.sendErrorResponse(req, res, err as Exception);
|
||||
}
|
||||
|
||||
const projectSSOList: Array<ProjectSSO> = await ProjectSSOService.findBy({
|
||||
query: {
|
||||
projectId: QueryHelper.any(projectUserBelongsTo),
|
||||
isEnabled: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
select: {
|
||||
name: true,
|
||||
description: true,
|
||||
_id: true,
|
||||
projectId: true,
|
||||
project: {
|
||||
name: true,
|
||||
} as Select<Project>,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
return Response.sendEntityArrayResponse(
|
||||
req,
|
||||
res,
|
||||
projectSSOList,
|
||||
projectSSOList.length,
|
||||
ProjectSSO,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -153,7 +160,7 @@ router.get(
|
||||
async (
|
||||
req: ExpressRequest,
|
||||
res: ExpressResponse,
|
||||
next: NextFunction,
|
||||
_next: NextFunction,
|
||||
): Promise<void> => {
|
||||
try {
|
||||
if (!req.params["projectId"]) {
|
||||
@@ -227,7 +234,9 @@ router.get(
|
||||
|
||||
return Response.redirect(req, res, samlRequestUrl);
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
logger.error(err);
|
||||
|
||||
Response.sendErrorResponse(req, res, err as Exception);
|
||||
}
|
||||
},
|
||||
);
|
||||
@@ -275,6 +284,7 @@ const loginUserWithSso: LoginUserWithSsoFunction = async (
|
||||
|
||||
let issuerUrl: string = "";
|
||||
let email: Email | null = null;
|
||||
let fullName: Name | null = null;
|
||||
|
||||
if (!req.params["projectId"]) {
|
||||
return Response.sendErrorResponse(
|
||||
@@ -364,6 +374,7 @@ const loginUserWithSso: LoginUserWithSsoFunction = async (
|
||||
|
||||
issuerUrl = SSOUtil.getIssuer(response);
|
||||
email = SSOUtil.getEmail(response);
|
||||
fullName = SSOUtil.getUserFullName(response);
|
||||
} catch (err: unknown) {
|
||||
if (err instanceof Exception) {
|
||||
return Response.sendErrorResponse(req, res, err);
|
||||
@@ -412,6 +423,7 @@ const loginUserWithSso: LoginUserWithSsoFunction = async (
|
||||
|
||||
alreadySavedUser = await UserService.createByEmail({
|
||||
email,
|
||||
name: fullName || undefined,
|
||||
isEmailVerified: true,
|
||||
generateRandomPassword: true,
|
||||
props: {
|
||||
@@ -522,7 +534,8 @@ const loginUserWithSso: LoginUserWithSsoFunction = async (
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
Response.sendErrorResponse(req, res, new ServerException());
|
||||
|
||||
Response.sendErrorResponse(req, res, err as Exception);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import logger from "Common/Server/Utils/Logger";
|
||||
import xmlCrypto, { FileKeyInfo } from "xml-crypto";
|
||||
import xmldom from "xmldom";
|
||||
import zlib from "zlib";
|
||||
import Name from "Common/Types/Name";
|
||||
|
||||
export default class SSOUtil {
|
||||
public static createSAMLRequestUrl(data: {
|
||||
@@ -138,6 +139,88 @@ export default class SSOUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static getUserFullName(payload: JSONObject): Name | null {
|
||||
if (!payload["saml2p:Response"] && !payload["samlp:Response"]) {
|
||||
return null;
|
||||
}
|
||||
|
||||
payload =
|
||||
(payload["saml2p:Response"] as JSONObject) ||
|
||||
(payload["samlp:Response"] as JSONObject) ||
|
||||
(payload["Response"] as JSONObject);
|
||||
|
||||
const samlAssertion: JSONArray =
|
||||
(payload["saml2:Assertion"] as JSONArray) ||
|
||||
(payload["saml:Assertion"] as JSONArray) ||
|
||||
(payload["Assertion"] as JSONArray);
|
||||
|
||||
if (!samlAssertion || samlAssertion.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const samlAttributeStatement: JSONArray =
|
||||
((samlAssertion[0] as JSONObject)[
|
||||
"saml2:AttributeStatement"
|
||||
] as JSONArray) ||
|
||||
((samlAssertion[0] as JSONObject)[
|
||||
"saml:AttributeStatement"
|
||||
] as JSONArray) ||
|
||||
((samlAssertion[0] as JSONObject)["AttributeStatement"] as JSONArray);
|
||||
|
||||
if (!samlAttributeStatement || samlAttributeStatement.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const samlAttribute: JSONArray =
|
||||
((samlAttributeStatement[0] as JSONObject)[
|
||||
"saml2:Attribute"
|
||||
] as JSONArray) ||
|
||||
((samlAttributeStatement[0] as JSONObject)[
|
||||
"saml:Attribute"
|
||||
] as JSONArray) ||
|
||||
((samlAttributeStatement[0] as JSONObject)["Attribute"] as JSONArray);
|
||||
|
||||
if (!samlAttribute || samlAttribute.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// get displayName attribute.
|
||||
// {
|
||||
// "$": {
|
||||
// "Name": "http://schemas.microsoft.com/identity/claims/displayname"
|
||||
// },
|
||||
// "AttributeValue": [
|
||||
// "Nawaz Dhandala"
|
||||
// ]
|
||||
// },
|
||||
|
||||
for (let i: number = 0; i < samlAttribute.length; i++) {
|
||||
const attribute: JSONObject = samlAttribute[i] as JSONObject;
|
||||
if (
|
||||
attribute["$"] &&
|
||||
(attribute["$"] as JSONObject)["Name"]?.toString()
|
||||
) {
|
||||
const name: string | undefined = (attribute["$"] as JSONObject)[
|
||||
"Name"
|
||||
]?.toString();
|
||||
if (
|
||||
name &&
|
||||
name === "http://schemas.microsoft.com/identity/claims/displayname" &&
|
||||
attribute["AttributeValue"] &&
|
||||
Array.isArray(attribute["AttributeValue"]) &&
|
||||
attribute["AttributeValue"].length > 0
|
||||
) {
|
||||
const fullName: Name = new Name(
|
||||
attribute["AttributeValue"][0]!.toString() as string,
|
||||
);
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static getEmail(payload: JSONObject): Email {
|
||||
if (!payload["saml2p:Response"] && !payload["samlp:Response"]) {
|
||||
throw new BadRequestException("SAML Response not found.");
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
{{> Start this}}
|
||||
|
||||
{{> CustomLogo this}}
|
||||
{{> EmailTitle title=(concat statusPageName " - Please confirm your subscription" ) }}
|
||||
|
||||
{{> InfoBlock info="You will be the first to hear from us when there are any incidents, announcements or scheduled maintenance events."}}
|
||||
|
||||
{{> ButtonBlock buttonUrl=confirmationUrl buttonText="Confirm Subscription"}}
|
||||
|
||||
{{> InfoBlock info="You can also view the status page by visiting this link:"}}
|
||||
{{> InfoBlock info=statusPageUrl}}
|
||||
|
||||
{{> UnsubscribeBlock this}}
|
||||
|
||||
{{> VerticalSpace this}}
|
||||
|
||||
{{> End this}}
|
||||
@@ -39,7 +39,7 @@
|
||||
{{> InfoBlock info="No resources have been added to this status page yet."}}
|
||||
{{/ifCond}}
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
{{> CustomLogo this}}
|
||||
{{> EmailTitle title=(concat "You have been subscribed to status page - " statusPageName) }}
|
||||
|
||||
{{> InfoBlock info=(concat "You have been subscribed to status page - " statusPageName)}}
|
||||
{{> InfoBlock info="You will be the first to hear from us when there are any incidents, announcements or scheduled maintenance events."}}
|
||||
|
||||
{{> ButtonBlock buttonUrl=statusPageUrl buttonText="Go to Status Page"}}
|
||||
|
||||
{{> InfoBlock info="You can also view the status page by visiting these link:"}}
|
||||
{{> InfoBlock info="You can also view the status page by visiting this link:"}}
|
||||
{{> InfoBlock info=statusPageUrl}}
|
||||
|
||||
{{> UnsubscribeBlock this}}
|
||||
|
||||
{{> VerticalSpace this}}
|
||||
|
||||
{{> End this}}
|
||||
{{> End this}}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
{{> DetailBoxField title="" text=announcementDescription }}
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
{{> DetailBoxField title="" text=incidentDescription }}
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
{{> InfoBlock info=statusPageUrl}}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
{{> DetailBoxField title="" text=eventDescription }}
|
||||
{{> DetailBoxEnd this }}
|
||||
|
||||
{{> InfoBlock info=(concat "This is an automated email sent to you because you are subscribed to " statusPageName) }}
|
||||
{{> InfoBlock info=(concat subscriberEmailNotificationFooterText "") }}
|
||||
|
||||
|
||||
{{> InfoBlock info="You can visit the status page here:"}}
|
||||
|
||||
1778
Clickhouse/config.xml
Normal file
1778
Clickhouse/config.xml
Normal file
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,8 @@ export enum MetricPointType {
|
||||
export enum ServiceType {
|
||||
OpenTelemetry = "OpenTelemetry",
|
||||
Monitor = "Monitor",
|
||||
Alert = "Alert",
|
||||
Incident = "Incident",
|
||||
}
|
||||
|
||||
export default class Metric extends AnalyticsBaseModel {
|
||||
|
||||
@@ -36,6 +36,7 @@ import {
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
import { TelemetryQuery } from "../../Types/Telemetry/TelemetryQuery";
|
||||
import { WorkspaceChannel } from "../../Server/Utils/Workspace/WorkspaceBase";
|
||||
|
||||
@EnableDocumentation()
|
||||
@AccessControlColumn("labels")
|
||||
@@ -1006,4 +1007,51 @@ export default class Alert extends BaseModel {
|
||||
nullable: true,
|
||||
})
|
||||
public telemetryQuery?: TelemetryQuery = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlert,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlert,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.Number,
|
||||
title: "Alert Number",
|
||||
description: "Alert Number",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Number,
|
||||
nullable: true,
|
||||
})
|
||||
public alertNumber?: number = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.JSON,
|
||||
title: "Post Updates To Workspace Channel Name",
|
||||
description: "Post Updates To Workspace Channel Name",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
nullable: true,
|
||||
})
|
||||
public postUpdatesToWorkspaceChannels?: Array<WorkspaceChannel> = undefined;
|
||||
}
|
||||
|
||||
526
Common/Models/DatabaseModels/AlertFeed.ts
Normal file
526
Common/Models/DatabaseModels/AlertFeed.ts
Normal file
@@ -0,0 +1,526 @@
|
||||
import Alert from "./Alert";
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
||||
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import Color from "../../Types/Color";
|
||||
|
||||
export enum AlertFeedEventType {
|
||||
PublicNote = "PublicNote",
|
||||
SubscriberNotificationSent = "SubscriberNotificationSent",
|
||||
OwnerNotificationSent = "OwnerNotificationSent",
|
||||
OwnerUserAdded = "OwnerUserAdded",
|
||||
OwnerTeamAdded = "OwnerTeamAdded",
|
||||
AlertCreated = "AlertCreated",
|
||||
AlertStateChanged = "AlertStateChanged",
|
||||
PrivateNote = "PrivateNote",
|
||||
AlertUpdated = "AlertUpdated",
|
||||
RootCause = "RootCause",
|
||||
RemediationNotes = "RemediationNotes",
|
||||
OwnerUserRemoved = "OwnerUserRemoved",
|
||||
OwnerTeamRemoved = "OwnerTeamRemoved",
|
||||
OnCallPolicy = "OnCallPolicy",
|
||||
OnCallNotification = "OnCallNotification",
|
||||
}
|
||||
|
||||
@EnableDocumentation()
|
||||
@CanAccessIfCanReadOn("alert")
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@EnableWorkflow({
|
||||
create: true,
|
||||
delete: true,
|
||||
update: true,
|
||||
read: true,
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/alert-feed"))
|
||||
@Entity({
|
||||
name: "AlertFeed",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "AlertFeed",
|
||||
singularName: "Alert Feed",
|
||||
pluralName: "Alert Feeds",
|
||||
icon: IconProp.List,
|
||||
tableDescription:
|
||||
"Log of the entire alert state change. This is a log of all the alert state changes, public notes, more etc.",
|
||||
})
|
||||
export default class AlertFeed extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Relation to Alert in which this resource belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "Alert ID",
|
||||
description: "Relation to Alert ID in which this resource belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: true,
|
||||
title: "Log (in Markdown)",
|
||||
description: "Log of the entire alert state change in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public feedInfoInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: false,
|
||||
title: "More Information (in Markdown)",
|
||||
description: "More information in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public moreInformationInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ShortText,
|
||||
required: true,
|
||||
title: "Alert Feed Event",
|
||||
description: "Alert Feed Event",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public alertFeedEventType?: AlertFeedEventType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Color,
|
||||
required: true,
|
||||
title: "Color",
|
||||
description: "Display color for the alert log",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Color,
|
||||
length: ColumnLength.Color,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
transformer: Color.getDatabaseTransformer(),
|
||||
})
|
||||
public displayColor?: Color = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description:
|
||||
"Relation to User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "User ID",
|
||||
description:
|
||||
"User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateAlertFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadAlertFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Feed Posted At",
|
||||
description: "Date and time when the feed was posted",
|
||||
type: TableColumnType.Date,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Date,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public postedAt?: Date = undefined;
|
||||
}
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
import { TelemetryQuery } from "../../Types/Telemetry/TelemetryQuery";
|
||||
import { WorkspaceChannel } from "../../Server/Utils/Workspace/WorkspaceBase";
|
||||
|
||||
@EnableDocumentation()
|
||||
@AccessControlColumn("labels")
|
||||
@@ -853,7 +854,12 @@ export default class Incident extends BaseModel {
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectIncident,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectIncident,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
@@ -1086,4 +1092,51 @@ export default class Incident extends BaseModel {
|
||||
nullable: true,
|
||||
})
|
||||
public telemetryQuery?: TelemetryQuery = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectIncident,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectIncident,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.Number,
|
||||
title: "Incident Number",
|
||||
description: "Incident Number",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Number,
|
||||
nullable: true,
|
||||
})
|
||||
public incidentNumber?: number = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.JSON,
|
||||
title: "Post Updates To Workspace Channel Name",
|
||||
description: "Post Updates To Workspace Channel Name",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
nullable: true,
|
||||
})
|
||||
public postUpdatesToWorkspaceChannels?: Array<WorkspaceChannel> = undefined;
|
||||
}
|
||||
|
||||
526
Common/Models/DatabaseModels/IncidentFeed.ts
Normal file
526
Common/Models/DatabaseModels/IncidentFeed.ts
Normal file
@@ -0,0 +1,526 @@
|
||||
import Incident from "./Incident";
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
||||
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import Color from "../../Types/Color";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
|
||||
export enum IncidentFeedEventType {
|
||||
PublicNote = "PublicNote",
|
||||
SubscriberNotificationSent = "SubscriberNotificationSent",
|
||||
OwnerNotificationSent = "OwnerNotificationSent",
|
||||
OwnerUserAdded = "OwnerUserAdded",
|
||||
OwnerTeamAdded = "OwnerTeamAdded",
|
||||
IncidentCreated = "IncidentCreated",
|
||||
IncidentStateChanged = "IncidentStateChanged",
|
||||
PrivateNote = "PrivateNote",
|
||||
IncidentUpdated = "IncidentUpdated",
|
||||
RootCause = "RootCause",
|
||||
RemediationNotes = "RemediationNotes",
|
||||
OwnerUserRemoved = "OwnerUserRemoved",
|
||||
OwnerTeamRemoved = "OwnerTeamRemoved",
|
||||
OnCallPolicy = "OnCallPolicy",
|
||||
OnCallNotification = "OnCallNotification",
|
||||
}
|
||||
|
||||
@EnableDocumentation()
|
||||
@CanAccessIfCanReadOn("incident")
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@EnableWorkflow({
|
||||
create: true,
|
||||
delete: true,
|
||||
update: true,
|
||||
read: true,
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/incident-feed"))
|
||||
@Entity({
|
||||
name: "IncidentFeed",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "IncidentFeed",
|
||||
singularName: "Incident Feed",
|
||||
pluralName: "Incident Feeds",
|
||||
icon: IconProp.List,
|
||||
tableDescription:
|
||||
"Log of the entire incident state change. This is a log of all the incident state changes, public notes, more etc.",
|
||||
})
|
||||
export default class IncidentFeed extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Relation to Incident in which this resource belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "Incident ID",
|
||||
description: "Relation to Incident ID in which this resource belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: true,
|
||||
title: "Log (in Markdown)",
|
||||
description: "Log of the entire incident state change in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public feedInfoInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: false,
|
||||
title: "More Information (in Markdown)",
|
||||
description: "More information in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public moreInformationInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ShortText,
|
||||
required: true,
|
||||
title: "Incident Feed Event",
|
||||
description: "Incident Feed Event",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public incidentFeedEventType?: IncidentFeedEventType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Color,
|
||||
required: true,
|
||||
title: "Color",
|
||||
description: "Display color for the incident log",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Color,
|
||||
length: ColumnLength.Color,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
transformer: Color.getDatabaseTransformer(),
|
||||
})
|
||||
public displayColor?: Color = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description:
|
||||
"Relation to User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "User ID",
|
||||
description:
|
||||
"User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Feed Posted At",
|
||||
description: "Date and time when the feed was posted",
|
||||
type: TableColumnType.Date,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Date,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public postedAt?: Date = undefined;
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import GreenlockCertificate from "./GreenlockCertificate";
|
||||
import GreenlockChallenge from "./GreenlockChallenge";
|
||||
// Incidents
|
||||
import Incident from "./Incident";
|
||||
import IncidentFeed from "./IncidentFeed";
|
||||
import IncidentCustomField from "./IncidentCustomField";
|
||||
import IncidentInternalNote from "./IncidentInternalNote";
|
||||
import IncidentNoteTemplate from "./IncidentNoteTemplate";
|
||||
@@ -142,6 +143,7 @@ import ScheduledMaintenanceTemplateOwnerTeam from "./ScheduledMaintenanceTemplat
|
||||
import ScheduledMaintenanceTemplateOwnerUser from "./ScheduledMaintenanceTemplateOwnerUser";
|
||||
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
|
||||
import AlertState from "./AlertState";
|
||||
import Alert from "./Alert";
|
||||
import AlertCustomField from "./AlertCustomField";
|
||||
@@ -151,15 +153,25 @@ import AlertOwnerTeam from "./AlertOwnerTeam";
|
||||
import AlertOwnerUser from "./AlertOwnerUser";
|
||||
import AlertSeverity from "./AlertSeverity";
|
||||
import AlertNoteTemplate from "./AlertNoteTemplate";
|
||||
import AlertFeed from "./AlertFeed";
|
||||
|
||||
import TableView from "./TableView";
|
||||
import Dashboard from "./Dashboard";
|
||||
|
||||
import MonitorTest from "./MonitorTest";
|
||||
import ScheduledMaintenanceFeed from "./ScheduledMaintenanceFeed";
|
||||
|
||||
import WorkspaceUserAuthToken from "./WorkspaceUserAuthToken";
|
||||
import WorkspaceProjectAuthToken from "./WorkspaceProjectAuthToken";
|
||||
import WorkspaceSetting from "./WorkspaceSetting";
|
||||
import WorkspaceNotificationRule from "./WorkspaceNotificationRule";
|
||||
|
||||
const AllModelTypes: Array<{
|
||||
new (): BaseModel;
|
||||
}> = [
|
||||
User,
|
||||
WorkspaceUserAuthToken,
|
||||
WorkspaceProjectAuthToken,
|
||||
Probe,
|
||||
Project,
|
||||
EmailVerificationToken,
|
||||
@@ -187,6 +199,7 @@ const AllModelTypes: Array<{
|
||||
|
||||
IncidentState,
|
||||
Incident,
|
||||
IncidentFeed,
|
||||
IncidentCustomField,
|
||||
IncidentStateTimeline,
|
||||
IncidentInternalNote,
|
||||
@@ -201,6 +214,7 @@ const AllModelTypes: Array<{
|
||||
|
||||
AlertState,
|
||||
Alert,
|
||||
AlertFeed,
|
||||
AlertCustomField,
|
||||
AlertStateTimeline,
|
||||
AlertInternalNote,
|
||||
@@ -232,6 +246,7 @@ const AllModelTypes: Array<{
|
||||
ScheduledMaintenancePublicNote,
|
||||
ScheduledMaintenanceInternalNote,
|
||||
ScheduledMaintenanceCustomField,
|
||||
ScheduledMaintenanceFeed,
|
||||
|
||||
BillingPaymentMethods,
|
||||
BillingInvoice,
|
||||
@@ -335,6 +350,9 @@ const AllModelTypes: Array<{
|
||||
Dashboard,
|
||||
|
||||
MonitorTest,
|
||||
|
||||
WorkspaceSetting,
|
||||
WorkspaceNotificationRule,
|
||||
];
|
||||
|
||||
const modelTypeMap: { [key: string]: { new (): BaseModel } } = {};
|
||||
|
||||
@@ -442,6 +442,7 @@ export default class MonitorTest extends BaseModel {
|
||||
})
|
||||
public monitorStepProbeResponse?: MonitorStepProbeResponse = undefined;
|
||||
|
||||
@Index()
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
|
||||
@@ -216,6 +216,7 @@ export default class OnCallDutyPolicyExecutionLog extends BaseModel {
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Triggered By Incident ID",
|
||||
required: false,
|
||||
description:
|
||||
"ID of the incident which triggered this on-call escalation policy.",
|
||||
})
|
||||
@@ -270,6 +271,7 @@ export default class OnCallDutyPolicyExecutionLog extends BaseModel {
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Triggered By Alert ID",
|
||||
required: false,
|
||||
description:
|
||||
"ID of the incident which triggered this on-call escalation policy.",
|
||||
})
|
||||
|
||||
@@ -26,6 +26,7 @@ import OnCallDutyExecutionLogTimelineStatus from "../../Types/OnCallDutyPolicy/O
|
||||
import Permission from "../../Types/Permission";
|
||||
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import Alert from "./Alert";
|
||||
|
||||
@TableBillingAccessControl({
|
||||
create: PlanType.Growth,
|
||||
@@ -216,18 +217,74 @@ export default class OnCallDutyPolicyExecutionLogTimeline extends BaseModel {
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of your OneUptime Incident in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByIncidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectOnCallDutyPolicyExecutionLogTimeline,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "triggeredByAlertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Relation to Alert Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "triggeredByAlertId" })
|
||||
public triggeredByAlert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectOnCallDutyPolicyExecutionLogTimeline,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of your OneUptime Alert in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByAlertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
import Recurring from "../../Types/Events/Recurring";
|
||||
import { WorkspaceChannel } from "../../Server/Utils/Workspace/WorkspaceBase";
|
||||
|
||||
@EnableDocumentation()
|
||||
@AccessControlColumn("labels")
|
||||
@@ -950,4 +951,51 @@ export default class ScheduledMaintenance extends BaseModel {
|
||||
nullable: true,
|
||||
})
|
||||
public nextSubscriberNotificationBeforeTheEventAt?: Date = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectScheduledMaintenance,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectScheduledMaintenance,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.Number,
|
||||
title: "Scheduled Maintenance Number",
|
||||
description: "Scheduled Maintenance Number",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Number,
|
||||
nullable: true,
|
||||
})
|
||||
public scheduledMaintenanceNumber?: number = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
required: false,
|
||||
type: TableColumnType.JSON,
|
||||
title: "Post Updates To Workspace Channel Name",
|
||||
description: "Post Updates To Workspace Channel Name",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
nullable: true,
|
||||
})
|
||||
public postUpdatesToWorkspaceChannels?: Array<WorkspaceChannel> = undefined;
|
||||
}
|
||||
|
||||
530
Common/Models/DatabaseModels/ScheduledMaintenanceFeed.ts
Normal file
530
Common/Models/DatabaseModels/ScheduledMaintenanceFeed.ts
Normal file
@@ -0,0 +1,530 @@
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
||||
import EnableWorkflow from "../../Types/Database/EnableWorkflow";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import Color from "../../Types/Color";
|
||||
|
||||
export enum ScheduledMaintenanceFeedEventType {
|
||||
PublicNote = "PublicNote",
|
||||
SubscriberNotificationSent = "SubscriberNotificationSent",
|
||||
OwnerNotificationSent = "OwnerNotificationSent",
|
||||
OwnerUserAdded = "OwnerUserAdded",
|
||||
OwnerTeamAdded = "OwnerTeamAdded",
|
||||
ScheduledMaintenanceCreated = "ScheduledMaintenanceCreated",
|
||||
ScheduledMaintenanceStateChanged = "ScheduledMaintenanceStateChanged",
|
||||
PrivateNote = "PrivateNote",
|
||||
ScheduledMaintenanceUpdated = "ScheduledMaintenanceUpdated",
|
||||
RootCause = "RootCause",
|
||||
RemediationNotes = "RemediationNotes",
|
||||
OwnerUserRemoved = "OwnerUserRemoved",
|
||||
OwnerTeamRemoved = "OwnerTeamRemoved",
|
||||
OnCallPolicy = "OnCallPolicy",
|
||||
OnCallNotification = "OnCallNotification",
|
||||
}
|
||||
|
||||
@EnableDocumentation()
|
||||
@CanAccessIfCanReadOn("scheduledMaintenance")
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@EnableWorkflow({
|
||||
create: true,
|
||||
delete: true,
|
||||
update: true,
|
||||
read: true,
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/scheduled-maintenance-feed"))
|
||||
@Entity({
|
||||
name: "ScheduledMaintenanceFeed",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "ScheduledMaintenanceFeed",
|
||||
singularName: "Scheduled Maintenance Feed",
|
||||
pluralName: "Scheduled Maintenance Feed",
|
||||
icon: IconProp.List,
|
||||
tableDescription:
|
||||
"Log of the entire scheduled maintenance state change. This is a log of all the scheduled maintenance state changes, public notes, more etc.",
|
||||
})
|
||||
export default class ScheduledMaintenanceFeed extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "ScheduledMaintenance",
|
||||
description:
|
||||
"Relation to ScheduledMaintenance in which this resource belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "ScheduledMaintenance ID",
|
||||
description:
|
||||
"Relation to ScheduledMaintenance ID in which this resource belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: true,
|
||||
title: "Log (in Markdown)",
|
||||
description:
|
||||
"Log of the entire scheduled maintenance state change in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public feedInfoInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Markdown,
|
||||
required: false,
|
||||
title: "More Information (in Markdown)",
|
||||
description: "More information in Markdown",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Markdown,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public moreInformationInMarkdown?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ShortText,
|
||||
required: true,
|
||||
title: "ScheduledMaintenance Log Event",
|
||||
description: "ScheduledMaintenance Log Event",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
})
|
||||
public scheduledMaintenanceFeedEventType?: ScheduledMaintenanceFeedEventType =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Color,
|
||||
required: true,
|
||||
title: "Color",
|
||||
description: "Display color for this log",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Color,
|
||||
length: ColumnLength.Color,
|
||||
nullable: false,
|
||||
unique: false,
|
||||
transformer: Color.getDatabaseTransformer(),
|
||||
})
|
||||
public displayColor?: Color = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description:
|
||||
"Relation to User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "User ID",
|
||||
description:
|
||||
"User who this feed belongs to (if this feed belongs to a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceFeed,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceFeed,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Feed Posted At",
|
||||
description: "Date and time when the feed was posted",
|
||||
type: TableColumnType.Date,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Date,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public postedAt?: Date = undefined;
|
||||
}
|
||||
@@ -1973,4 +1973,37 @@ export default class StatusPage extends BaseModel {
|
||||
default: UptimePrecision.TWO_DECIMAL,
|
||||
})
|
||||
public overallUptimePercentPrecision?: UptimePrecision = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectStatusPage,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectStatusPage,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectStatusPage,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Subscriber Email Notification Footer Text",
|
||||
description: "Text to send to subscribers in the footer of the email.",
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.VeryLongText,
|
||||
})
|
||||
public subscriberEmailNotificationFooterText?: string = undefined;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,12 @@ export default class StatusPageAnnouncement extends BaseModel {
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageAnnouncement,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditStatusPageAnnouncement,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
|
||||
@@ -434,6 +434,63 @@ export default class StatusPageSubscriber extends BaseModel {
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageSubscriber,
|
||||
Permission.Public,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSubscriber,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditStatusPageSubscriber,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Is Subscription Confirmed",
|
||||
description:
|
||||
"Has subscriber confirmed their subscription? (for example, by clicking on a confirmation link in an email)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
})
|
||||
public isSubscriptionConfirmed?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageSubscriber,
|
||||
],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscription Confirmation Token",
|
||||
description:
|
||||
"Token used to confirm subscription. This is a random token that is sent to the subscriber's email address to confirm their subscription.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriptionConfirmationToken?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import IncidentSeverity from "./IncidentSeverity";
|
||||
import AlertSeverity from "./AlertSeverity";
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import UserCall from "./UserCall";
|
||||
@@ -450,6 +451,55 @@ class UserNotificationRule extends BaseModel {
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentSeverityId?: ObjectID = undefined;
|
||||
|
||||
// alert severity.
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertSeverityId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: AlertSeverity,
|
||||
title: "Alert Severity",
|
||||
description:
|
||||
"Relation to Alert Severity Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return AlertSeverity;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertSeverityId" })
|
||||
public alertSeverity?: AlertSeverity = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert Severity ID",
|
||||
description: "ID of Alert Severity in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertSeverityId?: ObjectID = undefined;
|
||||
}
|
||||
|
||||
export default UserNotificationRule;
|
||||
|
||||
@@ -28,6 +28,7 @@ import Permission from "../../Types/Permission";
|
||||
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
|
||||
import UserNotificationExecutionStatus from "../../Types/UserNotification/UserNotificationExecutionStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import Alert from "./Alert";
|
||||
|
||||
@EnableDocumentation()
|
||||
@TenantColumn("projectId")
|
||||
@@ -368,16 +369,62 @@ export default class UserOnCallLog extends BaseModel {
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Triggered By Incident ID",
|
||||
required: false,
|
||||
description:
|
||||
"ID of the incident which triggered this on-call escalation policy.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByIncidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "triggeredByAlertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Triggered By Alert",
|
||||
description: "Relation to Alert which triggered this on-call duty policy.",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "triggeredByAlertId" })
|
||||
public triggeredByAlert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Triggered By Alert ID",
|
||||
required: false,
|
||||
description:
|
||||
"ID of the Alert which triggered this on-call escalation policy.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByAlertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicyExecutionLog from "./OnCallDutyPolicyExecutionLog";
|
||||
@@ -325,18 +326,64 @@ export default class UserOnCallLogTimeline extends BaseModel {
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of your OneUptime Incident in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByIncidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "triggeredByAlertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Relation to Alert Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "triggeredByAlertId" })
|
||||
public triggeredByAlert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of your OneUptime Alert in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public triggeredByAlertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [Permission.CurrentUser],
|
||||
|
||||
461
Common/Models/DatabaseModels/WorkspaceNotificationRule.ts
Normal file
461
Common/Models/DatabaseModels/WorkspaceNotificationRule.ts
Normal file
@@ -0,0 +1,461 @@
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import AllowAccessIfSubscriptionIsUnpaid from "../../Types/Database/AccessControl/AllowAccessIfSubscriptionIsUnpaid";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
import BaseNotificationRule from "../../Types/Workspace/NotificationRules/BaseNotificationRule";
|
||||
import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
|
||||
import Permission from "../../Types/Permission";
|
||||
|
||||
@TenantColumn("projectId")
|
||||
@AllowAccessIfSubscriptionIsUnpaid()
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.DeleteWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/workspace-notification-rule"))
|
||||
@Entity({
|
||||
name: "WorkspaceNotificationRule",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "WorkspaceNotificationRule",
|
||||
singularName: "Workspace Notification Rule",
|
||||
pluralName: "Workspace Notification Rules",
|
||||
icon: IconProp.Logs,
|
||||
tableDescription: "Notification Rule for Third Party Workspaces",
|
||||
})
|
||||
class WorkspaceNotificationRule extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Rule Name",
|
||||
description: "Name of the Notification Rule",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public name?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Rule Description",
|
||||
description: "Description of the Notification Rule",
|
||||
required: false,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: true,
|
||||
})
|
||||
public description?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Notification Rules",
|
||||
description: "Notification Rules for the Workspace",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.JSON,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public notificationRule?: BaseNotificationRule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Event Type",
|
||||
description:
|
||||
"Event Type for the Workspace like Incident Created, Monitor Status Updated, etc.",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.ShortText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public eventType?: NotificationRuleEventType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Type",
|
||||
description: "Type of Workspace - slack, microsoft teams etc.",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceType?: WorkspaceType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
// deleted by userId
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateWorkspaceNotificationRule,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationRule,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditWorkspaceNotificationRule,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
}
|
||||
|
||||
export default WorkspaceNotificationRule;
|
||||
379
Common/Models/DatabaseModels/WorkspaceProjectAuthToken.ts
Normal file
379
Common/Models/DatabaseModels/WorkspaceProjectAuthToken.ts
Normal file
@@ -0,0 +1,379 @@
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import AllowAccessIfSubscriptionIsUnpaid from "../../Types/Database/AccessControl/AllowAccessIfSubscriptionIsUnpaid";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
import Permission from "../../Types/Permission";
|
||||
|
||||
export interface MiscData {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface SlackMiscData extends MiscData {
|
||||
teamId: string;
|
||||
teamName: string;
|
||||
botUserId: string;
|
||||
}
|
||||
|
||||
@TenantColumn("projectId")
|
||||
@AllowAccessIfSubscriptionIsUnpaid()
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
delete: [Permission.ProjectOwner, Permission.ProjectAdmin],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/workspace-project-auth-token"))
|
||||
@Entity({
|
||||
name: "WorkspaceProjectAuthToken",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "WorkspaceProjectAuthToken",
|
||||
singularName: "Workspace Project Auth Token",
|
||||
pluralName: "Workspace Project Auth Tokens",
|
||||
icon: IconProp.Lock,
|
||||
tableDescription: "Third Party Auth Token for the Project",
|
||||
})
|
||||
class WorkspaceProjectAuthToken extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Auth Token",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public authToken?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Type",
|
||||
description: "Type of Workspace - slack, microsoft teams etc.",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceType?: WorkspaceType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Project ID in Workspace",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceProjectId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Misc Data",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.JSON,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public miscData?: MiscData = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
}
|
||||
|
||||
export default WorkspaceProjectAuthToken;
|
||||
230
Common/Models/DatabaseModels/WorkspaceSetting.ts
Normal file
230
Common/Models/DatabaseModels/WorkspaceSetting.ts
Normal file
@@ -0,0 +1,230 @@
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import AllowAccessIfSubscriptionIsUnpaid from "../../Types/Database/AccessControl/AllowAccessIfSubscriptionIsUnpaid";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
|
||||
export interface Settings {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
export interface SlackSettings extends Settings {
|
||||
teamId: string;
|
||||
teamName: string;
|
||||
botUserId: string;
|
||||
}
|
||||
|
||||
@TenantColumn("projectId")
|
||||
@AllowAccessIfSubscriptionIsUnpaid()
|
||||
@TableAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/workspace-setting"))
|
||||
@Entity({
|
||||
name: "WorkspaceSetting",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "WorkspaceSetting",
|
||||
singularName: "Workspace Setting",
|
||||
pluralName: "Workspace Settings",
|
||||
icon: IconProp.Settings,
|
||||
tableDescription: "Settings for Third Party Workspaces",
|
||||
})
|
||||
class WorkspaceSetting extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Settings",
|
||||
description: "Settings for the Workspace",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.JSON,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public settings?: SlackSettings = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Type",
|
||||
description: "Type of Workspace - slack, microsoft teams etc.",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceType?: WorkspaceType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
// deleted by userId
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
}
|
||||
|
||||
export default WorkspaceSetting;
|
||||
312
Common/Models/DatabaseModels/WorkspaceUserAuthToken.ts
Normal file
312
Common/Models/DatabaseModels/WorkspaceUserAuthToken.ts
Normal file
@@ -0,0 +1,312 @@
|
||||
import Project from "./Project";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import AllowAccessIfSubscriptionIsUnpaid from "../../Types/Database/AccessControl/AllowAccessIfSubscriptionIsUnpaid";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import CurrentUserCanAccessRecordBy from "../../Types/Database/CurrentUserCanAccessRecordBy";
|
||||
import TableColumn from "../../Types/Database/TableColumn";
|
||||
import TableColumnType from "../../Types/Database/TableColumnType";
|
||||
import TableMetadata from "../../Types/Database/TableMetadata";
|
||||
import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
|
||||
export interface MiscData {
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface SlackMiscData extends MiscData {
|
||||
userId: string;
|
||||
}
|
||||
|
||||
@TenantColumn("projectId")
|
||||
@AllowAccessIfSubscriptionIsUnpaid()
|
||||
@TableAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
delete: [Permission.CurrentUser],
|
||||
update: [Permission.CurrentUser],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/workspace-user-auth-token"))
|
||||
@Entity({
|
||||
name: "WorkspaceUserAuthToken",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "WorkspaceUserAuthToken",
|
||||
singularName: "Workspace User Auth Token",
|
||||
pluralName: "Workspace User Auth Tokens",
|
||||
icon: IconProp.Lock,
|
||||
tableDescription: "Third Party Auth Token for the User",
|
||||
})
|
||||
@CurrentUserCanAccessRecordBy("userId")
|
||||
class WorkspaceUserAuthToken extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "projectId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Project,
|
||||
title: "Project",
|
||||
description: "Relation to Project Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Project;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Project ID",
|
||||
description: "ID of your OneUptime Project in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public projectId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Auth Token",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public authToken?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "User ID in Service",
|
||||
description: "User ID in the Workspace",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceUserId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Workspace Type",
|
||||
description: "Type of Workspace - slack, microsoft teams etc.",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.LongText,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public workspaceType?: WorkspaceType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
title: "Misc Data",
|
||||
required: true,
|
||||
unique: false,
|
||||
type: TableColumnType.JSON,
|
||||
canReadOnRelationQuery: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.JSON,
|
||||
unique: false,
|
||||
nullable: false,
|
||||
})
|
||||
public miscData?: MiscData = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "user",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "Relation to User who this email belongs to",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "User ID",
|
||||
description: "User ID who this email belongs to",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
@Index()
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "createdByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "Created by User",
|
||||
description:
|
||||
"Relation to User who created this object (if this object was created by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "createdByUserId" })
|
||||
public createdByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.CurrentUser],
|
||||
read: [Permission.CurrentUser],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Created by User ID",
|
||||
description:
|
||||
"User ID who created this object (if this object was created by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public createdByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
description:
|
||||
"Relation to User who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
cascade: false,
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "SET NULL",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "deletedByUserId" })
|
||||
public deletedByUser?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
title: "Deleted by User ID",
|
||||
description:
|
||||
"User ID who deleted this object (if this object was deleted by a User)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
}
|
||||
|
||||
export default WorkspaceUserAuthToken;
|
||||
@@ -131,6 +131,30 @@ export default class BaseAPI<
|
||||
},
|
||||
);
|
||||
|
||||
router.post(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/:id/update-item`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
try {
|
||||
await this.updateItem(req, res);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
router.get(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/:id/update-item`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
try {
|
||||
await this.updateItem(req, res);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Delete
|
||||
router.delete(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/:id`,
|
||||
@@ -144,6 +168,30 @@ export default class BaseAPI<
|
||||
},
|
||||
);
|
||||
|
||||
router.post(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/:id/delete-item`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
try {
|
||||
await this.deleteItem(req, res);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
router.get(
|
||||
`${new this.entityType().getCrudApiPath()?.toString()}/:id/delete-item`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
try {
|
||||
await this.deleteItem(req, res);
|
||||
} catch (err) {
|
||||
next(err);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
this.router = router;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import {
|
||||
import Response from "../Utils/Response";
|
||||
import BaseAPI from "./BaseAPI";
|
||||
import BaseModel from "Common/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
||||
import SubscriptionStatus from "Common/Types/Billing/SubscriptionStatus";
|
||||
import BadDataException from "Common/Types/Exception/BadDataException";
|
||||
import { JSONObject } from "Common/Types/JSON";
|
||||
import Permission, { UserPermission } from "Common/Types/Permission";
|
||||
@@ -127,37 +126,8 @@ export default class UserAPI extends BaseAPI<
|
||||
},
|
||||
});
|
||||
|
||||
// refresh subscription status.
|
||||
const subscriptionState: SubscriptionStatus =
|
||||
await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderSubscriptionId as string,
|
||||
);
|
||||
|
||||
const meteredSubscriptionState: SubscriptionStatus =
|
||||
await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderMeteredSubscriptionId as string,
|
||||
);
|
||||
|
||||
// if subscription is cancelled, create a new subscription and update project.
|
||||
|
||||
if (
|
||||
meteredSubscriptionState === SubscriptionStatus.Canceled ||
|
||||
subscriptionState === SubscriptionStatus.Canceled
|
||||
) {
|
||||
await ProjectService.reactiveSubscription(project.id!);
|
||||
}
|
||||
|
||||
await ProjectService.updateOneById({
|
||||
id: project.id!,
|
||||
data: {
|
||||
paymentProviderSubscriptionStatus: subscriptionState,
|
||||
paymentProviderMeteredSubscriptionStatus:
|
||||
meteredSubscriptionState,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
ignoreHooks: true,
|
||||
},
|
||||
await BillingInvoiceService.refreshSubscriptionStatus({
|
||||
projectId: project.id!,
|
||||
});
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
|
||||
368
Common/Server/API/SlackAPI.ts
Normal file
368
Common/Server/API/SlackAPI.ts
Normal file
@@ -0,0 +1,368 @@
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
} from "../Utils/Express";
|
||||
import Response from "../Utils/Response";
|
||||
import SlackAuthorization from "../Middleware/SlackAuthorization";
|
||||
import BadRequestException from "../../Types/Exception/BadRequestException";
|
||||
import logger from "../Utils/Logger";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import BadDataException from "../../Types/Exception/BadDataException";
|
||||
import {
|
||||
AppApiClientUrl,
|
||||
DashboardClientUrl,
|
||||
SlackAppClientId,
|
||||
SlackAppClientSecret,
|
||||
} from "../EnvironmentConfig";
|
||||
import SlackAppManifest from "../Utils/Workspace/Slack/app-manifest.json";
|
||||
import URL from "../../Types/API/URL";
|
||||
import HTTPErrorResponse from "../../Types/API/HTTPErrorResponse";
|
||||
import HTTPResponse from "../../Types/API/HTTPResponse";
|
||||
import API from "../../Utils/API";
|
||||
import WorkspaceProjectAuthTokenService from "../Services/WorkspaceProjectAuthTokenService";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import WorkspaceUserAuthTokenService from "../Services/WorkspaceUserAuthTokenService";
|
||||
import WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
|
||||
export default class SlackAPI {
|
||||
public getRouter(): ExpressRouter {
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
router.get(
|
||||
"/slack/app-manifest",
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
// return app manifest for slack app
|
||||
return Response.sendJsonObjectResponse(req, res, SlackAppManifest);
|
||||
},
|
||||
);
|
||||
|
||||
router.get(
|
||||
"/slack/auth/:projectId/:userId",
|
||||
async (req: ExpressRequest, res: ExpressResponse) => {
|
||||
if (!SlackAppClientId) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException("Slack App Client ID is not set"),
|
||||
);
|
||||
}
|
||||
|
||||
if (!SlackAppClientSecret) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException("Slack App Client Secret is not set"),
|
||||
);
|
||||
}
|
||||
|
||||
const projectId: string | undefined =
|
||||
req.params["projectId"]?.toString();
|
||||
const userId: string | undefined = req.params["userId"]?.toString();
|
||||
|
||||
if (!projectId) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException("Invalid ProjectID in request"),
|
||||
);
|
||||
}
|
||||
|
||||
if (!userId) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException("Invalid UserID in request"),
|
||||
);
|
||||
}
|
||||
|
||||
// if there's an error query param.
|
||||
const error: string | undefined = req.query["error"]?.toString();
|
||||
|
||||
const slackIntegrationPageUrl: URL = URL.fromString(
|
||||
DashboardClientUrl.toString() +
|
||||
`/${projectId.toString()}/settings/slack-integration`,
|
||||
);
|
||||
|
||||
if (error) {
|
||||
return Response.redirect(
|
||||
req,
|
||||
res,
|
||||
slackIntegrationPageUrl.addQueryParam("error", error),
|
||||
);
|
||||
}
|
||||
|
||||
// slack returns the code on successful auth.
|
||||
const code: string | undefined = req.query["code"]?.toString();
|
||||
|
||||
if (!code) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Invalid request"),
|
||||
);
|
||||
}
|
||||
|
||||
// get access token from slack api.
|
||||
|
||||
const redirectUri: URL = URL.fromString(
|
||||
`${AppApiClientUrl.toString()}/slack/auth/${projectId}/${userId}`,
|
||||
);
|
||||
|
||||
const requestBody: JSONObject = {
|
||||
code: code,
|
||||
client_id: SlackAppClientId,
|
||||
client_secret: SlackAppClientSecret,
|
||||
redirect_uri: redirectUri.toString(),
|
||||
};
|
||||
|
||||
logger.debug("Slack Auth Request Body: ");
|
||||
logger.debug(requestBody);
|
||||
|
||||
// send the request to slack api to get the access token https://slack.com/api/oauth.v2.access
|
||||
|
||||
const response: HTTPErrorResponse | HTTPResponse<JSONObject> =
|
||||
await API.post(
|
||||
URL.fromString("https://slack.com/api/oauth.v2.access"),
|
||||
requestBody,
|
||||
{
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
);
|
||||
|
||||
if (response instanceof HTTPErrorResponse) {
|
||||
throw response;
|
||||
}
|
||||
|
||||
const responseBody: JSONObject = response.data;
|
||||
|
||||
logger.debug("Slack Auth Request Body: ");
|
||||
logger.debug(responseBody);
|
||||
|
||||
let slackTeamId: string | undefined = undefined;
|
||||
let slackBotAccessToken: string | undefined = undefined;
|
||||
let slackUserId: string | undefined = undefined;
|
||||
let slackTeamName: string | undefined = undefined;
|
||||
let botUserId: string | undefined = undefined;
|
||||
let slackUserAccessToken: string | undefined = undefined;
|
||||
|
||||
// ReponseBody is in this format.
|
||||
// {
|
||||
// "ok": true,
|
||||
// "access_token": "sample-token",
|
||||
// "token_type": "bot",
|
||||
// "scope": "commands,incoming-webhook",
|
||||
// "bot_user_id": "U0KRQLJ9H",
|
||||
// "app_id": "A0KRD7HC3",
|
||||
// "team": {
|
||||
// "name": "Slack Pickleball Team",
|
||||
// "id": "T9TK3CUKW"
|
||||
// },
|
||||
// "enterprise": {
|
||||
// "name": "slack-pickleball",
|
||||
// "id": "E12345678"
|
||||
// },
|
||||
// "authed_user": {
|
||||
// "id": "U1234",
|
||||
// "scope": "chat:write",
|
||||
// "access_token": "sample-token",
|
||||
// "token_type": "user"
|
||||
// }
|
||||
// }
|
||||
|
||||
if (responseBody["ok"] !== true) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Invalid request"),
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
responseBody["team"] &&
|
||||
(responseBody["team"] as JSONObject)["id"]
|
||||
) {
|
||||
slackTeamId = (responseBody["team"] as JSONObject)["id"]?.toString();
|
||||
}
|
||||
|
||||
if (responseBody["access_token"]) {
|
||||
slackBotAccessToken = responseBody["access_token"]?.toString();
|
||||
}
|
||||
|
||||
if (
|
||||
responseBody["authed_user"] &&
|
||||
(responseBody["authed_user"] as JSONObject)["id"]
|
||||
) {
|
||||
slackUserId = (responseBody["authed_user"] as JSONObject)[
|
||||
"id"
|
||||
]?.toString();
|
||||
}
|
||||
|
||||
if (
|
||||
responseBody["authed_user"] &&
|
||||
(responseBody["authed_user"] as JSONObject)["access_token"]
|
||||
) {
|
||||
slackUserAccessToken = (responseBody["authed_user"] as JSONObject)[
|
||||
"access_token"
|
||||
]?.toString();
|
||||
}
|
||||
|
||||
if (
|
||||
responseBody["team"] &&
|
||||
(responseBody["team"] as JSONObject)["name"]
|
||||
) {
|
||||
slackTeamName = (responseBody["team"] as JSONObject)[
|
||||
"name"
|
||||
]?.toString();
|
||||
}
|
||||
|
||||
if (responseBody["bot_user_id"]) {
|
||||
botUserId = responseBody["bot_user_id"]?.toString();
|
||||
}
|
||||
|
||||
await WorkspaceProjectAuthTokenService.refreshAuthToken({
|
||||
projectId: new ObjectID(projectId),
|
||||
workspaceType: WorkspaceType.Slack,
|
||||
authToken: slackBotAccessToken || "",
|
||||
workspaceProjectId: slackTeamId || "",
|
||||
miscData: {
|
||||
teamId: slackTeamId || "",
|
||||
teamName: slackTeamName || "",
|
||||
botUserId: botUserId || "",
|
||||
},
|
||||
});
|
||||
|
||||
await WorkspaceUserAuthTokenService.refreshAuthToken({
|
||||
projectId: new ObjectID(projectId),
|
||||
userId: new ObjectID(userId),
|
||||
workspaceType: WorkspaceType.Slack,
|
||||
authToken: slackUserAccessToken || "",
|
||||
workspaceUserId: slackUserId || "",
|
||||
miscData: {
|
||||
userId: slackUserId || "",
|
||||
},
|
||||
});
|
||||
|
||||
// return back to dashboard after successful auth.
|
||||
Response.redirect(req, res, slackIntegrationPageUrl);
|
||||
},
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/slack/interactive",
|
||||
SlackAuthorization.isAuthorizedSlackRequest,
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
response_action: "clear",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// options load endpoint.
|
||||
|
||||
router.post(
|
||||
"/slack/options-load",
|
||||
SlackAuthorization.isAuthorizedSlackRequest,
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
response_action: "clear",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/slack/command",
|
||||
SlackAuthorization.isAuthorizedSlackRequest,
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
response_action: "clear",
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
router.post(
|
||||
"/slack/events",
|
||||
SlackAuthorization.isAuthorizedSlackRequest,
|
||||
(req: ExpressRequest, res: ExpressResponse) => {
|
||||
// respond to slack challenge
|
||||
|
||||
const body: any = req.body;
|
||||
|
||||
if (body.challenge) {
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
challenge: body.challenge,
|
||||
});
|
||||
}
|
||||
|
||||
// if event is "create-incident" then show the incident create modal with title and description and add a button to submit the form.
|
||||
|
||||
if (body.event && body.event.type === "create-incident") {
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
type: "modal",
|
||||
title: {
|
||||
type: "plain_text",
|
||||
text: "Create Incident",
|
||||
},
|
||||
blocks: [
|
||||
{
|
||||
type: "input",
|
||||
block_id: "title",
|
||||
element: {
|
||||
type: "plain_text_input",
|
||||
action_id: "title",
|
||||
placeholder: {
|
||||
type: "plain_text",
|
||||
text: "Incident Title",
|
||||
},
|
||||
},
|
||||
label: {
|
||||
type: "plain_text",
|
||||
text: "Title",
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "input",
|
||||
block_id: "description",
|
||||
element: {
|
||||
type: "plain_text_input",
|
||||
action_id: "description",
|
||||
placeholder: {
|
||||
type: "plain_text",
|
||||
text: "Incident Description",
|
||||
},
|
||||
},
|
||||
label: {
|
||||
type: "plain_text",
|
||||
text: "Description",
|
||||
},
|
||||
},
|
||||
// button
|
||||
{
|
||||
type: "actions",
|
||||
elements: [
|
||||
{
|
||||
type: "button",
|
||||
text: {
|
||||
type: "plain_text",
|
||||
text: "Submit",
|
||||
},
|
||||
style: "primary",
|
||||
value: "submit",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadRequestException("Invalid request"),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
return router;
|
||||
}
|
||||
}
|
||||
@@ -74,6 +74,8 @@ import StatusPageResource from "Common/Models/DatabaseModels/StatusPageResource"
|
||||
import StatusPageSSO from "Common/Models/DatabaseModels/StatusPageSso";
|
||||
import StatusPageSubscriber from "Common/Models/DatabaseModels/StatusPageSubscriber";
|
||||
import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
|
||||
import StatusPageResourceUptimeUtil from "../../Utils/StatusPage/ResourceUptime";
|
||||
import MonitorService from "../Services/MonitorService";
|
||||
|
||||
export default class StatusPageAPI extends BaseAPI<
|
||||
StatusPage,
|
||||
@@ -82,6 +84,66 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
public constructor() {
|
||||
super(StatusPage, StatusPageService);
|
||||
|
||||
// confirm subscription api
|
||||
this.router.get(
|
||||
`${new this.entityType()
|
||||
.getCrudApiPath()
|
||||
?.toString()}/confirm-subscription/:statusPageSubscriberId`,
|
||||
async (req: ExpressRequest, res: ExpressResponse) => {
|
||||
const token: string = req.query["verification-token"] as string;
|
||||
|
||||
const statusPageSubscriberId: ObjectID = new ObjectID(
|
||||
req.params["statusPageSubscriberId"] as string,
|
||||
);
|
||||
|
||||
const subscriber: StatusPageSubscriber | null =
|
||||
await StatusPageSubscriberService.findOneBy({
|
||||
query: {
|
||||
_id: statusPageSubscriberId,
|
||||
subscriptionConfirmationToken: token,
|
||||
},
|
||||
select: {
|
||||
isSubscriptionConfirmed: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!subscriber) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new NotFoundException(
|
||||
"Subscriber not found or confirmation token is invalid",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// check if subscription confirmed already.
|
||||
|
||||
if (subscriber.isSubscriptionConfirmed) {
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
}
|
||||
|
||||
await StatusPageSubscriberService.updateOneById({
|
||||
id: statusPageSubscriberId,
|
||||
data: {
|
||||
isSubscriptionConfirmed: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
await StatusPageSubscriberService.sendYouHaveSubscribedEmail({
|
||||
subscriberId: statusPageSubscriberId,
|
||||
});
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
},
|
||||
);
|
||||
|
||||
// CNAME verification api
|
||||
this.router.get(
|
||||
`${new this.entityType()
|
||||
@@ -457,6 +519,128 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
this.router.post(
|
||||
`${new this.entityType()
|
||||
.getCrudApiPath()
|
||||
?.toString()}/overview/:statusPageId/uptime-percent`,
|
||||
UserMiddleware.getUserMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
||||
try {
|
||||
|
||||
// This reosurce ID can be of a status page resource OR a status page group.
|
||||
const statusPageResourceId: ObjectID = new ObjectID(
|
||||
req.params["statusPageResourceId"] as string,
|
||||
);
|
||||
|
||||
const statusPageId: ObjectID = new ObjectID(
|
||||
req.params["statusPageId"] as string,
|
||||
);
|
||||
|
||||
if(!statusPageId || !statusPageResourceId){
|
||||
throw new BadDataException("Status Page or Resource not found");
|
||||
}
|
||||
|
||||
// get start and end date from request body.
|
||||
// if no end date is provided then it will be current date.
|
||||
// if no start date is provided then it will be 14 days ago from end date.
|
||||
|
||||
let startDate: Date = OneUptimeDate.getSomeDaysAgo(14)
|
||||
let endDate: Date = OneUptimeDate.getCurrentDate();
|
||||
|
||||
if(req.body["startDate"]){
|
||||
startDate = OneUptimeDate.fromString(req.body["startDate"] as string);
|
||||
}
|
||||
|
||||
if(req.body["endDate"]){
|
||||
endDate = OneUptimeDate.fromString(req.body["endDate"] as string);
|
||||
}
|
||||
|
||||
const monitorStatusTimelines: Array<MonitorStatusTimeline> = [];
|
||||
|
||||
|
||||
// get monitor or group.
|
||||
|
||||
// get status page group.
|
||||
|
||||
const monitorsInResource: Array<ObjectID> = [];
|
||||
|
||||
const statusPageGroup: StatusPageGroup | null = await StatusPageGroupService.findOneBy({
|
||||
query: {
|
||||
_id: statusPageResourceId,
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
statusPageId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
if(statusPageGroup){
|
||||
// get all monitors in group.
|
||||
const groupResources: Array<StatusPageResource> = await StatusPageResourceService.findBy({
|
||||
query: {
|
||||
statusPageGroupId: statusPageResourceId,
|
||||
},
|
||||
select: {
|
||||
monitorId: true,
|
||||
monitorGroupId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
});
|
||||
|
||||
monitorsInGroup.push(...groupResources.map((resource: StatusPageResource) => {
|
||||
return resource.monitorId!;
|
||||
}).filter((id: ObjectID) => {
|
||||
return Boolean(id);
|
||||
}));
|
||||
|
||||
|
||||
}
|
||||
|
||||
const monitor: Monitor | null = await MonitorService.findOneBy({
|
||||
query: {
|
||||
_id: statusPageResourceId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
name: true,
|
||||
monitorGroupId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
const uptimePercent: number | null = null;
|
||||
StatusPageResourceUptimeUtil.calculateAvgUptimePercentOfStatusPageGroup(
|
||||
{
|
||||
statusPageGroup: data.group,
|
||||
monitorStatusTimelines: monitorStatusTimelines,
|
||||
precision:
|
||||
data.group.uptimePercentPrecision ||
|
||||
UptimePrecision.ONE_DECIMAL,
|
||||
downtimeMonitorStatuses:
|
||||
statusPage?.downtimeMonitorStatuses || [],
|
||||
statusPageResources: statusPageResources,
|
||||
monitorsInGroup: monitorsInGroup,
|
||||
},
|
||||
);
|
||||
} catch (err) {
|
||||
|
||||
next(err);
|
||||
|
||||
}
|
||||
});
|
||||
this.router.post(
|
||||
`${new this.entityType()
|
||||
.getCrudApiPath()
|
||||
@@ -1033,7 +1217,18 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
},
|
||||
});
|
||||
|
||||
const overallStatus: MonitorStatus | null =
|
||||
this.getOverallMonitorStatus(
|
||||
statusPageResources,
|
||||
monitorStatuses,
|
||||
monitorGroupCurrentStatuses,
|
||||
);
|
||||
|
||||
const response: JSONObject = {
|
||||
overallStatus: overallStatus
|
||||
? BaseModel.toJSON(overallStatus, MonitorStatus)
|
||||
: null,
|
||||
|
||||
scheduledMaintenanceEventsPublicNotes: BaseModel.toJSONArray(
|
||||
scheduledMaintenanceEventsPublicNotes,
|
||||
ScheduledMaintenancePublicNote,
|
||||
@@ -2224,4 +2419,54 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
|
||||
return response;
|
||||
}
|
||||
|
||||
public getOverallMonitorStatus(
|
||||
statusPageResources: Array<StatusPageResource>,
|
||||
monitorStatuses: Array<MonitorStatus>,
|
||||
monitorGroupCurrentStatuses: Dictionary<ObjectID>,
|
||||
): MonitorStatus | null {
|
||||
let currentStatus: MonitorStatus | null =
|
||||
monitorStatuses.length > 0 && monitorStatuses[0]
|
||||
? monitorStatuses[0]
|
||||
: null;
|
||||
|
||||
const dict: Dictionary<number> = {};
|
||||
|
||||
for (const resource of statusPageResources) {
|
||||
if (resource.monitor?.currentMonitorStatusId) {
|
||||
if (
|
||||
!Object.keys(dict).includes(
|
||||
resource.monitor?.currentMonitorStatusId.toString() || "",
|
||||
)
|
||||
) {
|
||||
dict[resource.monitor?.currentMonitorStatusId?.toString()] = 1;
|
||||
} else {
|
||||
dict[resource.monitor!.currentMonitorStatusId!.toString()]!++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check status of monitor groups.
|
||||
|
||||
for (const groupId in monitorGroupCurrentStatuses) {
|
||||
const statusId: ObjectID | undefined =
|
||||
monitorGroupCurrentStatuses[groupId];
|
||||
|
||||
if (statusId) {
|
||||
if (!Object.keys(dict).includes(statusId.toString() || "")) {
|
||||
dict[statusId.toString()] = 1;
|
||||
} else {
|
||||
dict[statusId.toString()]!++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const monitorStatus of monitorStatuses) {
|
||||
if (monitorStatus._id && dict[monitorStatus._id]) {
|
||||
currentStatus = monitorStatus;
|
||||
}
|
||||
}
|
||||
|
||||
return currentStatus;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ export default class UserNotificationLogTimelineAPI extends BaseAPI<
|
||||
_id: true,
|
||||
projectId: true,
|
||||
triggeredByIncidentId: true,
|
||||
triggeredByAlertId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -115,6 +116,7 @@ export default class UserNotificationLogTimelineAPI extends BaseAPI<
|
||||
_id: true,
|
||||
projectId: true,
|
||||
triggeredByIncidentId: true,
|
||||
triggeredByAlertId: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
@@ -147,16 +149,38 @@ export default class UserNotificationLogTimelineAPI extends BaseAPI<
|
||||
const host: Hostname = await DatabaseConfig.getHost();
|
||||
const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
|
||||
|
||||
return Response.redirect(
|
||||
if (timelineItem.triggeredByIncidentId) {
|
||||
return Response.redirect(
|
||||
req,
|
||||
res,
|
||||
new URL(
|
||||
httpProtocol,
|
||||
host,
|
||||
DashboardRoute.addRoute(
|
||||
`/${timelineItem.projectId?.toString()}/incidents/${timelineItem.triggeredByIncidentId!.toString()}`,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (timelineItem.triggeredByAlertId) {
|
||||
return Response.redirect(
|
||||
req,
|
||||
res,
|
||||
new URL(
|
||||
httpProtocol,
|
||||
host,
|
||||
DashboardRoute.addRoute(
|
||||
`/${timelineItem.projectId?.toString()}/alerts/${timelineItem.triggeredByAlertId!.toString()}`,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new URL(
|
||||
httpProtocol,
|
||||
host,
|
||||
DashboardRoute.addRoute(
|
||||
`/${timelineItem.projectId?.toString()}/incidents/${timelineItem.triggeredByIncidentId!.toString()}`,
|
||||
),
|
||||
),
|
||||
new BadDataException("Invalid item Id"),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -30,6 +30,14 @@ export default class DatabaseConfig {
|
||||
return globalConfig.getColumnValue(key);
|
||||
}
|
||||
|
||||
public static async getHomeUrl(): Promise<URL> {
|
||||
const host: Hostname = await DatabaseConfig.getHost();
|
||||
|
||||
const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
|
||||
|
||||
return new URL(httpProtocol, host);
|
||||
}
|
||||
|
||||
public static async getHost(): Promise<Hostname> {
|
||||
return Promise.resolve(new Hostname(process.env["HOST"] || "localhost"));
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ import {
|
||||
AccountsRoute,
|
||||
AdminDashboardRoute,
|
||||
DashboardRoute,
|
||||
AppApiRoute,
|
||||
} from "Common/ServiceRoute";
|
||||
import BillingConfig from "./BillingConfig";
|
||||
import Hostname from "Common/Types/API/Hostname";
|
||||
@@ -181,6 +182,10 @@ export const ShouldRedisTlsEnable: boolean = Boolean(
|
||||
RedisTlsCa || (RedisTlsCert && RedisTlsKey),
|
||||
);
|
||||
|
||||
export const RedisIPFamily: number = process.env["REDIS_IP_FAMILY"]
|
||||
? Number(process.env["REDIS_IP_FAMILY"])
|
||||
: 4;
|
||||
|
||||
export const IsProduction: boolean =
|
||||
process.env["ENVIRONMENT"] === "production";
|
||||
|
||||
@@ -198,6 +203,9 @@ export const AnalyticsHost: string = process.env["ANALYTICS_HOST"] || "";
|
||||
export const DisableAutomaticIncidentCreation: boolean =
|
||||
process.env["DISABLE_AUTOMATIC_INCIDENT_CREATION"] === "true";
|
||||
|
||||
export const DisableAutomaticAlertCreation: boolean =
|
||||
process.env["DISABLE_AUTOMATIC_ALERT_CREATION"] === "true";
|
||||
|
||||
export const ClickhouseHost: Hostname = Hostname.fromString(
|
||||
process.env["CLICKHOUSE_HOST"] || "clickhouse",
|
||||
);
|
||||
@@ -252,6 +260,10 @@ export const WorkflowScriptTimeoutInMS: number = process.env[
|
||||
? parseInt(process.env["WORKFLOW_SCRIPT_TIMEOUT_IN_MS"].toString())
|
||||
: 5000;
|
||||
|
||||
export const WorkflowTimeoutInMs: number = process.env["WORKFLOW_TIMEOUT_IN_MS"]
|
||||
? parseInt(process.env["WORKFLOW_TIMEOUT_IN_MS"].toString())
|
||||
: 5000;
|
||||
|
||||
export const AllowedActiveMonitorCountInFreePlan: number = process.env[
|
||||
"ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN"
|
||||
]
|
||||
@@ -272,8 +284,19 @@ export const AllowedSubscribersCountInFreePlan: number = process.env[
|
||||
? parseInt(process.env["ALLOWED_SUBSCRIBERS_COUNT_IN_FREE_PLAN"].toString())
|
||||
: 100;
|
||||
|
||||
export const NotificationWebhookOnCreateUser: string =
|
||||
process.env["NOTIFICATION_WEBHOOK_ON_CREATED_USER"] || "";
|
||||
export const NotificationSlackWebhookOnCreateUser: string =
|
||||
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_USER"] || "";
|
||||
|
||||
export const NotificationSlackWebhookOnCreateProject: string =
|
||||
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_CREATED_PROJECT"] || "";
|
||||
|
||||
// notification delete project
|
||||
export const NotificationSlackWebhookOnDeleteProject: string =
|
||||
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_DELETED_PROJECT"] || "";
|
||||
|
||||
// notification subscripton update.
|
||||
export const NotificationSlackWebhookOnSubscriptionUpdate: string =
|
||||
process.env["NOTIFICATION_SLACK_WEBHOOK_ON_SUBSCRIPTION_UPDATE"] || "";
|
||||
|
||||
export const AdminDashboardClientURL: URL = new URL(
|
||||
HttpProtocol,
|
||||
@@ -281,6 +304,8 @@ export const AdminDashboardClientURL: URL = new URL(
|
||||
AdminDashboardRoute,
|
||||
);
|
||||
|
||||
export const AppApiClientUrl: URL = new URL(HttpProtocol, Host, AppApiRoute);
|
||||
|
||||
export const DashboardClientUrl: URL = new URL(
|
||||
HttpProtocol,
|
||||
Host,
|
||||
@@ -295,3 +320,10 @@ export const AccountsClientUrl: URL = new URL(
|
||||
|
||||
export const DisableTelemetry: boolean =
|
||||
process.env["DISABLE_TELEMETRY"] === "true";
|
||||
|
||||
export const SlackAppClientId: string | null =
|
||||
process.env["SLACK_APP_CLIENT_ID"] || null;
|
||||
export const SlackAppClientSecret: string | null =
|
||||
process.env["SLACK_APP_CLIENT_SECRET"] || null;
|
||||
export const SlackAppSigningSecret: string | null =
|
||||
process.env["SLACK_APP_SIGNING_SECRET"] || null;
|
||||
|
||||
@@ -11,13 +11,17 @@ import {
|
||||
ClickhouseUsername,
|
||||
ShouldClickhouseSslEnable,
|
||||
} from "../EnvironmentConfig";
|
||||
import Hostname from "../../Types/API/Hostname";
|
||||
|
||||
export type ClickHouseClientConfigOptions = NodeClickHouseClientConfigOptions;
|
||||
|
||||
const hostProtocol: string = ClickHouseIsHostHttps ? "https" : "http";
|
||||
|
||||
const clickhouseHost: Hostname = ClickhouseHost || new Hostname("clickhouse");
|
||||
const clickhousePort: string = (ClickhousePort || 8123).toString();
|
||||
|
||||
const options: ClickHouseClientConfigOptions = {
|
||||
url: `${hostProtocol}://${ClickhouseHost.toString()}:${ClickhousePort.toNumber()}`,
|
||||
url: `${hostProtocol}://${clickhouseHost.toString()}:${clickhousePort}`,
|
||||
username: ClickhouseUsername,
|
||||
password: ClickhousePassword,
|
||||
database: ClickhouseDatabase,
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1734435866602 implements MigrationInterface {
|
||||
public name = "MigrationName1734435866602";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "isSubscriptionConfirmed" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "subscriptionConfirmationToken" character varying`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "subscriptionConfirmationToken"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "isSubscriptionConfirmed"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736364478985 implements MigrationInterface {
|
||||
public name = "MigrationName1736364478985";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentLog" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incidentId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "logInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "incidentLogEvent" character varying NOT NULL, CONSTRAINT "PK_947cb9f32cf204561d10d64adeb" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_855797e41af7d35b18a7f3f97b" ON "IncidentLog" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_1eff2f3d075754ef9c16e8b962" ON "IncidentLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" ADD CONSTRAINT "FK_855797e41af7d35b18a7f3f97bd" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" ADD CONSTRAINT "FK_1eff2f3d075754ef9c16e8b962c" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" ADD CONSTRAINT "FK_da6bb8bf63b18a7ddc35cc2901a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" ADD CONSTRAINT "FK_bb1b8b83ffdfc702088b74f2e16" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" DROP CONSTRAINT "FK_bb1b8b83ffdfc702088b74f2e16"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" DROP CONSTRAINT "FK_da6bb8bf63b18a7ddc35cc2901a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" DROP CONSTRAINT "FK_1eff2f3d075754ef9c16e8b962c"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" DROP CONSTRAINT "FK_855797e41af7d35b18a7f3f97bd"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_1eff2f3d075754ef9c16e8b962"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_855797e41af7d35b18a7f3f97b"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentLog"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736364957990 implements MigrationInterface {
|
||||
public name = "MigrationName1736364957990";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "AlertLog" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "logInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "alertLogEvent" character varying NOT NULL, CONSTRAINT "PK_500826238fa54528b0026f55d47" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_d5d56f9ed2c4c72745372a1ac6" ON "AlertLog" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_52bbabed66e4e728441d49478f" ON "AlertLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" ADD CONSTRAINT "FK_d5d56f9ed2c4c72745372a1ac6f" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" ADD CONSTRAINT "FK_52bbabed66e4e728441d49478f8" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" ADD CONSTRAINT "FK_f5f832aad105579e95a09e1ddd0" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" ADD CONSTRAINT "FK_7ca9046915f6de6e7a199588d26" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" DROP CONSTRAINT "FK_7ca9046915f6de6e7a199588d26"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" DROP CONSTRAINT "FK_f5f832aad105579e95a09e1ddd0"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" DROP CONSTRAINT "FK_52bbabed66e4e728441d49478f8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" DROP CONSTRAINT "FK_d5d56f9ed2c4c72745372a1ac6f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_52bbabed66e4e728441d49478f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_d5d56f9ed2c4c72745372a1ac6"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "AlertLog"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736365532085 implements MigrationInterface {
|
||||
public name = "MigrationName1736365532085";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "ScheduledMaintenanceLog" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "scheduledMaintenanceId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "logInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "scheduledMaintenanceLogEvent" character varying NOT NULL, CONSTRAINT "PK_27b89f28bf48418fabba9a1ea14" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_9239de1ee33f9505c30f255a99" ON "ScheduledMaintenanceLog" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_58e403ba261dfa94addb5f04d3" ON "ScheduledMaintenanceLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" ADD CONSTRAINT "FK_9239de1ee33f9505c30f255a994" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" ADD CONSTRAINT "FK_58e403ba261dfa94addb5f04d36" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" ADD CONSTRAINT "FK_9152528e4f7f59adaba3e9bc41f" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" ADD CONSTRAINT "FK_a957f435d1504f41808f20a2c45" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" DROP CONSTRAINT "FK_a957f435d1504f41808f20a2c45"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" DROP CONSTRAINT "FK_9152528e4f7f59adaba3e9bc41f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" DROP CONSTRAINT "FK_58e403ba261dfa94addb5f04d36"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" DROP CONSTRAINT "FK_9239de1ee33f9505c30f255a994"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_58e403ba261dfa94addb5f04d3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_9239de1ee33f9505c30f255a99"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "ScheduledMaintenanceLog"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736675947746 implements MigrationInterface {
|
||||
public name = "MigrationName1736675947746";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "incidentNumber" integer`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_0eca9ce7d12a4c472386dfc781" ON "Incident" ("incidentNumber") `,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_0eca9ce7d12a4c472386dfc781"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "incidentNumber"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736703138918 implements MigrationInterface {
|
||||
public name = "MigrationName1736703138918";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" ADD "incidentLogSeverity" character varying NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" ADD "alertLogSeverity" character varying NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" ADD "scheduledMaintenanceLogSeverity" character varying NOT NULL`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceLog" DROP COLUMN "scheduledMaintenanceLogSeverity"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertLog" DROP COLUMN "alertLogSeverity"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentLog" DROP COLUMN "incidentLogSeverity"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736780194077 implements MigrationInterface {
|
||||
public name = "MigrationName1736780194077";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "IncidentFeed" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "incidentId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "feedInfoInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "incidentFeedEventType" character varying NOT NULL, "displayColor" character varying(7) NOT NULL, CONSTRAINT "PK_8188c79d1ed22013205ff324dea" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_32ae47fa45018ecdb7f28c6468" ON "IncidentFeed" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_cf4aea7310bb855873fc40f244" ON "IncidentFeed" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "AlertFeed" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "alertId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "feedInfoInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "alertFeedEventType" character varying NOT NULL, "displayColor" character varying(7) NOT NULL, CONSTRAINT "PK_d5f629abd40a51d58a35423b361" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_f430519f21c327c14c12e4f106" ON "AlertFeed" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_f74177b6675d92243cc0794bd3" ON "AlertFeed" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "ScheduledMaintenanceFeed" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "scheduledMaintenanceId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, "feedInfoInMarkdown" text NOT NULL, "moreInformationInMarkdown" text NOT NULL, "scheduledMaintenanceFeedEventType" character varying NOT NULL, "displayColor" character varying(7) NOT NULL, CONSTRAINT "PK_ced33ccb5551624e432b2df6513" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_416c6ded7f17b15e9a83114740" ON "ScheduledMaintenanceFeed" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_ce3b353bbd3e1695c0ffb2d235" ON "ScheduledMaintenanceFeed" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD CONSTRAINT "FK_32ae47fa45018ecdb7f28c64685" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD CONSTRAINT "FK_cf4aea7310bb855873fc40f2441" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD CONSTRAINT "FK_4458fd00d52521ae4333e74ddbd" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD CONSTRAINT "FK_f1ee9faba64e96f91925247aae3" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD CONSTRAINT "FK_f430519f21c327c14c12e4f1063" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD CONSTRAINT "FK_f74177b6675d92243cc0794bd3f" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD CONSTRAINT "FK_2eda7dbbc78de28f653812b5e3d" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD CONSTRAINT "FK_f0e72673c38f18ed84f0e94a5a1" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD CONSTRAINT "FK_416c6ded7f17b15e9a831147403" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD CONSTRAINT "FK_ce3b353bbd3e1695c0ffb2d2354" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD CONSTRAINT "FK_fc34cf1a5eb488310bbe7c6a46a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD CONSTRAINT "FK_8374052884c5d75f5018c1dc908" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP CONSTRAINT "FK_8374052884c5d75f5018c1dc908"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP CONSTRAINT "FK_fc34cf1a5eb488310bbe7c6a46a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP CONSTRAINT "FK_ce3b353bbd3e1695c0ffb2d2354"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP CONSTRAINT "FK_416c6ded7f17b15e9a831147403"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" DROP CONSTRAINT "FK_f0e72673c38f18ed84f0e94a5a1"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" DROP CONSTRAINT "FK_2eda7dbbc78de28f653812b5e3d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" DROP CONSTRAINT "FK_f74177b6675d92243cc0794bd3f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" DROP CONSTRAINT "FK_f430519f21c327c14c12e4f1063"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP CONSTRAINT "FK_f1ee9faba64e96f91925247aae3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP CONSTRAINT "FK_4458fd00d52521ae4333e74ddbd"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP CONSTRAINT "FK_cf4aea7310bb855873fc40f2441"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP CONSTRAINT "FK_32ae47fa45018ecdb7f28c64685"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_ce3b353bbd3e1695c0ffb2d235"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_416c6ded7f17b15e9a83114740"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "ScheduledMaintenanceFeed"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_f74177b6675d92243cc0794bd3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_f430519f21c327c14c12e4f106"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "AlertFeed"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_cf4aea7310bb855873fc40f244"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_32ae47fa45018ecdb7f28c6468"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "IncidentFeed"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736780194078 implements MigrationInterface {
|
||||
public name = "MigrationName1736780194078";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
// drop tables IncidentLog, AlertLog, ScheduledMaintenanceLog
|
||||
await queryRunner.query(`DROP TABLE "IncidentLog"`);
|
||||
await queryRunner.query(`DROP TABLE "AlertLog"`);
|
||||
await queryRunner.query(`DROP TABLE "ScheduledMaintenanceLog"`);
|
||||
}
|
||||
|
||||
public async down(_queryRunner: QueryRunner): Promise<void> {
|
||||
// do nothing.
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736787495707 implements MigrationInterface {
|
||||
public name = "MigrationName1736787495707";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ALTER COLUMN "moreInformationInMarkdown" DROP NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ALTER COLUMN "moreInformationInMarkdown" DROP NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ALTER COLUMN "moreInformationInMarkdown" DROP NOT NULL`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ALTER COLUMN "moreInformationInMarkdown" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ALTER COLUMN "moreInformationInMarkdown" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ALTER COLUMN "moreInformationInMarkdown" SET NOT NULL`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736787985322 implements MigrationInterface {
|
||||
public name = "MigrationName1736787985322";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Label" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSeverity" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentState" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "MonitorStatus" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ALTER COLUMN "displayColor" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertSeverity" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertState" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceState" ALTER COLUMN "color" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ALTER COLUMN "defaultBarColor" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageHistoryChartBarColorRule" ALTER COLUMN "barColor" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ALTER COLUMN "displayColor" TYPE character varying(10)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ALTER COLUMN "displayColor" TYPE character varying(10)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Label" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentSeverity" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentState" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "MonitorStatus" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ALTER COLUMN "displayColor" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertSeverity" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertState" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceState" ALTER COLUMN "color" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ALTER COLUMN "defaultBarColor" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageHistoryChartBarColorRule" ALTER COLUMN "barColor" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ALTER COLUMN "displayColor" TYPE character varying(7)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ALTER COLUMN "displayColor" TYPE character varying(7)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736788706141 implements MigrationInterface {
|
||||
public name = "MigrationName1736788706141";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "IncidentFeed" ADD "userId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "AlertFeed" ADD "userId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD "userId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD CONSTRAINT "FK_010577090e59583da93c867f541" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD CONSTRAINT "FK_97b19fbc90b6105614cc0cba300" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD CONSTRAINT "FK_541c2b40579cbf342c8850ced2b" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP CONSTRAINT "FK_541c2b40579cbf342c8850ced2b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" DROP CONSTRAINT "FK_97b19fbc90b6105614cc0cba300"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP CONSTRAINT "FK_010577090e59583da93c867f541"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP COLUMN "userId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "AlertFeed" DROP COLUMN "userId"`);
|
||||
await queryRunner.query(`ALTER TABLE "IncidentFeed" DROP COLUMN "userId"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1736856662868 implements MigrationInterface {
|
||||
public name = "MigrationName1736856662868";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "AlertFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" ADD "postedAt" TIMESTAMP WITH TIME ZONE`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceFeed" DROP COLUMN "postedAt"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "AlertFeed" DROP COLUMN "postedAt"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentFeed" DROP COLUMN "postedAt"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1737141420441 implements MigrationInterface {
|
||||
public name = "MigrationName1737141420441";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ADD "triggeredByAlertId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserNotificationRule" ADD "alertSeverityId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ADD "triggeredByAlertId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ADD "triggeredByAlertId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" DROP CONSTRAINT "FK_90119ec7f77fa2efd82261e0448"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ALTER COLUMN "triggeredByIncidentId" DROP NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" DROP CONSTRAINT "FK_eeb0dd05d1dec542c3de5fb5074"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ALTER COLUMN "triggeredByIncidentId" DROP NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" DROP CONSTRAINT "FK_58a44736718a5ec4fe41526289a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ALTER COLUMN "triggeredByIncidentId" DROP NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_30358ab25e4c6c9ad72e74f201" ON "OnCallDutyPolicyExecutionLogTimeline" ("triggeredByAlertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_d73339f6c26fd6ebd0326badcd" ON "UserNotificationRule" ("alertSeverityId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_42d9916277fcbefa0cdd3904c6" ON "UserOnCallLogTimeline" ("triggeredByAlertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ADD CONSTRAINT "FK_90119ec7f77fa2efd82261e0448" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ADD CONSTRAINT "FK_30358ab25e4c6c9ad72e74f201c" FOREIGN KEY ("triggeredByAlertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserNotificationRule" ADD CONSTRAINT "FK_d73339f6c26fd6ebd0326badcd7" FOREIGN KEY ("alertSeverityId") REFERENCES "AlertSeverity"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ADD CONSTRAINT "FK_eeb0dd05d1dec542c3de5fb5074" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ADD CONSTRAINT "FK_0ee3711cdc64957845d9d028c31" FOREIGN KEY ("triggeredByAlertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ADD CONSTRAINT "FK_58a44736718a5ec4fe41526289a" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ADD CONSTRAINT "FK_42d9916277fcbefa0cdd3904c63" FOREIGN KEY ("triggeredByAlertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" DROP CONSTRAINT "FK_42d9916277fcbefa0cdd3904c63"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" DROP CONSTRAINT "FK_58a44736718a5ec4fe41526289a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" DROP CONSTRAINT "FK_0ee3711cdc64957845d9d028c31"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" DROP CONSTRAINT "FK_eeb0dd05d1dec542c3de5fb5074"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserNotificationRule" DROP CONSTRAINT "FK_d73339f6c26fd6ebd0326badcd7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" DROP CONSTRAINT "FK_30358ab25e4c6c9ad72e74f201c"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" DROP CONSTRAINT "FK_90119ec7f77fa2efd82261e0448"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_42d9916277fcbefa0cdd3904c6"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_d73339f6c26fd6ebd0326badcd"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_30358ab25e4c6c9ad72e74f201"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ALTER COLUMN "triggeredByIncidentId" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" ADD CONSTRAINT "FK_58a44736718a5ec4fe41526289a" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ALTER COLUMN "triggeredByIncidentId" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" ADD CONSTRAINT "FK_eeb0dd05d1dec542c3de5fb5074" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ALTER COLUMN "triggeredByIncidentId" SET NOT NULL`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" ADD CONSTRAINT "FK_90119ec7f77fa2efd82261e0448" FOREIGN KEY ("triggeredByIncidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLogTimeline" DROP COLUMN "triggeredByAlertId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserOnCallLog" DROP COLUMN "triggeredByAlertId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "UserNotificationRule" DROP COLUMN "alertSeverityId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyExecutionLogTimeline" DROP COLUMN "triggeredByAlertId"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1737713529424 implements MigrationInterface {
|
||||
public name = "MigrationName1737713529424";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ADD "subscriberEmailNotificationFooterText" character varying(100)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" DROP COLUMN "subscriberEmailNotificationFooterText"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1737715240684 implements MigrationInterface {
|
||||
public name = "MigrationName1737715240684";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" DROP COLUMN "subscriberEmailNotificationFooterText"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ADD "subscriberEmailNotificationFooterText" text`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" DROP COLUMN "subscriberEmailNotificationFooterText"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ADD "subscriberEmailNotificationFooterText" character varying(100)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1737997557974 implements MigrationInterface {
|
||||
public name = "MigrationName1737997557974";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_4d5e62631b2b63aaecb00950ef" ON "MonitorTest" ("isInQueue") `,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_4d5e62631b2b63aaecb00950ef"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739209832500 implements MigrationInterface {
|
||||
public name = "MigrationName1739209832500";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "WorkspaceUserAuthToken" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "authToken" text NOT NULL, "workspaceUserId" character varying(500) NOT NULL, "workspaceType" character varying(500) NOT NULL, "miscData" jsonb NOT NULL, "userId" uuid, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_ae2f1b46b7e26f58a1f4a56b6ea" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_bee888f5782b9585e01f13455f" ON "WorkspaceUserAuthToken" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_4b7c7d1a8b2259df8c790db094" ON "WorkspaceUserAuthToken" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "WorkspaceProjectAuthToken" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "authToken" text NOT NULL, "workspaceType" character varying(500) NOT NULL, "workspaceProjectId" character varying(500) NOT NULL, "miscData" jsonb NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_c0caa6a69da614ee74d8c1291da" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_73f5887268b09c0abccf04ef02" ON "WorkspaceProjectAuthToken" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "WorkspaceSetting" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "settings" jsonb NOT NULL, "workspaceType" character varying(500) NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_eb98d42edd6489fbe1cf3f34515" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c68f38e2b2b061c40209e85bf2" ON "WorkspaceSetting" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "WorkspaceNotificationRule" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "name" character varying(500) NOT NULL, "description" character varying(500), "notificationRule" jsonb NOT NULL, "eventType" character varying NOT NULL, "workspaceType" character varying(500) NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_d1485681c7695ac9841dc52a451" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_349b022afa9a50a597d6c91ec9" ON "WorkspaceNotificationRule" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type":"Recurring","value":{"intervalType":"Day","intervalCount":{"_type":"PositiveNumber","value":1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type":"RestrictionTimes","value":{"restictionType":"None","dayRestrictionTimes":null,"weeklyRestrictionTimes":[]}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_bee888f5782b9585e01f13455fb" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_4b7c7d1a8b2259df8c790db0940" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_ec5cbf4536681fe4bea883c98ea" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" ADD CONSTRAINT "FK_1b2cb71eaf9e665e4556d1b1263" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_73f5887268b09c0abccf04ef02e" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_8aa5804c7a728039564bf5d967d" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" ADD CONSTRAINT "FK_6287095997a16f1cbdd4fb24b61" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_c68f38e2b2b061c40209e85bf22" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_c8fdd61b95bfd0a2ca268b8c602" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" ADD CONSTRAINT "FK_cb3b7931417a4b4ee05d487b614" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_349b022afa9a50a597d6c91ec95" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_55f4e43427fc217ed32cf640a28" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" ADD CONSTRAINT "FK_65ac673d16286be2dcd5229fe24" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_65ac673d16286be2dcd5229fe24"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_55f4e43427fc217ed32cf640a28"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationRule" DROP CONSTRAINT "FK_349b022afa9a50a597d6c91ec95"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_cb3b7931417a4b4ee05d487b614"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_c8fdd61b95bfd0a2ca268b8c602"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceSetting" DROP CONSTRAINT "FK_c68f38e2b2b061c40209e85bf22"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_6287095997a16f1cbdd4fb24b61"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_8aa5804c7a728039564bf5d967d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceProjectAuthToken" DROP CONSTRAINT "FK_73f5887268b09c0abccf04ef02e"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_1b2cb71eaf9e665e4556d1b1263"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_ec5cbf4536681fe4bea883c98ea"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_4b7c7d1a8b2259df8c790db0940"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceUserAuthToken" DROP CONSTRAINT "FK_bee888f5782b9585e01f13455fb"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "restrictionTimes" SET DEFAULT '{"_type": "RestrictionTimes", "value": {"restictionType": "None", "dayRestrictionTimes": null, "weeklyRestrictionTimes": []}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ALTER COLUMN "rotation" SET DEFAULT '{"_type": "Recurring", "value": {"intervalType": "Day", "intervalCount": {"_type": "PositiveNumber", "value": 1}}}'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_349b022afa9a50a597d6c91ec9"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "WorkspaceNotificationRule"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_c68f38e2b2b061c40209e85bf2"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "WorkspaceSetting"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_73f5887268b09c0abccf04ef02"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "WorkspaceProjectAuthToken"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_4b7c7d1a8b2259df8c790db094"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_bee888f5782b9585e01f13455f"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "WorkspaceUserAuthToken"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739210586538 implements MigrationInterface {
|
||||
public name = "MigrationName1739210586538";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "Alert" ADD "alertNumber" integer`);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_aa91b2228a2b35424a3ae93fdc" ON "Alert" ("alertNumber") `,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_aa91b2228a2b35424a3ae93fdc"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "Alert" DROP COLUMN "alertNumber"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739217257089 implements MigrationInterface {
|
||||
public name = "MigrationName1739217257089";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "scheduledMaintenanceNumber" integer`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_207fe82fd8bdc67bbe1aa0ebf8" ON "ScheduledMaintenance" ("scheduledMaintenanceNumber") `,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_207fe82fd8bdc67bbe1aa0ebf8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "scheduledMaintenanceNumber"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739282331053 implements MigrationInterface {
|
||||
public name = "MigrationName1739282331053";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "postUpdatesToSlackChannelId" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" ADD "postUpdatesToSlackChannelId" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "postUpdatesToSlackChannelId" character varying(100)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" DROP COLUMN "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739374537088 implements MigrationInterface {
|
||||
public name = "MigrationName1739374537088";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" RENAME COLUMN "postUpdatesToSlackChannelId" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" RENAME COLUMN "postUpdatesToSlackChannelId" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" RENAME COLUMN "postUpdatesToSlackChannelId" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToSlackChannelId"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1739569321582 implements MigrationInterface {
|
||||
public name = "MigrationName1739569321582";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" RENAME COLUMN "postUpdatesToWorkspaceChannelName" TO "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "postUpdatesToWorkspaceChannels" jsonb`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" ADD "postUpdatesToWorkspaceChannels" jsonb`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "postUpdatesToWorkspaceChannels" jsonb`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "postUpdatesToWorkspaceChannels" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" ADD "postUpdatesToWorkspaceChannels" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "postUpdatesToWorkspaceChannels"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "postUpdatesToWorkspaceChannels" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" RENAME COLUMN "postUpdatesToWorkspaceChannels" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Alert" RENAME COLUMN "postUpdatesToWorkspaceChannels" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" RENAME COLUMN "postUpdatesToWorkspaceChannels" TO "postUpdatesToWorkspaceChannelName"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,28 @@ import { MigrationName1731433309124 } from "./1731433309124-MigrationName";
|
||||
import { MigrationName1731435267537 } from "./1731435267537-MigrationName";
|
||||
import { MigrationName1731435514287 } from "./1731435514287-MigrationName";
|
||||
import { MigrationName1732553444010 } from "./1732553444010-MigrationName";
|
||||
import { MigrationName1734435866602 } from "./1734435866602-MigrationName";
|
||||
import { MigrationName1736364478985 } from "./1736364478985-MigrationName";
|
||||
import { MigrationName1736364957990 } from "./1736364957990-MigrationName";
|
||||
import { MigrationName1736365532085 } from "./1736365532085-MigrationName";
|
||||
import { MigrationName1736675947746 } from "./1736675947746-MigrationName";
|
||||
import { MigrationName1736703138918 } from "./1736703138918-MigrationName";
|
||||
import { MigrationName1736780194077 } from "./1736780194077-MigrationName";
|
||||
import { MigrationName1736780194078 } from "./1736780194078-MigrationName";
|
||||
import { MigrationName1736787495707 } from "./1736787495707-MigrationName";
|
||||
import { MigrationName1736787985322 } from "./1736787985322-MigrationName";
|
||||
import { MigrationName1736788706141 } from "./1736788706141-MigrationName";
|
||||
import { MigrationName1736856662868 } from "./1736856662868-MigrationName";
|
||||
import { MigrationName1737141420441 } from "./1737141420441-MigrationName";
|
||||
import { MigrationName1737713529424 } from "./1737713529424-MigrationName";
|
||||
import { MigrationName1737715240684 } from "./1737715240684-MigrationName";
|
||||
import { MigrationName1737997557974 } from "./1737997557974-MigrationName";
|
||||
import { MigrationName1739209832500 } from "./1739209832500-MigrationName";
|
||||
import { MigrationName1739210586538 } from "./1739210586538-MigrationName";
|
||||
import { MigrationName1739217257089 } from "./1739217257089-MigrationName";
|
||||
import { MigrationName1739282331053 } from "./1739282331053-MigrationName";
|
||||
import { MigrationName1739374537088 } from "./1739374537088-MigrationName";
|
||||
import { MigrationName1739569321582 } from "./1739569321582-MigrationName";
|
||||
|
||||
export default [
|
||||
InitialMigration,
|
||||
@@ -170,4 +192,26 @@ export default [
|
||||
MigrationName1731435267537,
|
||||
MigrationName1731435514287,
|
||||
MigrationName1732553444010,
|
||||
MigrationName1734435866602,
|
||||
MigrationName1736364478985,
|
||||
MigrationName1736364957990,
|
||||
MigrationName1736365532085,
|
||||
MigrationName1736675947746,
|
||||
MigrationName1736703138918,
|
||||
MigrationName1736780194077,
|
||||
MigrationName1736780194078,
|
||||
MigrationName1736787495707,
|
||||
MigrationName1736787985322,
|
||||
MigrationName1736788706141,
|
||||
MigrationName1736856662868,
|
||||
MigrationName1737141420441,
|
||||
MigrationName1737713529424,
|
||||
MigrationName1737715240684,
|
||||
MigrationName1737997557974,
|
||||
MigrationName1739209832500,
|
||||
MigrationName1739210586538,
|
||||
MigrationName1739217257089,
|
||||
MigrationName1739282331053,
|
||||
MigrationName1739374537088,
|
||||
MigrationName1739569321582,
|
||||
];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
RedisDb,
|
||||
RedisHostname,
|
||||
RedisIPFamily,
|
||||
RedisPassword,
|
||||
RedisPort,
|
||||
RedisTlsCa,
|
||||
@@ -40,6 +41,7 @@ export default abstract class Redis {
|
||||
password: RedisPassword,
|
||||
db: RedisDb,
|
||||
enableTLSForSentinelMode: RedisTlsSentinelMode,
|
||||
family: RedisIPFamily,
|
||||
lazyConnect: true,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Redis, { ClientType } from "./Redis";
|
||||
import { Mutex } from "redis-semaphore";
|
||||
import { Mutex, LockOptions } from "redis-semaphore";
|
||||
|
||||
export type SemaphoreMutex = Mutex;
|
||||
|
||||
@@ -8,7 +8,8 @@ export default class Semaphore {
|
||||
public static async lock(data: {
|
||||
key: string;
|
||||
namespace: string;
|
||||
lockTimeout?: number;
|
||||
lockTimeout?: number | undefined;
|
||||
acquireTimeout?: number | undefined;
|
||||
}): Promise<SemaphoreMutex> {
|
||||
if (!data.lockTimeout) {
|
||||
data.lockTimeout = 5000;
|
||||
@@ -22,12 +23,20 @@ export default class Semaphore {
|
||||
throw new Error("Redis client is not connected");
|
||||
}
|
||||
|
||||
const lockOptions: LockOptions = {};
|
||||
|
||||
if (data.lockTimeout) {
|
||||
lockOptions.lockTimeout = data.lockTimeout;
|
||||
}
|
||||
|
||||
if (data.acquireTimeout) {
|
||||
lockOptions.acquireTimeout = data.acquireTimeout;
|
||||
}
|
||||
|
||||
const mutex: SemaphoreMutex = new Mutex(
|
||||
client,
|
||||
data.namespace + "-" + key,
|
||||
{
|
||||
lockTimeout: data.lockTimeout,
|
||||
},
|
||||
lockOptions,
|
||||
);
|
||||
|
||||
await mutex.acquire();
|
||||
|
||||
60
Common/Server/Middleware/SlackAuthorization.ts
Normal file
60
Common/Server/Middleware/SlackAuthorization.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
ExpressResponse,
|
||||
NextFunction,
|
||||
OneUptimeRequest,
|
||||
} from "../Utils/Express";
|
||||
import Response from "../Utils/Response";
|
||||
import BadDataException from "Common/Types/Exception/BadDataException";
|
||||
import { SlackAppSigningSecret } from "../EnvironmentConfig";
|
||||
import crypto from "crypto";
|
||||
import logger from "../Utils/Logger";
|
||||
|
||||
export default class SlackAuthorization {
|
||||
public static async isAuthorizedSlackRequest(
|
||||
req: OneUptimeRequest,
|
||||
res: ExpressResponse,
|
||||
next: NextFunction,
|
||||
): Promise<void> {
|
||||
if (!SlackAppSigningSecret) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException(
|
||||
"SLACK_APP_SIGNING_SECRET env variable not found.",
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// validate slack signing secret
|
||||
const slackSigningSecret: string = SlackAppSigningSecret.toString();
|
||||
|
||||
const slackSignature: string = req.headers["x-slack-signature"] as string;
|
||||
const timestamp: string = req.headers[
|
||||
"x-slack-request-timestamp"
|
||||
] as string;
|
||||
const requestBody: string = req.body;
|
||||
|
||||
logger.debug(`slackSignature: ${slackSignature}`);
|
||||
logger.debug(`timestamp: ${timestamp}`);
|
||||
logger.debug(`requestBody: ${requestBody}`);
|
||||
|
||||
const baseString: string = `v0:${timestamp}:${requestBody}`;
|
||||
const signature: string = `v0=${crypto.createHmac("sha256", slackSigningSecret).update(baseString).digest("hex")}`;
|
||||
|
||||
// check if the signature is valid
|
||||
if (
|
||||
!crypto.timingSafeEqual(
|
||||
Buffer.from(signature),
|
||||
Buffer.from(slackSignature),
|
||||
)
|
||||
) {
|
||||
return Response.sendErrorResponse(
|
||||
req,
|
||||
res,
|
||||
new BadDataException("Slack Signature Verification Failed."),
|
||||
);
|
||||
}
|
||||
|
||||
next();
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,8 @@ import {
|
||||
} from "../../Server/Utils/Express";
|
||||
import TelemetryIngestionKeyService from "../../Server/Services/TelemetryIngestionKeyService";
|
||||
import TelemetryIngestionKey from "../../Models/DatabaseModels/TelemetryIngestionKey";
|
||||
import Response from "../Utils/Response";
|
||||
import logger from "../Utils/Logger";
|
||||
|
||||
export interface TelemetryRequest extends ExpressRequest {
|
||||
projectId: ObjectID; // Project ID
|
||||
@@ -17,12 +19,14 @@ export interface TelemetryRequest extends ExpressRequest {
|
||||
export default class TelemetryIngest {
|
||||
public static async isAuthorizedServiceMiddleware(
|
||||
req: ExpressRequest,
|
||||
_res: ExpressResponse,
|
||||
res: ExpressResponse,
|
||||
next: NextFunction,
|
||||
): Promise<void> {
|
||||
try {
|
||||
// check header.
|
||||
|
||||
const isOpenTelemetryAPI: boolean = req.path.includes("/otlp/v1");
|
||||
|
||||
let oneuptimeToken: string | undefined = req.headers[
|
||||
"x-oneuptime-token"
|
||||
] as string | undefined;
|
||||
@@ -35,6 +39,14 @@ export default class TelemetryIngest {
|
||||
}
|
||||
|
||||
if (!oneuptimeToken) {
|
||||
logger.error("Missing header: x-oneuptime-token");
|
||||
|
||||
if (isOpenTelemetryAPI) {
|
||||
// then accept the response and return success.
|
||||
// do not return error because it causes Otel to retry the request.
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
}
|
||||
|
||||
throw new BadRequestException("Missing header: x-oneuptime-token");
|
||||
}
|
||||
|
||||
@@ -54,6 +66,14 @@ export default class TelemetryIngest {
|
||||
});
|
||||
|
||||
if (!token) {
|
||||
logger.error("Invalid service token: " + oneuptimeToken);
|
||||
|
||||
if (isOpenTelemetryAPI) {
|
||||
// then accept the response and return success.
|
||||
// do not return error because it causes Otel to retry the request.
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
"Invalid service token: " + oneuptimeToken,
|
||||
);
|
||||
@@ -62,6 +82,16 @@ export default class TelemetryIngest {
|
||||
projectId = token.projectId as ObjectID;
|
||||
|
||||
if (!projectId) {
|
||||
logger.error(
|
||||
"Project ID not found for service token: " + oneuptimeToken,
|
||||
);
|
||||
|
||||
if (isOpenTelemetryAPI) {
|
||||
// then accept the response and return success.
|
||||
// do not return error because it causes Otel to retry the request.
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
}
|
||||
|
||||
throw new BadRequestException(
|
||||
"Project ID not found for service token: " + oneuptimeToken,
|
||||
);
|
||||
|
||||
88
Common/Server/Services/AlertFeedService.ts
Normal file
88
Common/Server/Services/AlertFeedService.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { Blue500 } from "../../Types/BrandColors";
|
||||
import Color from "../../Types/Color";
|
||||
import OneUptimeDate from "../../Types/Date";
|
||||
import BadDataException from "../../Types/Exception/BadDataException";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import { IsBillingEnabled } from "../EnvironmentConfig";
|
||||
import logger from "../Utils/Logger";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model, {
|
||||
AlertFeedEventType,
|
||||
} from "Common/Models/DatabaseModels/AlertFeed";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
|
||||
if (IsBillingEnabled) {
|
||||
this.hardDeleteItemsOlderThanInDays("createdAt", 120);
|
||||
}
|
||||
}
|
||||
|
||||
public async createAlertFeed(data: {
|
||||
alertId: ObjectID;
|
||||
feedInfoInMarkdown: string;
|
||||
alertFeedEventType: AlertFeedEventType;
|
||||
projectId: ObjectID;
|
||||
moreInformationInMarkdown?: string | undefined;
|
||||
displayColor?: Color | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
postedAt?: Date | undefined;
|
||||
}): Promise<void> {
|
||||
try {
|
||||
if (!data.alertId) {
|
||||
throw new BadDataException("Alert ID is required");
|
||||
}
|
||||
|
||||
if (!data.feedInfoInMarkdown) {
|
||||
throw new BadDataException("Log in markdown is required");
|
||||
}
|
||||
|
||||
if (!data.alertFeedEventType) {
|
||||
throw new BadDataException("Alert log event is required");
|
||||
}
|
||||
|
||||
if (!data.projectId) {
|
||||
throw new BadDataException("Project ID is required");
|
||||
}
|
||||
|
||||
const alertFeed: Model = new Model();
|
||||
|
||||
if (!data.displayColor) {
|
||||
data.displayColor = Blue500;
|
||||
}
|
||||
|
||||
if (data.userId) {
|
||||
alertFeed.userId = data.userId;
|
||||
}
|
||||
|
||||
alertFeed.displayColor = data.displayColor;
|
||||
|
||||
alertFeed.alertId = data.alertId;
|
||||
alertFeed.feedInfoInMarkdown = data.feedInfoInMarkdown;
|
||||
alertFeed.alertFeedEventType = data.alertFeedEventType;
|
||||
alertFeed.projectId = data.projectId;
|
||||
|
||||
if (!data.postedAt) {
|
||||
alertFeed.postedAt = OneUptimeDate.getCurrentDate();
|
||||
}
|
||||
|
||||
if (data.moreInformationInMarkdown) {
|
||||
alertFeed.moreInformationInMarkdown = data.moreInformationInMarkdown;
|
||||
}
|
||||
|
||||
await this.create({
|
||||
data: alertFeed,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("AlertFeedService.createAlertFeed");
|
||||
logger.error(error);
|
||||
// we dont want to throw the error here, as this is a non-critical operation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
@@ -1,10 +1,83 @@
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "Common/Models/DatabaseModels/AlertInternalNote";
|
||||
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
||||
import AlertFeedService from "./AlertFeedService";
|
||||
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
||||
import { Blue500 } from "../../Types/BrandColors";
|
||||
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
}
|
||||
|
||||
public override async onCreateSuccess(
|
||||
_onCreate: OnCreate<Model>,
|
||||
createdItem: Model,
|
||||
): Promise<Model> {
|
||||
const userId: ObjectID | null | undefined =
|
||||
createdItem.createdByUserId || createdItem.createdByUser?.id;
|
||||
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: createdItem.alertId!,
|
||||
projectId: createdItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.PrivateNote,
|
||||
displayColor: Blue500,
|
||||
userId: userId || undefined,
|
||||
|
||||
feedInfoInMarkdown: `**Posted Internal / Private Note**
|
||||
|
||||
${createdItem.note}
|
||||
`,
|
||||
});
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
|
||||
public override async onUpdateSuccess(
|
||||
onUpdate: OnUpdate<Model>,
|
||||
_updatedItemIds: Array<ObjectID>,
|
||||
): Promise<OnUpdate<Model>> {
|
||||
if (onUpdate.updateBy.data.note) {
|
||||
const updatedItems: Array<Model> = await this.findBy({
|
||||
query: onUpdate.updateBy.query,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
alertId: true,
|
||||
projectId: true,
|
||||
note: true,
|
||||
createdByUserId: true,
|
||||
createdByUser: {
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const userId: ObjectID | null | undefined =
|
||||
onUpdate.updateBy.props.userId;
|
||||
|
||||
for (const updatedItem of updatedItems) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: updatedItem.alertId!,
|
||||
projectId: updatedItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.PrivateNote,
|
||||
displayColor: Blue500,
|
||||
userId: userId || undefined,
|
||||
|
||||
feedInfoInMarkdown: `**Updated Internal / Private Note**
|
||||
|
||||
${updatedItem.note}
|
||||
`,
|
||||
});
|
||||
}
|
||||
}
|
||||
return onUpdate;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
|
||||
@@ -1,10 +1,122 @@
|
||||
import Team from "../../Models/DatabaseModels/Team";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import DeleteBy from "../Types/Database/DeleteBy";
|
||||
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "Common/Models/DatabaseModels/AlertOwnerTeam";
|
||||
import TeamService from "./TeamService";
|
||||
import AlertFeedService from "./AlertFeedService";
|
||||
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
||||
import { Gray500, Red500 } from "../../Types/BrandColors";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
}
|
||||
|
||||
protected override async onBeforeDelete(
|
||||
deleteBy: DeleteBy<Model>,
|
||||
): Promise<OnDelete<Model>> {
|
||||
const itemsToDelete: Model[] = await this.findBy({
|
||||
query: deleteBy.query,
|
||||
limit: deleteBy.limit,
|
||||
skip: deleteBy.skip,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
alertId: true,
|
||||
projectId: true,
|
||||
teamId: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
carryForward: {
|
||||
itemsToDelete: itemsToDelete,
|
||||
},
|
||||
deleteBy: deleteBy,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async onDeleteSuccess(
|
||||
onDelete: OnDelete<Model>,
|
||||
_itemIdsBeforeDelete: Array<ObjectID>,
|
||||
): Promise<OnDelete<Model>> {
|
||||
const deleteByUserId: ObjectID | undefined =
|
||||
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
|
||||
|
||||
const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
|
||||
|
||||
for (const item of itemsToDelete) {
|
||||
const alertId: ObjectID | undefined = item.alertId;
|
||||
const projectId: ObjectID | undefined = item.projectId;
|
||||
const teamId: ObjectID | undefined = item.teamId;
|
||||
|
||||
if (alertId && teamId && projectId) {
|
||||
const team: Team | null = await TeamService.findOneById({
|
||||
id: teamId,
|
||||
select: {
|
||||
name: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (team && team.name) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: alertId,
|
||||
projectId: projectId,
|
||||
alertFeedEventType: AlertFeedEventType.OwnerTeamRemoved,
|
||||
displayColor: Red500,
|
||||
feedInfoInMarkdown: `**Team ${team.name}** was removed from the alert as the owner.`,
|
||||
userId: deleteByUserId || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return onDelete;
|
||||
}
|
||||
|
||||
public override async onCreateSuccess(
|
||||
onCreate: OnCreate<Model>,
|
||||
createdItem: Model,
|
||||
): Promise<Model> {
|
||||
// add alert feed.
|
||||
|
||||
const alertId: ObjectID | undefined = createdItem.alertId;
|
||||
const projectId: ObjectID | undefined = createdItem.projectId;
|
||||
const teamId: ObjectID | undefined = createdItem.teamId;
|
||||
const createdByUserId: ObjectID | undefined =
|
||||
createdItem.createdByUserId || onCreate.createBy.props.userId;
|
||||
|
||||
if (alertId && teamId && projectId) {
|
||||
const team: Team | null = await TeamService.findOneById({
|
||||
id: teamId,
|
||||
select: {
|
||||
name: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (team && team.name) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: alertId,
|
||||
projectId: projectId,
|
||||
alertFeedEventType: AlertFeedEventType.OwnerTeamAdded,
|
||||
displayColor: Gray500,
|
||||
feedInfoInMarkdown: `**Team ${team.name}** was added to the alert as the owner.`,
|
||||
userId: createdByUserId || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
|
||||
@@ -1,10 +1,124 @@
|
||||
import User from "../../Models/DatabaseModels/User";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import DeleteBy from "../Types/Database/DeleteBy";
|
||||
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "Common/Models/DatabaseModels/AlertOwnerUser";
|
||||
import UserService from "./UserService";
|
||||
import AlertFeedService from "./AlertFeedService";
|
||||
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
||||
import { Gray500, Red500 } from "../../Types/BrandColors";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
}
|
||||
|
||||
protected override async onBeforeDelete(
|
||||
deleteBy: DeleteBy<Model>,
|
||||
): Promise<OnDelete<Model>> {
|
||||
const itemsToDelete: Model[] = await this.findBy({
|
||||
query: deleteBy.query,
|
||||
limit: deleteBy.limit,
|
||||
skip: deleteBy.skip,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
alertId: true,
|
||||
projectId: true,
|
||||
userId: true,
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
carryForward: {
|
||||
itemsToDelete: itemsToDelete,
|
||||
},
|
||||
deleteBy: deleteBy,
|
||||
};
|
||||
}
|
||||
|
||||
protected override async onDeleteSuccess(
|
||||
onDelete: OnDelete<Model>,
|
||||
_itemIdsBeforeDelete: Array<ObjectID>,
|
||||
): Promise<OnDelete<Model>> {
|
||||
const deleteByUserId: ObjectID | undefined =
|
||||
onDelete.deleteBy.deletedByUser?.id || onDelete.deleteBy.props.userId;
|
||||
|
||||
const itemsToDelete: Model[] = onDelete.carryForward.itemsToDelete;
|
||||
|
||||
for (const item of itemsToDelete) {
|
||||
const alertId: ObjectID | undefined = item.alertId;
|
||||
const projectId: ObjectID | undefined = item.projectId;
|
||||
const userId: ObjectID | undefined = item.userId;
|
||||
|
||||
if (alertId && userId && projectId) {
|
||||
const user: User | null = await UserService.findOneById({
|
||||
id: userId,
|
||||
select: {
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (user && user.name) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: alertId,
|
||||
projectId: projectId,
|
||||
alertFeedEventType: AlertFeedEventType.OwnerUserRemoved,
|
||||
displayColor: Red500,
|
||||
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the alert as the owner.`,
|
||||
userId: deleteByUserId || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return onDelete;
|
||||
}
|
||||
|
||||
public override async onCreateSuccess(
|
||||
onCreate: OnCreate<Model>,
|
||||
createdItem: Model,
|
||||
): Promise<Model> {
|
||||
// add alert feed.
|
||||
|
||||
const alertId: ObjectID | undefined = createdItem.alertId;
|
||||
const projectId: ObjectID | undefined = createdItem.projectId;
|
||||
const userId: ObjectID | undefined = createdItem.userId;
|
||||
const createdByUserId: ObjectID | undefined =
|
||||
createdItem.createdByUserId || onCreate.createBy.props.userId;
|
||||
|
||||
if (alertId && userId && projectId) {
|
||||
const user: User | null = await UserService.findOneById({
|
||||
id: userId,
|
||||
select: {
|
||||
name: true,
|
||||
email: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (user && user.name) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: alertId,
|
||||
projectId: projectId,
|
||||
alertFeedEventType: AlertFeedEventType.OwnerUserAdded,
|
||||
displayColor: Gray500,
|
||||
feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was added to the alert as the owner.`,
|
||||
userId: createdByUserId || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
|
||||
@@ -28,6 +28,23 @@ import AlertState from "Common/Models/DatabaseModels/AlertState";
|
||||
import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
|
||||
import User from "Common/Models/DatabaseModels/User";
|
||||
import { IsBillingEnabled } from "../EnvironmentConfig";
|
||||
import TelemetryType from "../../Types/Telemetry/TelemetryType";
|
||||
import logger from "../Utils/Logger";
|
||||
import TelemetryUtil from "../Utils/Telemetry/Telemetry";
|
||||
import MetricService from "./MetricService";
|
||||
import OneUptimeDate from "../../Types/Date";
|
||||
import Metric, {
|
||||
MetricPointType,
|
||||
ServiceType,
|
||||
} from "../../Models/AnalyticsModels/Metric";
|
||||
import AlertMetricType from "../../Types/Alerts/AlertMetricType";
|
||||
import AlertFeedService from "./AlertFeedService";
|
||||
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
||||
import { Gray500, Red500 } from "../../Types/BrandColors";
|
||||
import Label from "../../Models/DatabaseModels/Label";
|
||||
import LabelService from "./LabelService";
|
||||
import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
|
||||
import AlertSeverityService from "./AlertSeverityService";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
@@ -81,6 +98,32 @@ export class Service extends DatabaseService<Model> {
|
||||
return false;
|
||||
}
|
||||
|
||||
public async getExistingAlertNumberForProject(data: {
|
||||
projectId: ObjectID;
|
||||
}): Promise<number> {
|
||||
// get last alert number.
|
||||
const lastAlert: Model | null = await this.findOneBy({
|
||||
query: {
|
||||
projectId: data.projectId,
|
||||
},
|
||||
select: {
|
||||
alertNumber: true,
|
||||
},
|
||||
sort: {
|
||||
createdAt: SortOrder.Descending,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!lastAlert) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return lastAlert.alertNumber || 0;
|
||||
}
|
||||
|
||||
public async acknowledgeAlert(
|
||||
alertId: ObjectID,
|
||||
acknowledgedByUserId: ObjectID,
|
||||
@@ -139,9 +182,12 @@ export class Service extends DatabaseService<Model> {
|
||||
throw new BadDataException("ProjectId required to create alert.");
|
||||
}
|
||||
|
||||
const projectId: ObjectID =
|
||||
createBy.props.tenantId || createBy.data.projectId!;
|
||||
|
||||
const alertState: AlertState | null = await AlertStateService.findOneBy({
|
||||
query: {
|
||||
projectId: createBy.props.tenantId || createBy.data.projectId!,
|
||||
projectId: projectId,
|
||||
isCreatedState: true,
|
||||
},
|
||||
select: {
|
||||
@@ -160,6 +206,13 @@ export class Service extends DatabaseService<Model> {
|
||||
|
||||
createBy.data.currentAlertStateId = alertState.id;
|
||||
|
||||
const alertNumberForThisAlert: number =
|
||||
(await this.getExistingAlertNumberForProject({
|
||||
projectId: projectId,
|
||||
})) + 1;
|
||||
|
||||
createBy.data.alertNumber = alertNumberForThisAlert;
|
||||
|
||||
if (
|
||||
(createBy.data.createdByUserId ||
|
||||
createBy.data.createdByUser ||
|
||||
@@ -214,6 +267,48 @@ export class Service extends DatabaseService<Model> {
|
||||
throw new BadDataException("currentAlertStateId is required");
|
||||
}
|
||||
|
||||
const createdByUserId: ObjectID | undefined | null =
|
||||
createdItem.createdByUserId || createdItem.createdByUser?.id;
|
||||
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: createdItem.id!,
|
||||
projectId: createdItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.AlertCreated,
|
||||
displayColor: Red500,
|
||||
feedInfoInMarkdown: `**Alert #${createdItem.alertNumber?.toString()} Created**:
|
||||
|
||||
**Alert Title**:
|
||||
|
||||
${createdItem.title || "No title provided."}
|
||||
|
||||
**Description**:
|
||||
|
||||
${createdItem.description || "No description provided."}
|
||||
|
||||
`,
|
||||
userId: createdByUserId || undefined,
|
||||
});
|
||||
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: createdItem.id!,
|
||||
projectId: createdItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.RootCause,
|
||||
displayColor: Red500,
|
||||
feedInfoInMarkdown: `**Root Cause**
|
||||
|
||||
${createdItem.rootCause || "No root cause provided."}`,
|
||||
});
|
||||
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: createdItem.id!,
|
||||
projectId: createdItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.RemediationNotes,
|
||||
displayColor: Red500,
|
||||
feedInfoInMarkdown: `**Remediation Notes**
|
||||
|
||||
${createdItem.remediationNotes || "No remediation notes provided."}`,
|
||||
});
|
||||
|
||||
await this.changeAlertState({
|
||||
projectId: createdItem.projectId,
|
||||
alertId: createdItem.id,
|
||||
@@ -435,6 +530,140 @@ export class Service extends DatabaseService<Model> {
|
||||
}
|
||||
}
|
||||
|
||||
if (updatedItemIds.length > 0) {
|
||||
for (const alertId of updatedItemIds) {
|
||||
let shouldAddAlertFeed: boolean = false;
|
||||
let feedInfoInMarkdown: string = "**Alert was updated.**";
|
||||
|
||||
const createdByUserId: ObjectID | undefined | null =
|
||||
onUpdate.updateBy.props.userId;
|
||||
|
||||
if (onUpdate.updateBy.data.title) {
|
||||
// add alert feed.
|
||||
|
||||
feedInfoInMarkdown += `\n\n**Title**:
|
||||
${onUpdate.updateBy.data.title || "No title provided."}
|
||||
`;
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
|
||||
if (onUpdate.updateBy.data.rootCause) {
|
||||
if (onUpdate.updateBy.data.title) {
|
||||
// add alert feed.
|
||||
|
||||
feedInfoInMarkdown += `\n\n**Root Cause**:
|
||||
${onUpdate.updateBy.data.rootCause || "No root cause provided."}
|
||||
`;
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (onUpdate.updateBy.data.description) {
|
||||
// add alert feed.
|
||||
|
||||
feedInfoInMarkdown += `\n\n**Alert Description**:
|
||||
${onUpdate.updateBy.data.description || "No description provided."}
|
||||
`;
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
|
||||
if (onUpdate.updateBy.data.remediationNotes) {
|
||||
// add alert feed.
|
||||
|
||||
feedInfoInMarkdown += `\n\n**Remediation Notes**:
|
||||
${onUpdate.updateBy.data.remediationNotes || "No remediation notes provided."}
|
||||
`;
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
|
||||
if (
|
||||
onUpdate.updateBy.data.labels &&
|
||||
onUpdate.updateBy.data.labels.length > 0 &&
|
||||
Array.isArray(onUpdate.updateBy.data.labels)
|
||||
) {
|
||||
const labelIds: Array<ObjectID> = (
|
||||
onUpdate.updateBy.data.labels as any
|
||||
)
|
||||
.map((label: Label) => {
|
||||
if (label._id) {
|
||||
return new ObjectID(label._id?.toString());
|
||||
}
|
||||
|
||||
return null;
|
||||
})
|
||||
.filter((labelId: ObjectID | null) => {
|
||||
return labelId !== null;
|
||||
});
|
||||
|
||||
const labels: Array<Label> = await LabelService.findBy({
|
||||
query: {
|
||||
_id: QueryHelper.any(labelIds),
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (labels.length > 0) {
|
||||
feedInfoInMarkdown += `\n\n**Labels**:
|
||||
|
||||
${labels
|
||||
.map((label: Label) => {
|
||||
return `- ${label.name}`;
|
||||
})
|
||||
.join("\n")}
|
||||
`;
|
||||
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
onUpdate.updateBy.data.alertSeverity &&
|
||||
(onUpdate.updateBy.data.alertSeverity as any)._id
|
||||
) {
|
||||
const alertSeverity: AlertSeverity | null =
|
||||
await AlertSeverityService.findOneBy({
|
||||
query: {
|
||||
_id: new ObjectID(
|
||||
(onUpdate.updateBy.data.alertSeverity as any)?._id.toString(),
|
||||
),
|
||||
},
|
||||
select: {
|
||||
name: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (alertSeverity) {
|
||||
feedInfoInMarkdown += `\n\n**Alert Severity**:
|
||||
${alertSeverity.name}
|
||||
`;
|
||||
|
||||
shouldAddAlertFeed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldAddAlertFeed) {
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: alertId,
|
||||
projectId: onUpdate.updateBy.props.tenantId as ObjectID,
|
||||
alertFeedEventType: AlertFeedEventType.AlertUpdated,
|
||||
displayColor: Gray500,
|
||||
feedInfoInMarkdown: feedInfoInMarkdown,
|
||||
userId: createdByUserId || undefined,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return onUpdate;
|
||||
}
|
||||
|
||||
@@ -564,5 +793,265 @@ export class Service extends DatabaseService<Model> {
|
||||
props: props || {},
|
||||
});
|
||||
}
|
||||
|
||||
public async refreshAlertMetrics(data: { alertId: ObjectID }): Promise<void> {
|
||||
const alert: Model | null = await this.findOneById({
|
||||
id: data.alertId,
|
||||
select: {
|
||||
projectId: true,
|
||||
monitor: {
|
||||
_id: true,
|
||||
name: true,
|
||||
},
|
||||
alertSeverity: {
|
||||
name: true,
|
||||
_id: true,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!alert) {
|
||||
throw new BadDataException("Alert not found");
|
||||
}
|
||||
|
||||
if (!alert.projectId) {
|
||||
throw new BadDataException("Incient Project ID not found");
|
||||
}
|
||||
|
||||
// get alert state timeline
|
||||
|
||||
const alertStateTimelines: Array<AlertStateTimeline> =
|
||||
await AlertStateTimelineService.findBy({
|
||||
query: {
|
||||
alertId: data.alertId,
|
||||
},
|
||||
select: {
|
||||
projectId: true,
|
||||
alertStateId: true,
|
||||
alertState: {
|
||||
isAcknowledgedState: true,
|
||||
isResolvedState: true,
|
||||
},
|
||||
startsAt: true,
|
||||
endsAt: true,
|
||||
},
|
||||
sort: {
|
||||
startsAt: SortOrder.Ascending,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
const firstAlertStateTimeline: AlertStateTimeline | undefined =
|
||||
alertStateTimelines[0];
|
||||
|
||||
// delete all the alert metrics with this alert id because its a refresh.
|
||||
|
||||
await MetricService.deleteBy({
|
||||
query: {
|
||||
serviceId: data.alertId,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
const itemsToSave: Array<Metric> = [];
|
||||
|
||||
// now we need to create new metrics for this alert - TimeToAcknowledge, TimeToResolve, AlertCount, AlertDuration
|
||||
|
||||
const alertStartsAt: Date =
|
||||
firstAlertStateTimeline?.startsAt ||
|
||||
alert.createdAt ||
|
||||
OneUptimeDate.getCurrentDate();
|
||||
|
||||
const alertCountMetric: Metric = new Metric();
|
||||
|
||||
alertCountMetric.projectId = alert.projectId;
|
||||
alertCountMetric.serviceId = alert.id!;
|
||||
alertCountMetric.serviceType = ServiceType.Alert;
|
||||
alertCountMetric.name = AlertMetricType.AlertCount;
|
||||
alertCountMetric.description = "Number of alerts created";
|
||||
alertCountMetric.value = 1;
|
||||
alertCountMetric.unit = "";
|
||||
alertCountMetric.attributes = {
|
||||
alertId: data.alertId.toString(),
|
||||
projectId: alert.projectId.toString(),
|
||||
monitorId: alert.monitor?.id!.toString() || "",
|
||||
monitorName: alert.monitor?.name!.toString() || "",
|
||||
alertSeverityId: alert.alertSeverity?.id!.toString() || "",
|
||||
alertSeverityName: alert.alertSeverity?.name!.toString() || "",
|
||||
};
|
||||
|
||||
alertCountMetric.time = alertStartsAt;
|
||||
alertCountMetric.timeUnixNano = OneUptimeDate.toUnixNano(
|
||||
alertCountMetric.time,
|
||||
);
|
||||
alertCountMetric.metricPointType = MetricPointType.Sum;
|
||||
|
||||
itemsToSave.push(alertCountMetric);
|
||||
|
||||
// is the alert acknowledged?
|
||||
const isAlertAcknowledged: boolean = alertStateTimelines.some(
|
||||
(timeline: AlertStateTimeline) => {
|
||||
return timeline.alertState?.isAcknowledgedState;
|
||||
},
|
||||
);
|
||||
|
||||
if (isAlertAcknowledged) {
|
||||
const ackAlertStateTimeline: AlertStateTimeline | undefined =
|
||||
alertStateTimelines.find((timeline: AlertStateTimeline) => {
|
||||
return timeline.alertState?.isAcknowledgedState;
|
||||
});
|
||||
|
||||
if (ackAlertStateTimeline) {
|
||||
const timeToAcknowledgeMetric: Metric = new Metric();
|
||||
|
||||
timeToAcknowledgeMetric.projectId = alert.projectId;
|
||||
timeToAcknowledgeMetric.serviceId = alert.id!;
|
||||
timeToAcknowledgeMetric.serviceType = ServiceType.Alert;
|
||||
timeToAcknowledgeMetric.name = AlertMetricType.TimeToAcknowledge;
|
||||
timeToAcknowledgeMetric.description =
|
||||
"Time taken to acknowledge the alert";
|
||||
timeToAcknowledgeMetric.value = OneUptimeDate.getDifferenceInSeconds(
|
||||
ackAlertStateTimeline?.startsAt || OneUptimeDate.getCurrentDate(),
|
||||
alertStartsAt,
|
||||
);
|
||||
timeToAcknowledgeMetric.unit = "seconds";
|
||||
timeToAcknowledgeMetric.attributes = {
|
||||
alertId: data.alertId.toString(),
|
||||
projectId: alert.projectId.toString(),
|
||||
monitorId: alert.monitor?.id!.toString() || "",
|
||||
monitorName: alert.monitor?.name!.toString() || "",
|
||||
alertSeverityId: alert.alertSeverity?.id!.toString() || "",
|
||||
alertSeverityName: alert.alertSeverity?.name!.toString() || "",
|
||||
};
|
||||
|
||||
timeToAcknowledgeMetric.time =
|
||||
ackAlertStateTimeline?.startsAt ||
|
||||
alert.createdAt ||
|
||||
OneUptimeDate.getCurrentDate();
|
||||
timeToAcknowledgeMetric.timeUnixNano = OneUptimeDate.toUnixNano(
|
||||
timeToAcknowledgeMetric.time,
|
||||
);
|
||||
timeToAcknowledgeMetric.metricPointType = MetricPointType.Sum;
|
||||
|
||||
itemsToSave.push(timeToAcknowledgeMetric);
|
||||
}
|
||||
}
|
||||
|
||||
// time to resolve
|
||||
const isAlertResolved: boolean = alertStateTimelines.some(
|
||||
(timeline: AlertStateTimeline) => {
|
||||
return timeline.alertState?.isResolvedState;
|
||||
},
|
||||
);
|
||||
|
||||
if (isAlertResolved) {
|
||||
const resolvedAlertStateTimeline: AlertStateTimeline | undefined =
|
||||
alertStateTimelines.find((timeline: AlertStateTimeline) => {
|
||||
return timeline.alertState?.isResolvedState;
|
||||
});
|
||||
|
||||
if (resolvedAlertStateTimeline) {
|
||||
const timeToResolveMetric: Metric = new Metric();
|
||||
|
||||
timeToResolveMetric.projectId = alert.projectId;
|
||||
timeToResolveMetric.serviceId = alert.id!;
|
||||
timeToResolveMetric.serviceType = ServiceType.Alert;
|
||||
timeToResolveMetric.name = AlertMetricType.TimeToResolve;
|
||||
timeToResolveMetric.description = "Time taken to resolve the alert";
|
||||
timeToResolveMetric.value = OneUptimeDate.getDifferenceInSeconds(
|
||||
resolvedAlertStateTimeline?.startsAt ||
|
||||
OneUptimeDate.getCurrentDate(),
|
||||
alertStartsAt,
|
||||
);
|
||||
timeToResolveMetric.unit = "seconds";
|
||||
timeToResolveMetric.attributes = {
|
||||
alertId: data.alertId.toString(),
|
||||
projectId: alert.projectId.toString(),
|
||||
monitorId: alert.monitor?.id!.toString() || "",
|
||||
monitorName: alert.monitor?.name!.toString() || "",
|
||||
alertSeverityId: alert.alertSeverity?.id!.toString() || "",
|
||||
alertSeverityName: alert.alertSeverity?.name!.toString() || "",
|
||||
};
|
||||
|
||||
timeToResolveMetric.time =
|
||||
resolvedAlertStateTimeline?.startsAt ||
|
||||
alert.createdAt ||
|
||||
OneUptimeDate.getCurrentDate();
|
||||
timeToResolveMetric.timeUnixNano = OneUptimeDate.toUnixNano(
|
||||
timeToResolveMetric.time,
|
||||
);
|
||||
timeToResolveMetric.metricPointType = MetricPointType.Sum;
|
||||
|
||||
itemsToSave.push(timeToResolveMetric);
|
||||
}
|
||||
}
|
||||
|
||||
// alert duration
|
||||
|
||||
const alertDurationMetric: Metric = new Metric();
|
||||
|
||||
const lastAlertStateTimeline: AlertStateTimeline | undefined =
|
||||
alertStateTimelines[alertStateTimelines.length - 1];
|
||||
|
||||
if (lastAlertStateTimeline) {
|
||||
const alertEndsAt: Date =
|
||||
lastAlertStateTimeline.startsAt || OneUptimeDate.getCurrentDate();
|
||||
|
||||
// save metric.
|
||||
|
||||
alertDurationMetric.projectId = alert.projectId;
|
||||
alertDurationMetric.serviceId = alert.id!;
|
||||
alertDurationMetric.serviceType = ServiceType.Alert;
|
||||
alertDurationMetric.name = AlertMetricType.AlertDuration;
|
||||
alertDurationMetric.description = "Duration of the alert";
|
||||
alertDurationMetric.value = OneUptimeDate.getDifferenceInSeconds(
|
||||
alertEndsAt,
|
||||
alertStartsAt,
|
||||
);
|
||||
alertDurationMetric.unit = "seconds";
|
||||
alertDurationMetric.attributes = {
|
||||
alertId: data.alertId.toString(),
|
||||
projectId: alert.projectId.toString(),
|
||||
monitorId: alert.monitor?.id!.toString() || "",
|
||||
monitorName: alert.monitor?.name!.toString() || "",
|
||||
alertSeverityId: alert.alertSeverity?.id!.toString() || "",
|
||||
alertSeverityName: alert.alertSeverity?.name!.toString() || "",
|
||||
};
|
||||
|
||||
alertDurationMetric.time =
|
||||
lastAlertStateTimeline?.startsAt ||
|
||||
alert.createdAt ||
|
||||
OneUptimeDate.getCurrentDate();
|
||||
alertDurationMetric.timeUnixNano = OneUptimeDate.toUnixNano(
|
||||
alertDurationMetric.time,
|
||||
);
|
||||
alertDurationMetric.metricPointType = MetricPointType.Sum;
|
||||
}
|
||||
|
||||
await MetricService.createMany({
|
||||
items: itemsToSave,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
// index attributes.
|
||||
TelemetryUtil.indexAttributes({
|
||||
attributes: ["monitorId", "projectId", "alertId", "monitorNames"],
|
||||
projectId: alert.projectId,
|
||||
telemetryType: TelemetryType.Metric,
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
}
|
||||
}
|
||||
export default new Service();
|
||||
|
||||
@@ -18,6 +18,9 @@ import { IsBillingEnabled } from "../EnvironmentConfig";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
|
||||
import AlertInternalNoteService from "./AlertInternalNoteService";
|
||||
import logger from "../Utils/Logger";
|
||||
import AlertFeedService from "./AlertFeedService";
|
||||
import { AlertFeedEventType } from "../../Models/DatabaseModels/AlertFeed";
|
||||
|
||||
export class Service extends DatabaseService<AlertStateTimeline> {
|
||||
public constructor() {
|
||||
@@ -129,10 +132,15 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
||||
});
|
||||
}
|
||||
|
||||
const privateNote: string | undefined = (
|
||||
createBy.miscDataProps as JSONObject | undefined
|
||||
)?.["privateNote"] as string | undefined;
|
||||
|
||||
return {
|
||||
createBy,
|
||||
carryForward: {
|
||||
lastAlertStateTimelineId: lastAlertStateTimeline?.id || null,
|
||||
privateNote: privateNote,
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -163,6 +171,36 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
||||
});
|
||||
}
|
||||
|
||||
const alertState: AlertState | null = await AlertStateService.findOneBy({
|
||||
query: {
|
||||
_id: createdItem.alertStateId.toString()!,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
isResolvedState: true,
|
||||
isAcknowledgedState: true,
|
||||
isCreatedState: true,
|
||||
color: true,
|
||||
name: true,
|
||||
},
|
||||
});
|
||||
|
||||
const stateName: string = alertState?.name || "";
|
||||
|
||||
await AlertFeedService.createAlertFeed({
|
||||
alertId: createdItem.alertId!,
|
||||
projectId: createdItem.projectId!,
|
||||
alertFeedEventType: AlertFeedEventType.AlertStateChanged,
|
||||
displayColor: alertState?.color,
|
||||
feedInfoInMarkdown: "**Alert State** changed to **" + stateName + "**",
|
||||
moreInformationInMarkdown: `**Cause:**
|
||||
${createdItem.rootCause}`,
|
||||
userId: createdItem.createdByUserId || onCreate.createBy.props.userId,
|
||||
});
|
||||
|
||||
await AlertService.updateOneBy({
|
||||
query: {
|
||||
_id: createdItem.alertId?.toString(),
|
||||
@@ -173,6 +211,30 @@ export class Service extends DatabaseService<AlertStateTimeline> {
|
||||
props: onCreate.createBy.props,
|
||||
});
|
||||
|
||||
if (onCreate.carryForward.privateNote) {
|
||||
const privateNote: string = onCreate.carryForward.privateNote;
|
||||
|
||||
const alertInternalNote: AlertInternalNote = new AlertInternalNote();
|
||||
alertInternalNote.alertId = createdItem.alertId;
|
||||
alertInternalNote.note = privateNote;
|
||||
alertInternalNote.createdAt = createdItem.startsAt!;
|
||||
alertInternalNote.projectId = createdItem.projectId!;
|
||||
|
||||
await AlertInternalNoteService.create({
|
||||
data: alertInternalNote,
|
||||
props: onCreate.createBy.props,
|
||||
});
|
||||
}
|
||||
|
||||
AlertService.refreshAlertMetrics({
|
||||
alertId: createdItem.alertId,
|
||||
}).catch((error: Error) => {
|
||||
logger.error(
|
||||
"Error while refreshing alert metrics after alert state timeline creation",
|
||||
);
|
||||
logger.error(error);
|
||||
});
|
||||
|
||||
return createdItem;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ import logger from "../Utils/Logger";
|
||||
import Realtime from "../Utils/Realtime";
|
||||
import StreamUtil from "../Utils/Stream";
|
||||
import BaseService from "./BaseService";
|
||||
import { ExecResult } from "@clickhouse/client";
|
||||
import { ExecResult, ResponseJSON, ResultSet } from "@clickhouse/client";
|
||||
import AnalyticsBaseModel from "Common/Models/AnalyticsModels/AnalyticsBaseModel/AnalyticsBaseModel";
|
||||
import { WorkflowRoute } from "Common/ServiceRoute";
|
||||
import Protocol from "../../Types/API/Protocol";
|
||||
@@ -148,19 +148,29 @@ export default class AnalyticsDatabaseService<
|
||||
|
||||
const countStatement: Statement = this.toCountStatement(countBy);
|
||||
|
||||
const dbResult: ExecResult<Stream> = await this.execute(countStatement);
|
||||
const dbResult: ResultSet<"JSON"> =
|
||||
await this.executeQuery(countStatement);
|
||||
|
||||
const strResult: string = await StreamUtil.convertStreamToText(
|
||||
dbResult.stream,
|
||||
);
|
||||
logger.debug(`${this.model.tableName} Count Statement executed`);
|
||||
logger.debug(countStatement);
|
||||
|
||||
let countPositive: PositiveNumber = new PositiveNumber(strResult || 0);
|
||||
|
||||
if (countBy.groupBy && Object.keys(countBy.groupBy).length > 0) {
|
||||
// this usually happens when group by is used. In this case we count the total number of groups and not rows in those groups.
|
||||
countPositive = new PositiveNumber(strResult.split("\n").length - 1); // -1 because the last line is empty.
|
||||
const resultInJSON: ResponseJSON<JSONObject> =
|
||||
await dbResult.json<JSONObject>();
|
||||
let countPositive: PositiveNumber = new PositiveNumber(0);
|
||||
if (
|
||||
resultInJSON.data &&
|
||||
resultInJSON.data[0] &&
|
||||
resultInJSON.data[0]["count()"] &&
|
||||
typeof resultInJSON.data[0]["count()"] === "string"
|
||||
) {
|
||||
countPositive = new PositiveNumber(
|
||||
resultInJSON.data[0]["count()"] as string,
|
||||
);
|
||||
}
|
||||
|
||||
logger.debug(`Result: `);
|
||||
logger.debug(countPositive.toNumber());
|
||||
|
||||
countPositive = await this.onCountSuccess(countPositive);
|
||||
return countPositive;
|
||||
} catch (error) {
|
||||
@@ -240,20 +250,18 @@ export default class AnalyticsDatabaseService<
|
||||
columns: Array<string>;
|
||||
} = this.toAggregateStatement(aggregateBy);
|
||||
|
||||
const dbResult: ExecResult<Stream> = await this.execute(
|
||||
const dbResult: ResultSet<"JSON"> = await this.executeQuery(
|
||||
findStatement.statement,
|
||||
);
|
||||
|
||||
const strResult: string = await StreamUtil.convertStreamToText(
|
||||
dbResult.stream,
|
||||
);
|
||||
logger.debug(`${this.model.tableName} Aggregate Statement executed`);
|
||||
|
||||
const jsonItems: Array<JSONObject> = this.convertSelectReturnedDataToJson(
|
||||
strResult,
|
||||
findStatement.columns,
|
||||
);
|
||||
const responseJSON: ResponseJSON<JSONObject> =
|
||||
await dbResult.json<JSONObject>();
|
||||
|
||||
const items: Array<JSONObject> = jsonItems as any;
|
||||
const items: Array<JSONObject> = responseJSON.data
|
||||
? responseJSON.data
|
||||
: [];
|
||||
|
||||
const aggregatedItems: Array<AggregatedModel> = [];
|
||||
|
||||
@@ -314,16 +322,6 @@ export default class AnalyticsDatabaseService<
|
||||
}
|
||||
}
|
||||
|
||||
public async executeQuery(query: string): Promise<string> {
|
||||
const dbResult: ExecResult<Stream> = await this.execute(query);
|
||||
|
||||
const strResult: string = await StreamUtil.convertStreamToText(
|
||||
dbResult.stream,
|
||||
);
|
||||
|
||||
return strResult;
|
||||
}
|
||||
|
||||
private async _findBy(
|
||||
findBy: FindBy<TBaseModel>,
|
||||
): Promise<Array<TBaseModel>> {
|
||||
@@ -379,21 +377,17 @@ export default class AnalyticsDatabaseService<
|
||||
columns: Array<string>;
|
||||
} = this.toFindStatement(onBeforeFind);
|
||||
|
||||
const dbResult: ExecResult<Stream> = await this.execute(
|
||||
const dbResult: ResultSet<"JSON"> = await this.executeQuery(
|
||||
findStatement.statement,
|
||||
);
|
||||
|
||||
logger.debug(`${this.model.tableName} Find Statement executed`);
|
||||
logger.debug(findStatement.statement);
|
||||
|
||||
const strResult: string = await StreamUtil.convertStreamToText(
|
||||
dbResult.stream,
|
||||
);
|
||||
const responseJSON: ResponseJSON<JSONObject> =
|
||||
await dbResult.json<JSONObject>();
|
||||
|
||||
const jsonItems: Array<JSONObject> = this.convertSelectReturnedDataToJson(
|
||||
strResult,
|
||||
findStatement.columns,
|
||||
);
|
||||
const jsonItems: Array<JSONObject> = responseJSON.data;
|
||||
|
||||
let items: Array<TBaseModel> =
|
||||
AnalyticsBaseModel.fromJSONArray<TBaseModel>(jsonItems, this.modelType);
|
||||
@@ -411,10 +405,14 @@ export default class AnalyticsDatabaseService<
|
||||
}
|
||||
}
|
||||
|
||||
private convertSelectReturnedDataToJson(
|
||||
public convertSelectReturnedDataToJson(
|
||||
strResult: string,
|
||||
columns: string[],
|
||||
): JSONObject[] {
|
||||
if (!strResult || !strResult.trim()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const jsonItems: Array<JSONObject> = [];
|
||||
|
||||
const rows: Array<string> = strResult.split("\n");
|
||||
@@ -811,6 +809,24 @@ export default class AnalyticsDatabaseService<
|
||||
) as ExecResult<Stream>;
|
||||
}
|
||||
|
||||
|
||||
public async executeQuery(
|
||||
statement: Statement | string,
|
||||
): Promise<ResultSet<"JSON">> {
|
||||
if (!this.databaseClient) {
|
||||
this.useDefaultDatabase();
|
||||
}
|
||||
|
||||
const query: string = statement instanceof Statement ? statement.query : statement;
|
||||
const queryParams: Record<string, unknown> | undefined = statement instanceof Statement ? statement.query_params : undefined;
|
||||
|
||||
return await this.databaseClient.query({
|
||||
query: query,
|
||||
format: "JSON",
|
||||
query_params: queryParams || undefined as any, // undefined is not specified in the type for query_params, but its ok to pass undefined.
|
||||
})
|
||||
}
|
||||
|
||||
protected async onUpdateSuccess(
|
||||
onUpdate: OnUpdate<TBaseModel>,
|
||||
_updatedItemIds: Array<ObjectID>,
|
||||
|
||||
@@ -10,6 +10,11 @@ import Model, {
|
||||
InvoiceStatus,
|
||||
} from "Common/Models/DatabaseModels/BillingInvoice";
|
||||
import Project from "Common/Models/DatabaseModels/Project";
|
||||
import SubscriptionStatus from "../../Types/Billing/SubscriptionStatus";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
|
||||
import logger from "../Utils/Logger";
|
||||
import OneUptimeDate from "../../Types/Date";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
@@ -17,6 +22,166 @@ export class Service extends DatabaseService<Model> {
|
||||
this.setDoNotAllowDelete(true);
|
||||
}
|
||||
|
||||
public async refreshSubscriptionStatus(data: {
|
||||
projectId: ObjectID;
|
||||
}): Promise<void> {
|
||||
let mutex: SemaphoreMutex | null = null;
|
||||
|
||||
try {
|
||||
mutex = await Semaphore.lock({
|
||||
key: data.projectId.toString(),
|
||||
namespace: "BillingInoviceService.refreshSubscriptionStatus",
|
||||
lockTimeout: 15000,
|
||||
acquireTimeout: 20000,
|
||||
});
|
||||
logger.debug(
|
||||
"Mutex acquired - " +
|
||||
data.projectId.toString() +
|
||||
" at " +
|
||||
OneUptimeDate.getCurrentDateAsFormattedString(),
|
||||
);
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
"Mutex acquire failed - " +
|
||||
data.projectId.toString() +
|
||||
" at " +
|
||||
OneUptimeDate.getCurrentDateAsFormattedString(),
|
||||
);
|
||||
logger.error(err);
|
||||
}
|
||||
|
||||
let project: Project | null = await ProjectService.findOneById({
|
||||
id: data.projectId,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
paymentProviderCustomerId: true,
|
||||
paymentProviderSubscriptionId: true,
|
||||
paymentProviderMeteredSubscriptionId: true,
|
||||
},
|
||||
});
|
||||
|
||||
// refresh the subscription status. This is a hack to ensure that the subscription status is always up to date.
|
||||
// This is because the subscription status can change at any time and we need to ensure that the subscription status is always up to date.
|
||||
|
||||
if (!project) {
|
||||
throw new BadDataException("Project not found");
|
||||
}
|
||||
|
||||
if (!project.paymentProviderCustomerId) {
|
||||
throw new BadDataException("Payment provider customer id not found.");
|
||||
}
|
||||
|
||||
let subscriptionState: SubscriptionStatus =
|
||||
await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderSubscriptionId as string,
|
||||
);
|
||||
|
||||
let meteredSubscriptionState: SubscriptionStatus =
|
||||
await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderMeteredSubscriptionId as string,
|
||||
);
|
||||
|
||||
// update the project.
|
||||
|
||||
await ProjectService.updateOneById({
|
||||
id: project.id!,
|
||||
data: {
|
||||
paymentProviderSubscriptionStatus: subscriptionState,
|
||||
paymentProviderMeteredSubscriptionStatus: meteredSubscriptionState,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
ignoreHooks: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (
|
||||
meteredSubscriptionState === SubscriptionStatus.Canceled ||
|
||||
subscriptionState === SubscriptionStatus.Canceled
|
||||
) {
|
||||
// check if all invoices are paid. If yes, then reactivate the subscription.
|
||||
|
||||
const invoices: Array<Invoice> = await BillingService.getInvoices(
|
||||
project.paymentProviderCustomerId,
|
||||
);
|
||||
|
||||
let allInvoicesPaid: boolean = true;
|
||||
|
||||
for (const invoice of invoices) {
|
||||
if (
|
||||
invoice.status === InvoiceStatus.Open ||
|
||||
invoice.status === InvoiceStatus.Uncollectible
|
||||
) {
|
||||
allInvoicesPaid = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (allInvoicesPaid) {
|
||||
await ProjectService.reactiveSubscription(project.id!);
|
||||
project = await ProjectService.findOneById({
|
||||
id: data.projectId,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
paymentProviderCustomerId: true,
|
||||
paymentProviderSubscriptionId: true,
|
||||
paymentProviderMeteredSubscriptionId: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (!project) {
|
||||
throw new BadDataException("Project not found");
|
||||
}
|
||||
|
||||
subscriptionState = await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderSubscriptionId as string,
|
||||
);
|
||||
|
||||
meteredSubscriptionState = await BillingService.getSubscriptionStatus(
|
||||
project.paymentProviderMeteredSubscriptionId as string,
|
||||
);
|
||||
|
||||
await ProjectService.updateOneById({
|
||||
id: project.id!,
|
||||
data: {
|
||||
paymentProviderSubscriptionStatus: subscriptionState,
|
||||
paymentProviderMeteredSubscriptionStatus: meteredSubscriptionState,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
ignoreHooks: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (mutex) {
|
||||
try {
|
||||
await Semaphore.release(mutex);
|
||||
logger.debug(
|
||||
"Mutex released - " +
|
||||
data.projectId.toString() +
|
||||
" at " +
|
||||
OneUptimeDate.getCurrentDateAsFormattedString(),
|
||||
);
|
||||
} catch (err) {
|
||||
logger.debug(
|
||||
"Mutex release failed - " +
|
||||
data.projectId.toString() +
|
||||
" at " +
|
||||
OneUptimeDate.getCurrentDateAsFormattedString(),
|
||||
);
|
||||
logger.error(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override async onBeforeFind(
|
||||
findBy: FindBy<Model>,
|
||||
): Promise<OnFind<Model>> {
|
||||
@@ -37,6 +202,11 @@ export class Service extends DatabaseService<Model> {
|
||||
},
|
||||
});
|
||||
|
||||
// refresh the subscription status. This is a hack to ensure that the subscription status is always up to date.
|
||||
// This is because the subscription status can change at any time and we need to ensure that the subscription status is always up to date.
|
||||
|
||||
await this.refreshSubscriptionStatus({ projectId: findBy.props.tenantId! });
|
||||
|
||||
if (!project) {
|
||||
throw new BadDataException("Project not found");
|
||||
}
|
||||
|
||||
@@ -1392,6 +1392,9 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
...data,
|
||||
} as any;
|
||||
|
||||
logger.debug("Updated Item");
|
||||
logger.debug(JSON.stringify(updatedItem, null, 2));
|
||||
|
||||
await this.getRepository().save(updatedItem);
|
||||
|
||||
// hit workflow.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user