mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 08:42:13 +02:00
Compare commits
409 Commits
probe-queu
...
scim-updat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c17328ee3 | ||
|
|
3eeb2a9eca | ||
|
|
51fa5705b1 | ||
|
|
6f952d0a5b | ||
|
|
ade98cf1ed | ||
|
|
a65e480bb6 | ||
|
|
c777a935c3 | ||
|
|
8ec9d2a930 | ||
|
|
224c225789 | ||
|
|
85dae7a307 | ||
|
|
332a479c22 | ||
|
|
d708fbbb52 | ||
|
|
03bceb959e | ||
|
|
efa411206e | ||
|
|
27fd99f2e8 | ||
|
|
07361bfeb7 | ||
|
|
bc8a5be0fa | ||
|
|
518768078a | ||
|
|
86e95f99ff | ||
|
|
ea48f56097 | ||
|
|
b8b9dd859a | ||
|
|
d28c14ef24 | ||
|
|
670bec2a12 | ||
|
|
aff24845a8 | ||
|
|
f280e97c1b | ||
|
|
62facf62dd | ||
|
|
db0387d81a | ||
|
|
5c4b19ab3d | ||
|
|
463755fa4d | ||
|
|
85888572de | ||
|
|
475bb25b2d | ||
|
|
badd200aed | ||
|
|
b40d87cbc9 | ||
|
|
36d0066b3a | ||
|
|
a49a0b2cba | ||
|
|
bada97d474 | ||
|
|
a1699f2d55 | ||
|
|
a11e054291 | ||
|
|
47cf7ba763 | ||
|
|
4e0dfb3664 | ||
|
|
250cb9e547 | ||
|
|
541257e3c6 | ||
|
|
ed43686736 | ||
|
|
9ca45f23e3 | ||
|
|
e3573a9b77 | ||
|
|
c9e78044e6 | ||
|
|
813581dec5 | ||
|
|
e528decf73 | ||
|
|
42ef41ede8 | ||
|
|
af26472db4 | ||
|
|
44b5c8b668 | ||
|
|
d821b88ed7 | ||
|
|
1df43e21ff | ||
|
|
76ca6ee7e1 | ||
|
|
dac731a57b | ||
|
|
0f4b248598 | ||
|
|
b2c14e0380 | ||
|
|
3ab9705bbe | ||
|
|
40812c8749 | ||
|
|
45ae1501f2 | ||
|
|
13d9f19606 | ||
|
|
ad3221310a | ||
|
|
659042fcfb | ||
|
|
d65b9c7b29 | ||
|
|
dc77206e6f | ||
|
|
9c1910d3f1 | ||
|
|
afe8f8e6f4 | ||
|
|
015bd0f870 | ||
|
|
383c145186 | ||
|
|
f155795e6b | ||
|
|
757f5b5721 | ||
|
|
694215df06 | ||
|
|
0eb6022f1d | ||
|
|
3109006828 | ||
|
|
272695bd11 | ||
|
|
330e3bc106 | ||
|
|
c7876bf3a3 | ||
|
|
345ada5404 | ||
|
|
4f97b1b460 | ||
|
|
e35ef1809f | ||
|
|
c2926f3542 | ||
|
|
9495b4bd47 | ||
|
|
ad3f36fdf5 | ||
|
|
f2221b0a40 | ||
|
|
62fbc1f4be | ||
|
|
054a2bc8f5 | ||
|
|
896787109c | ||
|
|
3a55fcc872 | ||
|
|
2945a48d05 | ||
|
|
da3a7ddb2e | ||
|
|
04a0bfedaa | ||
|
|
fa5c7b1e73 | ||
|
|
a1c2918cd7 | ||
|
|
91b11b12c1 | ||
|
|
778a34d631 | ||
|
|
6dbd838ca4 | ||
|
|
e09634dc6f | ||
|
|
af60715de2 | ||
|
|
3b4c54876e | ||
|
|
e357100e46 | ||
|
|
7f3a50076d | ||
|
|
9d182b6d55 | ||
|
|
33fce0b53c | ||
|
|
3db8419349 | ||
|
|
dfc324b099 | ||
|
|
36521ef37c | ||
|
|
a6f336340e | ||
|
|
c36f782192 | ||
|
|
5219f1cfc0 | ||
|
|
7f84d50baa | ||
|
|
cd2ce3f1a8 | ||
|
|
01b0e01ca8 | ||
|
|
73dc6bb5db | ||
|
|
ab7fc1c244 | ||
|
|
3927bea29c | ||
|
|
6060d66c2b | ||
|
|
9f4869b05f | ||
|
|
17bdfee012 | ||
|
|
4988b9fc7a | ||
|
|
9edc6b9f18 | ||
|
|
525e19faa6 | ||
|
|
588e8976d2 | ||
|
|
d5e28e98fb | ||
|
|
0e84bc9c40 | ||
|
|
39e8b1da6b | ||
|
|
66c4badd94 | ||
|
|
a245fabc34 | ||
|
|
fa9fce2774 | ||
|
|
a256f4be54 | ||
|
|
4869172648 | ||
|
|
1abd323b00 | ||
|
|
fa196a55cd | ||
|
|
29b4417aca | ||
|
|
29c0d7e7e9 | ||
|
|
bfbe2437c0 | ||
|
|
ca0e082daf | ||
|
|
1987b1c42e | ||
|
|
38be6edec3 | ||
|
|
b80dda6d1a | ||
|
|
f65b2711ca | ||
|
|
151c3d8c52 | ||
|
|
f17ae36dce | ||
|
|
777c6948ad | ||
|
|
1c6f9adbcb | ||
|
|
6d1b3f8568 | ||
|
|
11526816d1 | ||
|
|
bf190b6a32 | ||
|
|
4736ea8227 | ||
|
|
2cb4281fc3 | ||
|
|
505ed980c3 | ||
|
|
a0b77c94b0 | ||
|
|
bb996ddaa2 | ||
|
|
a2f8e49bc1 | ||
|
|
4d6086b7fd | ||
|
|
f84a1db36a | ||
|
|
3aa4214e54 | ||
|
|
2fb8341f9c | ||
|
|
888d18d0a3 | ||
|
|
7f8270fac1 | ||
|
|
318c1516cd | ||
|
|
0343dcca93 | ||
|
|
7728e38029 | ||
|
|
83a0efcbb9 | ||
|
|
577ba9436e | ||
|
|
a521f42417 | ||
|
|
1002616ab3 | ||
|
|
13adbd2443 | ||
|
|
12b82252f1 | ||
|
|
bdb9cb9b9a | ||
|
|
c5e19db669 | ||
|
|
345bdf80e1 | ||
|
|
c4bf5e5001 | ||
|
|
a3685b3698 | ||
|
|
388f6e3530 | ||
|
|
0493dabb93 | ||
|
|
2383b2d352 | ||
|
|
c526c0e320 | ||
|
|
7d607608b3 | ||
|
|
abece559ea | ||
|
|
f9b0c499ed | ||
|
|
38594f5198 | ||
|
|
8f08ec42c7 | ||
|
|
8c697149e3 | ||
|
|
2ff3dee440 | ||
|
|
c0e8193614 | ||
|
|
c1d06fdae5 | ||
|
|
00ed20ea68 | ||
|
|
db93cc8841 | ||
|
|
374e8ecb4c | ||
|
|
9ac17850a6 | ||
|
|
a38d75b8f0 | ||
|
|
1bfdf90bca | ||
|
|
49e3db9442 | ||
|
|
83ab7030a4 | ||
|
|
76abf62917 | ||
|
|
a5c2f19846 | ||
|
|
d37e783aeb | ||
|
|
657ea0ec09 | ||
|
|
e59f7a0a7f | ||
|
|
35fc80de1e | ||
|
|
5e2dea40a3 | ||
|
|
a66f92e0b9 | ||
|
|
a2ce7c9433 | ||
|
|
eab1dc4b1b | ||
|
|
6939c70ed8 | ||
|
|
cce0dc8a45 | ||
|
|
ec51d7b574 | ||
|
|
d4129cfa8e | ||
|
|
1ee7c092d3 | ||
|
|
daf3b13e00 | ||
|
|
5035319cc6 | ||
|
|
3d53889d1e | ||
|
|
65b610ebbb | ||
|
|
30d1b43178 | ||
|
|
d0645f5dc2 | ||
|
|
2274c14098 | ||
|
|
d1b4d3867a | ||
|
|
04d4712c81 | ||
|
|
9c2d2b658b | ||
|
|
fdb1444dc8 | ||
|
|
39f724b77f | ||
|
|
dbfa153209 | ||
|
|
1c8739237f | ||
|
|
26cdaacf6b | ||
|
|
bbc8f0c680 | ||
|
|
61dd8e9202 | ||
|
|
6e17832239 | ||
|
|
6460827c4c | ||
|
|
7bfd810b73 | ||
|
|
8b17217778 | ||
|
|
19a86e9683 | ||
|
|
d2fd46db50 | ||
|
|
26cfbd07cb | ||
|
|
33992984e2 | ||
|
|
e295c19b19 | ||
|
|
51d42c8436 | ||
|
|
50f16d0fdc | ||
|
|
726ab4d7c0 | ||
|
|
1461dd0164 | ||
|
|
5ce1a782b3 | ||
|
|
741eaec1d3 | ||
|
|
2d8c931641 | ||
|
|
4db479958b | ||
|
|
8c825f1498 | ||
|
|
25426992be | ||
|
|
861a72d194 | ||
|
|
0857cebcfc | ||
|
|
975af2c22a | ||
|
|
98d15f91b0 | ||
|
|
6d55b59a21 | ||
|
|
8a27651d84 | ||
|
|
6a35dffcb5 | ||
|
|
1e4c46bb3f | ||
|
|
fe44c0fde4 | ||
|
|
089f612ec4 | ||
|
|
8dbd9e7430 | ||
|
|
66eb9eede0 | ||
|
|
e8db6fcb7f | ||
|
|
d9e7f44590 | ||
|
|
b7df0a7d05 | ||
|
|
4101954862 | ||
|
|
d68e4737e7 | ||
|
|
bfb80388a0 | ||
|
|
1beb96345b | ||
|
|
1eb2af737d | ||
|
|
18f756a29b | ||
|
|
002f98720c | ||
|
|
fdf5aacc2b | ||
|
|
574cad6806 | ||
|
|
34c4ae947b | ||
|
|
8d9fc46506 | ||
|
|
c41fbefdcb | ||
|
|
3e47051233 | ||
|
|
8219f44708 | ||
|
|
59e6505aa3 | ||
|
|
1f971b932a | ||
|
|
d0e12ae86f | ||
|
|
cd11a450cd | ||
|
|
c0259fc041 | ||
|
|
db1f5a29bb | ||
|
|
a9ecaf2dc8 | ||
|
|
138aad596a | ||
|
|
2577b339aa | ||
|
|
80e7731cca | ||
|
|
9da7b258f9 | ||
|
|
0ec3b1aa39 | ||
|
|
7a9bb22813 | ||
|
|
92550ac7d6 | ||
|
|
101df5b9b7 | ||
|
|
c3d7672935 | ||
|
|
859c6378af | ||
|
|
620979eab2 | ||
|
|
0aa1c51efa | ||
|
|
1985e9fc25 | ||
|
|
ba4093838b | ||
|
|
4bd7902afe | ||
|
|
5c300ed513 | ||
|
|
c4a50e853c | ||
|
|
20c1f13876 | ||
|
|
09426ed6be | ||
|
|
675a031ee6 | ||
|
|
92986ac1f8 | ||
|
|
2b95d608dc | ||
|
|
2696071933 | ||
|
|
684a61b599 | ||
|
|
633a89161e | ||
|
|
fd24781783 | ||
|
|
903b13d515 | ||
|
|
58a128a05e | ||
|
|
ec1d567813 | ||
|
|
0a53161eac | ||
|
|
83b91af708 | ||
|
|
3fefee8725 | ||
|
|
9b2cc7d377 | ||
|
|
1fb71ed2e3 | ||
|
|
94a5abdb31 | ||
|
|
73f4559943 | ||
|
|
9c3c6ee4e9 | ||
|
|
56743214a0 | ||
|
|
9136c6d40e | ||
|
|
920a9baee9 | ||
|
|
1c4aad2d81 | ||
|
|
8a4644922a | ||
|
|
c3f4b7d3d4 | ||
|
|
6f7c0814ee | ||
|
|
77cd3fc4c0 | ||
|
|
e7cbc3d739 | ||
|
|
6d14ea19b9 | ||
|
|
1290d3b946 | ||
|
|
c0c58546d0 | ||
|
|
6c5ef10606 | ||
|
|
ec4c6ff7c5 | ||
|
|
616e6e43ab | ||
|
|
aa08cd904b | ||
|
|
fef1c1055c | ||
|
|
22e33809f9 | ||
|
|
eb8324a3c2 | ||
|
|
fa6dedc9a1 | ||
|
|
099cd807bf | ||
|
|
5d0b010fc4 | ||
|
|
1fc421f92a | ||
|
|
14a14e2341 | ||
|
|
ab23cca264 | ||
|
|
678a961fb9 | ||
|
|
c2e458f035 | ||
|
|
4daf17dc8c | ||
|
|
842aa4b88d | ||
|
|
fd51142693 | ||
|
|
e0ddf80aa6 | ||
|
|
e8d55164c6 | ||
|
|
5cd8795e7a | ||
|
|
aebf7a4f2e | ||
|
|
3ef093eee1 | ||
|
|
b4c530a6a5 | ||
|
|
166228cad5 | ||
|
|
1eb95c71fe | ||
|
|
56f33f256b | ||
|
|
42afd164b7 | ||
|
|
0796166a55 | ||
|
|
170bfa8515 | ||
|
|
2f517d8dcc | ||
|
|
cb5c4dce45 | ||
|
|
d9abeda60d | ||
|
|
15c4c89310 | ||
|
|
8c1d5652f4 | ||
|
|
fbf87cf8d4 | ||
|
|
1c12ad94dd | ||
|
|
aa09bab7c9 | ||
|
|
f7d1975ab0 | ||
|
|
99c9a591cb | ||
|
|
c956d01789 | ||
|
|
17c829869b | ||
|
|
d65e91a912 | ||
|
|
39710ba9b0 | ||
|
|
8c70a4dfae | ||
|
|
ff99055594 | ||
|
|
f01cc2fd71 | ||
|
|
49b43593b1 | ||
|
|
e293ffd0eb | ||
|
|
b62a5e7722 | ||
|
|
8f8ba0abb8 | ||
|
|
5525556b54 | ||
|
|
669066b70a | ||
|
|
76d2abed08 | ||
|
|
a6c18b3f21 | ||
|
|
955ea7bc31 | ||
|
|
45719d4656 | ||
|
|
796c94a261 | ||
|
|
d2fe822cb7 | ||
|
|
289a369eab | ||
|
|
6f07e3e119 | ||
|
|
8cdc1e9faf | ||
|
|
d4609a84ef | ||
|
|
eb4a91a598 | ||
|
|
5bea404d6c | ||
|
|
df3f8b6a74 | ||
|
|
0c9d2c821a | ||
|
|
ba49aaf0c3 | ||
|
|
6ea5ad7fe8 | ||
|
|
962866d109 | ||
|
|
115216561c | ||
|
|
f709c90cc4 | ||
|
|
d7f01b0189 | ||
|
|
c3eaa8995c | ||
|
|
53b482b9f3 | ||
|
|
d52670f39c | ||
|
|
fdc1332b9e | ||
|
|
a937416663 | ||
|
|
546d41da81 |
126
.github/workflows/build.yml
vendored
126
.github/workflows/build.yml
vendored
@@ -23,7 +23,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Accounts/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Accounts/Dockerfile .
|
||||
|
||||
docker-build-isolated-vm:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -38,7 +42,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./IsolatedVM/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./IsolatedVM/Dockerfile .
|
||||
|
||||
docker-build-home:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -53,7 +61,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Home/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Home/Dockerfile .
|
||||
|
||||
docker-build-worker:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -68,7 +80,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Worker/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Worker/Dockerfile .
|
||||
|
||||
docker-build-workflow:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -83,7 +99,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Workflow/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Workflow/Dockerfile .
|
||||
|
||||
docker-build-api-reference:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -98,7 +118,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./APIReference/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./APIReference/Dockerfile .
|
||||
|
||||
docker-build-docs:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -113,7 +137,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Docs/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Docs/Dockerfile .
|
||||
|
||||
|
||||
docker-build-otel-collector:
|
||||
@@ -129,7 +157,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./OTelCollector/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./OTelCollector/Dockerfile .
|
||||
|
||||
docker-build-app:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -145,7 +177,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./App/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./App/Dockerfile .
|
||||
|
||||
|
||||
docker-build-copilot:
|
||||
@@ -161,7 +197,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Copilot/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Copilot/Dockerfile .
|
||||
|
||||
docker-build-e2e:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -177,7 +217,11 @@ jobs:
|
||||
|
||||
# build image for accounts service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./E2E/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./E2E/Dockerfile .
|
||||
|
||||
docker-build-admin-dashboard:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -192,7 +236,11 @@ jobs:
|
||||
|
||||
# build image for home
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./AdminDashboard/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./AdminDashboard/Dockerfile .
|
||||
|
||||
docker-build-dashboard:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -207,7 +255,11 @@ jobs:
|
||||
|
||||
# build image for home
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Dashboard/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Dashboard/Dockerfile .
|
||||
|
||||
docker-build-probe:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -222,7 +274,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./Probe/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./Probe/Dockerfile .
|
||||
|
||||
docker-build-probe-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -237,7 +293,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./ProbeIngest/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./ProbeIngest/Dockerfile .
|
||||
|
||||
docker-build-server-monitor-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -252,7 +312,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./ServerMonitorIngest/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./ServerMonitorIngest/Dockerfile .
|
||||
|
||||
docker-build-open-telemetry-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -267,7 +331,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./OpenTelemetryIngest/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./OpenTelemetryIngest/Dockerfile .
|
||||
|
||||
docker-build-incoming-request-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -282,7 +350,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./IncomingRequestIngest/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./IncomingRequestIngest/Dockerfile .
|
||||
|
||||
docker-build-fluent-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -297,7 +369,11 @@ jobs:
|
||||
|
||||
# build image probe api
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./FluentIngest/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./FluentIngest/Dockerfile .
|
||||
|
||||
docker-build-status-page:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -312,7 +388,11 @@ jobs:
|
||||
|
||||
# build image for home
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./StatusPage/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./StatusPage/Dockerfile .
|
||||
|
||||
docker-build-test-server:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -327,4 +407,8 @@ jobs:
|
||||
|
||||
# build image for mail service
|
||||
- name: build docker image
|
||||
run: sudo docker build -f ./TestServer/Dockerfile .
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: sudo docker build -f ./TestServer/Dockerfile .
|
||||
|
||||
168
.github/workflows/compile.yml
vendored
168
.github/workflows/compile.yml
vendored
@@ -20,7 +20,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Accounts && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Accounts
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Accounts && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-isolated-vm:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -32,7 +37,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd IsolatedVM && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile IsolatedVM
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd IsolatedVM && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-common:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -43,7 +53,12 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Common
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Common && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-app:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -55,7 +70,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd App && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile App
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd App && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-home:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -67,7 +87,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Home && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Home
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Home && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-worker:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -79,7 +104,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Worker && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Worker
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Worker && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-workflow:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -91,7 +121,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Workflow && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Workflow
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Workflow && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-api-reference:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -103,7 +138,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd APIReference && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile API Reference
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd APIReference && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-docs-reference:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -115,7 +155,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Docs && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Docs Reference
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Docs && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-copilot:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -127,7 +172,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Copilot && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Copilot
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Copilot && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-nginx:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -140,7 +190,12 @@ jobs:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd Nginx && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Nginx
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Nginx && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-infrastructure-agent:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -150,7 +205,12 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
# Setup Go
|
||||
- uses: actions/setup-go@v5
|
||||
- run: cd InfrastructureAgent && go build .
|
||||
- name: Compile Infrastructure Agent
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd InfrastructureAgent && go build .
|
||||
|
||||
|
||||
compile-admin-dashboard:
|
||||
@@ -164,7 +224,12 @@ jobs:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd AdminDashboard && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Admin Dashboard
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd AdminDashboard && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-dashboard:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -177,7 +242,12 @@ jobs:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd Dashboard && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Dashboard
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Dashboard && npm install && npm run compile && npm run dep-check
|
||||
|
||||
|
||||
compile-e2e:
|
||||
@@ -191,7 +261,12 @@ jobs:
|
||||
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
|
||||
- name: Compile E2E
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd E2E && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-probe:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -203,7 +278,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd Probe && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Probe
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd Probe && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-probe-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -215,7 +295,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd ProbeIngest && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Probe Ingest
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd ProbeIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-server-monitor-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -227,7 +312,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd ServerMonitorIngest && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Server Monitor Ingest
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd ServerMonitorIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-open-telemetry-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -239,7 +329,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd OpenTelemetryIngest && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Open Telemetry Ingest
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd OpenTelemetryIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
|
||||
compile-incoming-request-ingest:
|
||||
@@ -252,7 +347,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd IncomingRequestIngest && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Incoming Request Ingest
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd IncomingRequestIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-fluent-ingest:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -264,7 +364,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd FluentIngest && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Fluent Ingest
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd FluentIngest && npm install && npm run compile && npm run dep-check
|
||||
|
||||
|
||||
compile-status-page:
|
||||
@@ -278,7 +383,12 @@ jobs:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
|
||||
- run: cd StatusPage && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Status Page
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd StatusPage && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-test-server:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -290,7 +400,12 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd TestServer && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile Test Server
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd TestServer && npm install && npm run compile && npm run dep-check
|
||||
|
||||
compile-mcp:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -302,4 +417,9 @@ jobs:
|
||||
with:
|
||||
node-version: latest
|
||||
- run: cd Common && npm install
|
||||
- run: cd MCP && npm install && npm run compile && npm run dep-check
|
||||
- name: Compile MCP
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: cd MCP && npm install && npm run compile && npm run dep-check
|
||||
667
.github/workflows/release.yml
vendored
667
.github/workflows/release.yml
vendored
@@ -184,18 +184,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
run: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--file ./MCP/Dockerfile.tpl \
|
||||
--tag oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag oneuptime/mcp-server:release \
|
||||
--tag ghcr.io/oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag ghcr.io/oneuptime/mcp-server:release \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=${{ steps.version.outputs.version }} \
|
||||
--push .
|
||||
echo "✅ Pushed Docker images to Docker Hub and GitHub Container Registry"
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--file ./MCP/Dockerfile.tpl \
|
||||
--tag oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag oneuptime/mcp-server:release \
|
||||
--tag ghcr.io/oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag ghcr.io/oneuptime/mcp-server:release \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=${{ steps.version.outputs.version }} \
|
||||
--push .
|
||||
echo "✅ Pushed Docker images to Docker Hub and GitHub Container Registry"
|
||||
|
||||
- name: Upload MCP server artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -252,17 +256,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Nginx/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Nginx/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/nginx:release \
|
||||
--tag oneuptime/nginx:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/nginx:release \
|
||||
--tag ghcr.io/oneuptime/nginx:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
e2e-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -312,17 +321,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./E2E/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./E2E/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/e2e:release \
|
||||
--tag oneuptime/e2e:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/e2e:release \
|
||||
--tag ghcr.io/oneuptime/e2e:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
isolated-vm-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -372,17 +386,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./IsolatedVM/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./IsolatedVM/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/isolated-vm:release \
|
||||
--tag oneuptime/isolated-vm:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/isolated-vm:release \
|
||||
--tag ghcr.io/oneuptime/isolated-vm:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
home-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -432,17 +451,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Home/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Home/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/home:release \
|
||||
--tag oneuptime/home:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/home:release \
|
||||
--tag ghcr.io/oneuptime/home:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -495,17 +519,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./TestServer/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./TestServer/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/test-server:release \
|
||||
--tag oneuptime/test-server:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/test-server:release \
|
||||
--tag ghcr.io/oneuptime/test-server:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
otel-collector-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -555,17 +584,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./OTelCollector/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./OTelCollector/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/otel-collector:release \
|
||||
--tag oneuptime/otel-collector:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/otel-collector:release \
|
||||
--tag ghcr.io/oneuptime/otel-collector:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -617,17 +651,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./StatusPage/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./StatusPage/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/status-page:release \
|
||||
--tag oneuptime/status-page:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/status-page:release \
|
||||
--tag ghcr.io/oneuptime/status-page:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
test-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -677,17 +716,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Tests/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Tests/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/test:release \
|
||||
--tag oneuptime/test:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/test:release \
|
||||
--tag ghcr.io/oneuptime/test:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
probe-ingest-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -737,17 +781,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./ProbeIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./ProbeIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/probe-ingest:release \
|
||||
--tag oneuptime/probe-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/probe-ingest:release \
|
||||
--tag ghcr.io/oneuptime/probe-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
server-monitor-ingest-docker-image-deploy:
|
||||
@@ -798,17 +847,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./ServerMonitorIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./ServerMonitorIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/server-monitor-ingest:release \
|
||||
--tag oneuptime/server-monitor-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/server-monitor-ingest:release \
|
||||
--tag ghcr.io/oneuptime/server-monitor-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -860,17 +914,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./OpenTelemetryIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./OpenTelemetryIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/open-telemetry-ingest:release \
|
||||
--tag oneuptime/open-telemetry-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/open-telemetry-ingest:release \
|
||||
--tag ghcr.io/oneuptime/open-telemetry-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
incoming-request-ingest-docker-image-deploy:
|
||||
@@ -921,17 +980,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./IncomingRequestIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./IncomingRequestIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/incoming-request-ingest:release \
|
||||
--tag oneuptime/incoming-request-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/incoming-request-ingest:release \
|
||||
--tag ghcr.io/oneuptime/incoming-request-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
fluent-ingest-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -981,17 +1045,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./FluentIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./FluentIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/fluent-ingest:release \
|
||||
--tag oneuptime/fluent-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/fluent-ingest:release \
|
||||
--tag ghcr.io/oneuptime/fluent-ingest:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
probe-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -1041,17 +1110,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Probe/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Probe/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/probe:release \
|
||||
--tag oneuptime/probe:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/probe:release \
|
||||
--tag ghcr.io/oneuptime/probe:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
admin-dashboard-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -1101,17 +1175,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./AdminDashboard/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./AdminDashboard/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/admin-dashboard:release \
|
||||
--tag oneuptime/admin-dashboard:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/admin-dashboard:release \
|
||||
--tag ghcr.io/oneuptime/admin-dashboard:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
dashboard-docker-image-deploy:
|
||||
@@ -1162,17 +1241,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Dashboard/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Dashboard/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/dashboard:release \
|
||||
--tag oneuptime/dashboard:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/dashboard:release \
|
||||
--tag ghcr.io/oneuptime/dashboard:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
app-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -1222,17 +1306,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./App/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./App/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/app:release \
|
||||
--tag oneuptime/app:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/app:release \
|
||||
--tag ghcr.io/oneuptime/app:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
copilot-docker-image-deploy:
|
||||
@@ -1283,17 +1372,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Copilot/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Copilot/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/copilot:release \
|
||||
--tag oneuptime/copilot:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/copilot:release \
|
||||
--tag ghcr.io/oneuptime/copilot:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
accounts-docker-image-deploy:
|
||||
needs: [generate-build-number]
|
||||
@@ -1343,17 +1437,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Accounts/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Accounts/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/accounts:release \
|
||||
--tag oneuptime/accounts:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/accounts:release \
|
||||
--tag ghcr.io/oneuptime/accounts:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
publish-npm-packages:
|
||||
@@ -1443,17 +1542,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./LLM/Dockerfile
|
||||
context: ./LLM
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./LLM/Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
--push \
|
||||
--tag oneuptime/llm:release \
|
||||
--tag oneuptime/llm:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/llm:release \
|
||||
--tag ghcr.io/oneuptime/llm:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
./LLM
|
||||
|
||||
docs-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1505,17 +1609,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Docs/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Docs/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/docs:release \
|
||||
--tag oneuptime/docs:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/docs:release \
|
||||
--tag ghcr.io/oneuptime/docs:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1570,17 +1679,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Worker/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Worker/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/worker:release \
|
||||
--tag oneuptime/worker:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/worker:release \
|
||||
--tag ghcr.io/oneuptime/worker:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1635,17 +1749,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Workflow/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Workflow/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/workflow:release \
|
||||
--tag oneuptime/workflow:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/workflow:release \
|
||||
--tag ghcr.io/oneuptime/workflow:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1761,17 +1880,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./APIReference/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 45
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./APIReference/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/api-reference:release \
|
||||
--tag oneuptime/api-reference:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--tag ghcr.io/oneuptime/api-reference:release \
|
||||
--tag ghcr.io/oneuptime/api-reference:7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1898,12 +2022,49 @@ jobs:
|
||||
configuration: "./Scripts/Release/ChangelogConfig.json"
|
||||
- run: echo "Changelog:"
|
||||
- run: echo "${{steps.build_changelog.outputs.changelog}}"
|
||||
- name: Fallback to commit messages if changelog empty
|
||||
id: fallback_changelog
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
CHANGELOG_CONTENT="${{steps.build_changelog.outputs.changelog}}"
|
||||
OLD_PLACEHOLDER="No significant changes were made. We have just fixed minor bugs for this release. You can find the detailed information in the commit history."
|
||||
NEW_PLACEHOLDER="(auto) No categorized pull requests. Fallback will list raw commit messages."
|
||||
if echo "$CHANGELOG_CONTENT" | grep -Fq "$OLD_PLACEHOLDER" || echo "$CHANGELOG_CONTENT" | grep -Fq "$NEW_PLACEHOLDER"; then
|
||||
echo "Detected empty placeholder changelog. Building commit list fallback."
|
||||
# Find previous tag (skip the most recent tag which might be for an older release). If none, include all commits.
|
||||
if prev_tag=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1) 2>/dev/null); then
|
||||
echo "Previous tag: $prev_tag"
|
||||
commits=$(git log --pretty=format:'- %s (%h)' "$prev_tag"..HEAD)
|
||||
else
|
||||
echo "No previous tag found; using full commit history on this branch."
|
||||
commits=$(git log --pretty=format:'- %s (%h)')
|
||||
fi
|
||||
# If still empty (e.g., no commits), keep placeholder to avoid empty body.
|
||||
if [ -z "$commits" ]; then
|
||||
commits="(no commits found)"
|
||||
fi
|
||||
{
|
||||
echo "changelog<<EOF"
|
||||
echo "## Commit Messages"
|
||||
echo ""
|
||||
echo "$commits"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
# Pass through original changelog
|
||||
{
|
||||
echo "changelog<<EOF"
|
||||
echo "$CHANGELOG_CONTENT"
|
||||
echo "EOF"
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- uses: ncipollo/release-action@v1
|
||||
with:
|
||||
tag: "7.0.${{needs.generate-build-number.outputs.build_number}}"
|
||||
artifactErrorsFailBuild: true
|
||||
body: |
|
||||
${{steps.build_changelog.outputs.changelog}}
|
||||
${{steps.fallback_changelog.outputs.changelog}}
|
||||
|
||||
|
||||
infrastructure-agent-deploy:
|
||||
|
||||
@@ -77,17 +77,21 @@ jobs:
|
||||
ls -la "$PROVIDER_DIR" || true
|
||||
|
||||
- name: Test Go build
|
||||
run: |
|
||||
PROVIDER_DIR="./Terraform"
|
||||
if [ -d "$PROVIDER_DIR" ] && [ -f "$PROVIDER_DIR/go.mod" ]; then
|
||||
cd "$PROVIDER_DIR"
|
||||
echo "🔨 Testing Go build..."
|
||||
go mod tidy
|
||||
go build -v ./...
|
||||
echo "✅ Go build successful"
|
||||
else
|
||||
echo "⚠️ Cannot test build - missing go.mod or provider directory"
|
||||
fi
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
PROVIDER_DIR="./Terraform"
|
||||
if [ -d "$PROVIDER_DIR" ] && [ -f "$PROVIDER_DIR/go.mod" ]; then
|
||||
cd "$PROVIDER_DIR"
|
||||
echo "🔨 Testing Go build..."
|
||||
go mod tidy
|
||||
go build -v ./...
|
||||
echo "✅ Go build successful"
|
||||
else
|
||||
echo "⚠️ Cannot test build - missing go.mod or provider directory"
|
||||
fi
|
||||
|
||||
- name: Upload Terraform provider as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
|
||||
629
.github/workflows/test-release.yaml
vendored
629
.github/workflows/test-release.yaml
vendored
@@ -176,18 +176,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker images (test)
|
||||
run: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--file ./MCP/Dockerfile.tpl \
|
||||
--tag oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag oneuptime/mcp-server:test \
|
||||
--tag ghcr.io/oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag ghcr.io/oneuptime/mcp-server:test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=${{ steps.version.outputs.version }} \
|
||||
--push .
|
||||
echo "✅ Pushed test Docker images to Docker Hub and GitHub Container Registry"
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--file ./MCP/Dockerfile.tpl \
|
||||
--tag oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag oneuptime/mcp-server:test \
|
||||
--tag ghcr.io/oneuptime/mcp-server:${{ steps.version.outputs.version }} \
|
||||
--tag ghcr.io/oneuptime/mcp-server:test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=${{ steps.version.outputs.version }} \
|
||||
--push .
|
||||
echo "✅ Pushed test Docker images to Docker Hub and GitHub Container Registry"
|
||||
|
||||
- name: Upload MCP server artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
@@ -269,18 +273,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./LLM/Dockerfile
|
||||
context: ./LLM
|
||||
# arm64 is not supported by the base image of the LLM
|
||||
platforms: linux/amd64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./LLM/Dockerfile \
|
||||
--platform linux/amd64 \
|
||||
--push \
|
||||
--tag oneuptime/llm:test \
|
||||
--tag oneuptime/llm:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/llm:test \
|
||||
--tag ghcr.io/oneuptime/llm:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
./LLM
|
||||
|
||||
|
||||
nginx-docker-image-deploy:
|
||||
@@ -332,17 +340,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Nginx/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Nginx/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/nginx:test \
|
||||
--tag oneuptime/nginx:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/nginx:test \
|
||||
--tag ghcr.io/oneuptime/nginx:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
e2e-docker-image-deploy:
|
||||
@@ -394,17 +407,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./E2E/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./E2E/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/e2e:test \
|
||||
--tag oneuptime/e2e:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/e2e:test \
|
||||
--tag ghcr.io/oneuptime/e2e:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
test-server-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -455,17 +473,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./TestServer/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./TestServer/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/test-server:test \
|
||||
--tag oneuptime/test-server:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/test-server:test \
|
||||
--tag ghcr.io/oneuptime/test-server:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
otel-collector-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -516,17 +539,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./OTelCollector/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./OTelCollector/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/otel-collector:test \
|
||||
--tag oneuptime/otel-collector:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/otel-collector:test \
|
||||
--tag ghcr.io/oneuptime/otel-collector:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
isolated-vm-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -577,17 +605,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./IsolatedVM/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./IsolatedVM/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/isolated-vm:test \
|
||||
--tag oneuptime/isolated-vm:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/isolated-vm:test \
|
||||
--tag ghcr.io/oneuptime/isolated-vm:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
home-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -638,17 +671,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Home/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Home/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/home:test \
|
||||
--tag oneuptime/home:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/home:test \
|
||||
--tag ghcr.io/oneuptime/home:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -701,17 +739,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./StatusPage/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./StatusPage/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/status-page:test \
|
||||
--tag oneuptime/status-page:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/status-page:test \
|
||||
--tag ghcr.io/oneuptime/status-page:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -764,17 +807,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Tests/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Tests/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/test:test \
|
||||
--tag oneuptime/test:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/test:test \
|
||||
--tag ghcr.io/oneuptime/test:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
probe-ingest-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -825,17 +873,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./ProbeIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./ProbeIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/probe-ingest:test \
|
||||
--tag oneuptime/probe-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/probe-ingest:test \
|
||||
--tag ghcr.io/oneuptime/probe-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -888,17 +941,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./ServerMonitorIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./ServerMonitorIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/server-monitor-ingest:test \
|
||||
--tag oneuptime/server-monitor-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/server-monitor-ingest:test \
|
||||
--tag ghcr.io/oneuptime/server-monitor-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -952,17 +1010,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./IncomingRequestIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./IncomingRequestIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/incoming-request-ingest:test \
|
||||
--tag oneuptime/incoming-request-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/incoming-request-ingest:test \
|
||||
--tag ghcr.io/oneuptime/incoming-request-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
open-telemetry-ingest-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1013,17 +1076,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./OpenTelemetryIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./OpenTelemetryIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/open-telemetry-ingest:test \
|
||||
--tag oneuptime/open-telemetry-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/open-telemetry-ingest:test \
|
||||
--tag ghcr.io/oneuptime/open-telemetry-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
fluent-ingest-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1074,17 +1142,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./FluentIngest/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./FluentIngest/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/fluent-ingest:test \
|
||||
--tag oneuptime/fluent-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/fluent-ingest:test \
|
||||
--tag ghcr.io/oneuptime/fluent-ingest:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
probe-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1135,17 +1208,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Probe/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Probe/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/probe:test \
|
||||
--tag oneuptime/probe:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/probe:test \
|
||||
--tag ghcr.io/oneuptime/probe:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
dashboard-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1196,17 +1274,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Dashboard/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Dashboard/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/dashboard:test \
|
||||
--tag oneuptime/dashboard:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/dashboard:test \
|
||||
--tag ghcr.io/oneuptime/dashboard:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
admin-dashboard-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1257,17 +1340,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./AdminDashboard/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./AdminDashboard/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/admin-dashboard:test \
|
||||
--tag oneuptime/admin-dashboard:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/admin-dashboard:test \
|
||||
--tag ghcr.io/oneuptime/admin-dashboard:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
app-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1318,17 +1406,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./App/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./App/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/app:test \
|
||||
--tag oneuptime/app:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/app:test \
|
||||
--tag ghcr.io/oneuptime/app:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1382,17 +1475,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./APIReference/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./APIReference/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/api-reference:test \
|
||||
--tag oneuptime/api-reference:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/api-reference:test \
|
||||
--tag ghcr.io/oneuptime/api-reference:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
@@ -1445,17 +1543,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Accounts/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Accounts/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/accounts:test \
|
||||
--tag oneuptime/accounts:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/accounts:test \
|
||||
--tag ghcr.io/oneuptime/accounts:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
worker-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1506,17 +1609,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Worker/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.copilot-docker-image-deploybuild_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Worker/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/worker:test \
|
||||
--tag oneuptime/worker:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/worker:test \
|
||||
--tag ghcr.io/oneuptime/worker:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
copilot-docker-image-deploy:
|
||||
needs: generate-build-number
|
||||
@@ -1567,17 +1675,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Copilot/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Copilot/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/copilot:test \
|
||||
--tag oneuptime/copilot:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/copilot:test \
|
||||
--tag ghcr.io/oneuptime/copilot:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
workflow-docker-image-deploy:
|
||||
@@ -1629,17 +1742,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Workflow/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Workflow/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/workflow:test \
|
||||
--tag oneuptime/workflow:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/workflow:test \
|
||||
--tag ghcr.io/oneuptime/workflow:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
docs-docker-image-deploy:
|
||||
@@ -1691,17 +1809,22 @@ jobs:
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: nick-fields/retry@v3
|
||||
with:
|
||||
file: ./Docs/Dockerfile
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
build-args: |
|
||||
GIT_SHA=${{ github.sha }}
|
||||
APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}}
|
||||
timeout_minutes: 30
|
||||
max_attempts: 3
|
||||
command: |
|
||||
docker buildx build \
|
||||
--file ./Docs/Dockerfile \
|
||||
--platform linux/amd64,linux/arm64 \
|
||||
--push \
|
||||
--tag oneuptime/docs:test \
|
||||
--tag oneuptime/docs:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--tag ghcr.io/oneuptime/docs:test \
|
||||
--tag ghcr.io/oneuptime/docs:7.0.${{needs.generate-build-number.outputs.build_number}}-test \
|
||||
--build-arg GIT_SHA=${{ github.sha }} \
|
||||
--build-arg APP_VERSION=7.0.${{needs.generate-build-number.outputs.build_number}} \
|
||||
.
|
||||
|
||||
|
||||
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -127,3 +127,4 @@ MCP/build/
|
||||
MCP/.env
|
||||
MCP/node_modules
|
||||
Dashboard/public/sw.js
|
||||
.claude/settings.local.json
|
||||
|
||||
@@ -4,5 +4,7 @@
|
||||
"ignore": [
|
||||
"greenlock.d/*"
|
||||
],
|
||||
"exec": "node --inspect=0.0.0.0:9229 --require ts-node/register Index.ts"
|
||||
"watchOptions": {"useFsEvents": false, "interval": 500},
|
||||
"env": {"TS_NODE_TRANSPILE_ONLY": "1", "TS_NODE_FILES": "false"},
|
||||
"exec": "node --inspect=0.0.0.0:9229 -r ts-node/register/transpile-only Index.ts"
|
||||
}
|
||||
@@ -135,7 +135,6 @@
|
||||
<link rel="apple-touch-icon-precomposed" href="/img/ou-wb.svg">
|
||||
<link rel="icon" href="/img/ou-wb.svg">
|
||||
<link rel="image_src" type="image/png" href="/img/hou-wb.svg">
|
||||
<link rel="canonical" href="/">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<meta property="og:title" content="OneUptime - One Complete Observability platform.">
|
||||
<meta property="og:url" content="https://oneuptime.com">
|
||||
|
||||
@@ -282,6 +282,9 @@ import ShortLinkService, {
|
||||
import SmsLogService, {
|
||||
Service as SmsLogServiceType,
|
||||
} from "Common/Server/Services/SmsLogService";
|
||||
import PushNotificationLogService, {
|
||||
Service as PushNotificationLogServiceType,
|
||||
} from "Common/Server/Services/PushNotificationLogService";
|
||||
import SpanService, {
|
||||
SpanService as SpanServiceType,
|
||||
} from "Common/Server/Services/SpanService";
|
||||
@@ -379,6 +382,8 @@ import Span from "Common/Models/AnalyticsModels/Span";
|
||||
import ApiKey from "Common/Models/DatabaseModels/ApiKey";
|
||||
import ApiKeyPermission from "Common/Models/DatabaseModels/ApiKeyPermission";
|
||||
import CallLog from "Common/Models/DatabaseModels/CallLog";
|
||||
import PushNotificationLog from "Common/Models/DatabaseModels/PushNotificationLog";
|
||||
import WorkspaceNotificationLog from "Common/Models/DatabaseModels/WorkspaceNotificationLog";
|
||||
import Domain from "Common/Models/DatabaseModels/Domain";
|
||||
import EmailLog from "Common/Models/DatabaseModels/EmailLog";
|
||||
import EmailVerificationToken from "Common/Models/DatabaseModels/EmailVerificationToken";
|
||||
@@ -480,6 +485,9 @@ import TelemetryAttribute from "Common/Models/AnalyticsModels/TelemetryAttribute
|
||||
import ExceptionInstance from "Common/Models/AnalyticsModels/ExceptionInstance";
|
||||
import TelemetyException from "Common/Models/DatabaseModels/TelemetryException";
|
||||
import CopilotActionTypePriority from "Common/Models/DatabaseModels/CopilotActionTypePriority";
|
||||
import WorkspaceNotificationLogService, {
|
||||
Service as WorkspaceNotificationLogServiceType,
|
||||
} from "Common/Server/Services/WorkspaceNotificationLogService";
|
||||
|
||||
// scheduled maintenance template
|
||||
import ScheduledMaintenanceTemplate from "Common/Models/DatabaseModels/ScheduledMaintenanceTemplate";
|
||||
@@ -530,11 +538,6 @@ import WorkspaceSettingService, {
|
||||
Service as WorkspaceSettingServiceType,
|
||||
} from "Common/Server/Services/WorkspaceSettingService";
|
||||
|
||||
import ProjectUser from "Common/Models/DatabaseModels/ProjectUser";
|
||||
import ProjectUserService, {
|
||||
Service as ProjectUserServiceType,
|
||||
} from "Common/Server/Services/ProjectUserService";
|
||||
|
||||
import MonitorFeed from "Common/Models/DatabaseModels/MonitorFeed";
|
||||
import MonitorFeedService, {
|
||||
Service as MonitorFeedServiceType,
|
||||
@@ -583,6 +586,18 @@ import StatusPageAnnouncementTemplateService, {
|
||||
Service as StatusPageAnnouncementTemplateServiceType,
|
||||
} from "Common/Server/Services/StatusPageAnnouncementTemplateService";
|
||||
|
||||
// ProjectSCIM
|
||||
import ProjectSCIM from "Common/Models/DatabaseModels/ProjectSCIM";
|
||||
import ProjectSCIMService, {
|
||||
Service as ProjectSCIMServiceType,
|
||||
} from "Common/Server/Services/ProjectSCIMService";
|
||||
|
||||
// StatusPageSCIM
|
||||
import StatusPageSCIM from "Common/Models/DatabaseModels/StatusPageSCIM";
|
||||
import StatusPageSCIMService, {
|
||||
Service as StatusPageSCIMServiceType,
|
||||
} from "Common/Server/Services/StatusPageSCIMService";
|
||||
|
||||
// Open API Spec
|
||||
import OpenAPI from "Common/Server/API/OpenAPI";
|
||||
|
||||
@@ -618,6 +633,24 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
// Project SCIM
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<ProjectSCIM, ProjectSCIMServiceType>(
|
||||
ProjectSCIM,
|
||||
ProjectSCIMService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
// Status Page SCIM
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<StatusPageSCIM, StatusPageSCIMServiceType>(
|
||||
StatusPageSCIM,
|
||||
StatusPageSCIMService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
// status page announcement templates
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
@@ -698,14 +731,6 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<ProjectUser, ProjectUserServiceType>(
|
||||
ProjectUser,
|
||||
ProjectUserService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
//service provider setting
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
@@ -1501,6 +1526,22 @@ const BaseAPIFeatureSet: FeatureSet = {
|
||||
new BaseAPI<SmsLog, SmsLogServiceType>(SmsLog, SmsLogService).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<PushNotificationLog, PushNotificationLogServiceType>(
|
||||
PushNotificationLog,
|
||||
PushNotificationLogService,
|
||||
).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<
|
||||
WorkspaceNotificationLog,
|
||||
WorkspaceNotificationLogServiceType
|
||||
>(WorkspaceNotificationLog, WorkspaceNotificationLogService).getRouter(),
|
||||
);
|
||||
|
||||
app.use(
|
||||
`/${APP_NAME.toLocaleLowerCase()}`,
|
||||
new BaseAPI<EmailLog, EmailLogServiceType>(
|
||||
|
||||
1181
App/FeatureSet/Identity/API/SCIM.ts
Normal file
1181
App/FeatureSet/Identity/API/SCIM.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -168,6 +168,7 @@ router.post(
|
||||
},
|
||||
{
|
||||
projectId: statusPage.projectId!,
|
||||
statusPageId: statusPage.id!,
|
||||
},
|
||||
).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
@@ -306,6 +307,7 @@ router.post(
|
||||
},
|
||||
{
|
||||
projectId: statusPage.projectId!,
|
||||
statusPageId: statusPage.id!,
|
||||
},
|
||||
).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
|
||||
996
App/FeatureSet/Identity/API/StatusPageSCIM.ts
Normal file
996
App/FeatureSet/Identity/API/StatusPageSCIM.ts
Normal file
@@ -0,0 +1,996 @@
|
||||
import SCIMMiddleware from "Common/Server/Middleware/SCIMAuthorization";
|
||||
import StatusPagePrivateUserService from "Common/Server/Services/StatusPagePrivateUserService";
|
||||
import StatusPageSCIMUserService from "Common/Server/Services/StatusPageSCIMUserService";
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
OneUptimeRequest,
|
||||
} from "Common/Server/Utils/Express";
|
||||
import Response from "Common/Server/Utils/Response";
|
||||
import logger from "Common/Server/Utils/Logger";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
import Email from "Common/Types/Email";
|
||||
import { JSONObject } from "Common/Types/JSON";
|
||||
import StatusPagePrivateUser from "Common/Models/DatabaseModels/StatusPagePrivateUser";
|
||||
import StatusPageSCIM from "Common/Models/DatabaseModels/StatusPageSCIM";
|
||||
import StatusPageSCIMUser from "Common/Models/DatabaseModels/StatusPageSCIMUser";
|
||||
import BadRequestException from "Common/Types/Exception/BadRequestException";
|
||||
import NotFoundException from "Common/Types/Exception/NotFoundException";
|
||||
import LIMIT_MAX from "Common/Types/Database/LimitMax";
|
||||
import {
|
||||
parseNameFromSCIM,
|
||||
formatUserForSCIM,
|
||||
generateServiceProviderConfig,
|
||||
generateUsersListResponse,
|
||||
parseSCIMQueryParams,
|
||||
logSCIMOperation,
|
||||
extractEmailFromSCIM,
|
||||
extractExternalIdFromSCIM,
|
||||
isUserNameEmail,
|
||||
} from "../Utils/SCIMUtils";
|
||||
import Text from "Common/Types/Text";
|
||||
import HashedString from "Common/Types/HashedString";
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
// Helper function to find user by external ID or email
|
||||
const findUserByExternalIdOrEmail: (
|
||||
userName: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
) => Promise<StatusPagePrivateUser | null> = async (
|
||||
userName: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
): Promise<StatusPagePrivateUser | null> => {
|
||||
// First check if userName is an external ID (not an email)
|
||||
if (!isUserNameEmail(userName)) {
|
||||
logSCIMOperation(
|
||||
"User lookup",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Looking for external ID: ${userName}`,
|
||||
);
|
||||
|
||||
// Look up by external ID
|
||||
const scimUser: StatusPageSCIMUser | null = await StatusPageSCIMUserService.findOneBy({
|
||||
query: {
|
||||
externalId: userName,
|
||||
statusPageId: statusPageId,
|
||||
projectId: projectId,
|
||||
scimConfigId: scimConfigId,
|
||||
},
|
||||
select: {
|
||||
statusPagePrivateUserId: true,
|
||||
statusPagePrivateUser: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (scimUser && scimUser.statusPagePrivateUser) {
|
||||
logSCIMOperation(
|
||||
"User lookup",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Found user by external ID: ${scimUser.statusPagePrivateUser.id}`,
|
||||
);
|
||||
return scimUser.statusPagePrivateUser;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to email lookup
|
||||
try {
|
||||
logSCIMOperation(
|
||||
"User lookup",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Looking for email: ${userName}`,
|
||||
);
|
||||
|
||||
const user: StatusPagePrivateUser | null = await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
email: new Email(userName),
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (user) {
|
||||
logSCIMOperation(
|
||||
"User lookup",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Found user by email: ${user.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
return user;
|
||||
} catch (error) {
|
||||
// If email validation fails, userName is likely an external ID but no mapping exists
|
||||
logSCIMOperation(
|
||||
"User lookup",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Email validation failed for: ${userName}, treating as external ID with no mapping`,
|
||||
);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to create or update SCIM user mapping
|
||||
const createOrUpdateSCIMUserMapping: (
|
||||
user: StatusPagePrivateUser,
|
||||
externalId: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
) => Promise<void> = async (
|
||||
user: StatusPagePrivateUser,
|
||||
externalId: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
): Promise<void> => {
|
||||
// Check if mapping already exists
|
||||
const existingMapping: StatusPageSCIMUser | null = await StatusPageSCIMUserService.findOneBy({
|
||||
query: {
|
||||
statusPagePrivateUserId: user.id!,
|
||||
statusPageId: statusPageId,
|
||||
projectId: projectId,
|
||||
scimConfigId: scimConfigId,
|
||||
},
|
||||
select: { _id: true, externalId: true },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (existingMapping) {
|
||||
// Update existing mapping if external ID changed
|
||||
if (existingMapping.externalId !== externalId) {
|
||||
await StatusPageSCIMUserService.updateOneById({
|
||||
id: existingMapping.id!,
|
||||
data: { externalId: externalId },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
logSCIMOperation(
|
||||
"SCIM mapping",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Updated external ID mapping for user ${user.id} from ${existingMapping.externalId} to ${externalId}`,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
// Create new mapping
|
||||
const scimUser: StatusPageSCIMUser = new StatusPageSCIMUser();
|
||||
scimUser.statusPageId = statusPageId;
|
||||
scimUser.projectId = projectId;
|
||||
scimUser.scimConfigId = scimConfigId;
|
||||
scimUser.statusPagePrivateUserId = user.id!;
|
||||
scimUser.externalId = externalId;
|
||||
|
||||
await StatusPageSCIMUserService.create({
|
||||
data: scimUser,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
logSCIMOperation(
|
||||
"SCIM mapping",
|
||||
"status-page",
|
||||
scimConfigId.toString(),
|
||||
`Created external ID mapping for user ${user.id} with external ID ${externalId}`,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Helper function to resolve user ID (could be internal ID or external ID)
|
||||
const resolveUserId: (
|
||||
userIdParam: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
) => Promise<ObjectID | null> = async (
|
||||
userIdParam: string,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
): Promise<ObjectID | null> => {
|
||||
// First try to parse as ObjectID (internal user ID)
|
||||
try {
|
||||
const objectId: ObjectID = new ObjectID(userIdParam);
|
||||
|
||||
// Verify this user exists in the status page
|
||||
const statusPageUser: StatusPagePrivateUser | null = await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
_id: objectId,
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: { _id: true },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (statusPageUser) {
|
||||
return objectId;
|
||||
}
|
||||
} catch (error) {
|
||||
// Not a valid ObjectID, continue to external ID lookup
|
||||
}
|
||||
|
||||
// Try to find by external ID
|
||||
const scimUser: StatusPageSCIMUser | null = await StatusPageSCIMUserService.findOneBy({
|
||||
query: {
|
||||
externalId: userIdParam,
|
||||
statusPageId: statusPageId,
|
||||
projectId: projectId,
|
||||
scimConfigId: scimConfigId,
|
||||
},
|
||||
select: { statusPagePrivateUserId: true },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (scimUser && scimUser.statusPagePrivateUserId) {
|
||||
return scimUser.statusPagePrivateUserId;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
// Helper function to get external ID for a user
|
||||
const getExternalIdForUser: (
|
||||
userId: ObjectID,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
) => Promise<string | null> = async (
|
||||
userId: ObjectID,
|
||||
statusPageId: ObjectID,
|
||||
projectId: ObjectID,
|
||||
scimConfigId: ObjectID,
|
||||
): Promise<string | null> => {
|
||||
const scimUser: StatusPageSCIMUser | null = await StatusPageSCIMUserService.findOneBy({
|
||||
query: {
|
||||
statusPagePrivateUserId: userId,
|
||||
statusPageId: statusPageId,
|
||||
projectId: projectId,
|
||||
scimConfigId: scimConfigId,
|
||||
},
|
||||
select: { externalId: true },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
return scimUser?.externalId || null;
|
||||
};
|
||||
|
||||
// SCIM Service Provider Configuration - GET /status-page-scim/v2/ServiceProviderConfig
|
||||
router.get(
|
||||
"/status-page-scim/v2/:statusPageScimId/ServiceProviderConfig",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: GET ServiceProviderConfig - statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
|
||||
logSCIMOperation(
|
||||
"ServiceProviderConfig",
|
||||
"status-page",
|
||||
req.params["statusPageScimId"]!,
|
||||
);
|
||||
|
||||
const serviceProviderConfig: JSONObject = generateServiceProviderConfig(
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
);
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, serviceProviderConfig);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Status Page Users endpoint - GET /status-page-scim/v2/Users
|
||||
router.get(
|
||||
"/status-page-scim/v2/:statusPageScimId/Users",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: GET Users List - statusPageScimId: ${req.params["statusPageScimId"]}, query: ${JSON.stringify(req.query)}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Users list request for statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
const bearerData: JSONObject =
|
||||
oneuptimeRequest.bearerTokenData as JSONObject;
|
||||
const statusPageId: ObjectID = bearerData["statusPageId"] as ObjectID;
|
||||
const projectId: ObjectID = bearerData["projectId"] as ObjectID;
|
||||
const scimConfig: StatusPageSCIM = bearerData["scimConfig"] as StatusPageSCIM;
|
||||
|
||||
// Parse query parameters
|
||||
const { startIndex, count } = parseSCIMQueryParams(req);
|
||||
const filter: string = req.query["filter"] as string;
|
||||
|
||||
logSCIMOperation(
|
||||
"Users list",
|
||||
"status-page",
|
||||
req.params["statusPageScimId"]!,
|
||||
`statusPageId: ${statusPageId}, startIndex: ${startIndex}, count: ${count}, filter: ${filter || "none"}`,
|
||||
);
|
||||
|
||||
let users: Array<StatusPagePrivateUser> = [];
|
||||
|
||||
// Handle SCIM filter for userName
|
||||
if (filter) {
|
||||
const emailMatch: RegExpMatchArray | null = filter.match(
|
||||
/userName eq "([^"]+)"/i,
|
||||
);
|
||||
if (emailMatch) {
|
||||
const userName: string = emailMatch[1]!;
|
||||
logSCIMOperation(
|
||||
"Users list",
|
||||
"status-page",
|
||||
req.params["statusPageScimId"]!,
|
||||
`filter by userName: ${userName}`,
|
||||
);
|
||||
|
||||
if (userName) {
|
||||
const user: StatusPagePrivateUser | null = await findUserByExternalIdOrEmail(
|
||||
userName,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
if (user) {
|
||||
users = [user];
|
||||
logSCIMOperation(
|
||||
"Users list",
|
||||
"status-page",
|
||||
req.params["statusPageScimId"]!,
|
||||
`found user with id: ${user.id}`,
|
||||
);
|
||||
} else {
|
||||
logSCIMOperation(
|
||||
"Users list",
|
||||
"status-page",
|
||||
req.params["statusPageScimId"]!,
|
||||
`user not found for userName: ${userName}`,
|
||||
);
|
||||
users = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Get all private users for this status page
|
||||
users = await StatusPagePrivateUserService.findBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
skip: 0,
|
||||
limit: LIMIT_MAX,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Users - found ${users.length} users`,
|
||||
);
|
||||
|
||||
// Format users for SCIM with external IDs
|
||||
const formattedUsers: Array<JSONObject> = [];
|
||||
|
||||
for (const user of users) {
|
||||
// Get external ID for this user if it exists
|
||||
const externalId: string | null = await getExternalIdForUser(
|
||||
user.id!,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
const userFormatted: JSONObject = formatUserForSCIM(
|
||||
user,
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
externalId,
|
||||
);
|
||||
|
||||
formattedUsers.push(userFormatted);
|
||||
}
|
||||
|
||||
// Paginate the results
|
||||
const paginatedUsers: Array<JSONObject> = formattedUsers.slice(
|
||||
(startIndex - 1) * count,
|
||||
startIndex * count,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Users response prepared with ${formattedUsers.length} users`,
|
||||
);
|
||||
|
||||
return Response.sendJsonObjectResponse(
|
||||
req,
|
||||
res,
|
||||
generateUsersListResponse(paginatedUsers, startIndex, formattedUsers.length),
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Get Individual Status Page User - GET /status-page-scim/v2/Users/{id}
|
||||
router.get(
|
||||
"/status-page-scim/v2/:statusPageScimId/Users/:userId",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: GET Individual User - statusPageScimId: ${req.params["statusPageScimId"]}, userId: ${req.params["userId"]}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Get individual user request for userId: ${req.params["userId"]}, statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
const bearerData: JSONObject =
|
||||
oneuptimeRequest.bearerTokenData as JSONObject;
|
||||
const statusPageId: ObjectID = bearerData["statusPageId"] as ObjectID;
|
||||
const projectId: ObjectID = bearerData["projectId"] as ObjectID;
|
||||
const scimConfig: StatusPageSCIM = bearerData["scimConfig"] as StatusPageSCIM;
|
||||
const userIdParam: string = req.params["userId"]!;
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Get user - statusPageId: ${statusPageId}, userIdParam: ${userIdParam}`,
|
||||
);
|
||||
|
||||
if (!userIdParam) {
|
||||
throw new BadRequestException("User ID is required");
|
||||
}
|
||||
|
||||
// Resolve user ID (could be internal ID or external ID)
|
||||
const userId: ObjectID | null = await resolveUserId(
|
||||
userIdParam,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
if (!userId) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Get user - could not resolve user ID for param: ${userIdParam}`,
|
||||
);
|
||||
throw new NotFoundException(
|
||||
"User not found or not part of this status page",
|
||||
);
|
||||
}
|
||||
|
||||
// Check if user exists and belongs to this status page
|
||||
const statusPageUser: StatusPagePrivateUser | null =
|
||||
await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
_id: userId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (!statusPageUser) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Get user - user not found for resolved userId: ${userId}`,
|
||||
);
|
||||
throw new NotFoundException(
|
||||
"User not found or not part of this status page",
|
||||
);
|
||||
}
|
||||
|
||||
// Get external ID for this user if it exists
|
||||
const externalId: string | null = await getExternalIdForUser(
|
||||
statusPageUser.id!,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
const user: JSONObject = formatUserForSCIM(
|
||||
statusPageUser,
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
externalId,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Get user - returning user with id: ${statusPageUser.id}`,
|
||||
);
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, user);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Create Status Page User - POST /status-page-scim/v2/Users
|
||||
router.post(
|
||||
"/status-page-scim/v2/:statusPageScimId/Users",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: POST Create User - statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Create user request for statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
const bearerData: JSONObject =
|
||||
oneuptimeRequest.bearerTokenData as JSONObject;
|
||||
const statusPageId: ObjectID = bearerData["statusPageId"] as ObjectID;
|
||||
const projectId: ObjectID = bearerData["projectId"] as ObjectID;
|
||||
const scimConfig: StatusPageSCIM = bearerData[
|
||||
"scimConfig"
|
||||
] as StatusPageSCIM;
|
||||
|
||||
if (!scimConfig.autoProvisionUsers) {
|
||||
throw new BadRequestException(
|
||||
"Auto-provisioning is disabled for this status page",
|
||||
);
|
||||
}
|
||||
|
||||
const scimUser: JSONObject = req.body;
|
||||
const userName: string = extractEmailFromSCIM(scimUser);
|
||||
const externalId: string | null = extractExternalIdFromSCIM(scimUser);
|
||||
const name: string = parseNameFromSCIM(scimUser);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Create user - statusPageId: ${statusPageId}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Request body for Status Page SCIM Create user: ${JSON.stringify(scimUser, null, 2)}`,
|
||||
);
|
||||
|
||||
logger.debug(`Status Page SCIM Create user - userName: ${userName}, externalId: ${externalId}, name: ${name}`);
|
||||
|
||||
// Extract email from emails array if userName is not an email
|
||||
let email: string = "";
|
||||
if (isUserNameEmail(userName)) {
|
||||
email = userName;
|
||||
} else {
|
||||
// Look for email in the emails array
|
||||
const emailsArray: JSONObject[] = scimUser["emails"] as JSONObject[];
|
||||
if (emailsArray && emailsArray.length > 0) {
|
||||
email = emailsArray[0]?.["value"] as string;
|
||||
}
|
||||
}
|
||||
|
||||
if (!email && !externalId) {
|
||||
throw new BadRequestException(
|
||||
"Either a valid email address or external ID is required",
|
||||
);
|
||||
}
|
||||
|
||||
// Check if user already exists (by external ID first, then email)
|
||||
let user: StatusPagePrivateUser | null = null;
|
||||
|
||||
if (externalId) {
|
||||
user = await findUserByExternalIdOrEmail(
|
||||
externalId,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
}
|
||||
|
||||
if (!user && email) {
|
||||
try {
|
||||
user = await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
email: new Email(email),
|
||||
statusPageId: statusPageId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
} catch (error) {
|
||||
// Email validation failed, continue without email lookup
|
||||
logger.debug(`Status Page SCIM Create user - email validation failed for: ${email}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Create user if doesn't exist
|
||||
if (!user) {
|
||||
if (!email) {
|
||||
throw new BadRequestException(
|
||||
"A valid email address is required to create a new user",
|
||||
);
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Create user - creating new user with email: ${email}`,
|
||||
);
|
||||
|
||||
const privateUser: StatusPagePrivateUser = new StatusPagePrivateUser();
|
||||
privateUser.statusPageId = statusPageId;
|
||||
privateUser.email = new Email(email);
|
||||
privateUser.password = new HashedString(Text.generateRandomText(32));
|
||||
privateUser.projectId = projectId;
|
||||
|
||||
// Create new status page private user
|
||||
user = await StatusPagePrivateUserService.create({
|
||||
data: privateUser as any,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
} else {
|
||||
logger.debug(
|
||||
`Status Page SCIM Create user - user already exists with id: ${user.id}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Create or update SCIM user mapping if we have an external ID
|
||||
if (externalId && user.id) {
|
||||
await createOrUpdateSCIMUserMapping(
|
||||
user,
|
||||
externalId,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
}
|
||||
|
||||
const createdUser: JSONObject = formatUserForSCIM(
|
||||
user,
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
externalId,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Create user - returning created user with id: ${user.id}`,
|
||||
);
|
||||
|
||||
res.status(201);
|
||||
return Response.sendJsonObjectResponse(req, res, createdUser);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Update Status Page User - PUT /status-page-scim/v2/Users/{id}
|
||||
router.put(
|
||||
"/status-page-scim/v2/:statusPageScimId/Users/:userId",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: PUT Update User - statusPageScimId: ${req.params["statusPageScimId"]}, userId: ${req.params["userId"]}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user request for userId: ${req.params["userId"]}, statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
const bearerData: JSONObject =
|
||||
oneuptimeRequest.bearerTokenData as JSONObject;
|
||||
const statusPageId: ObjectID = bearerData["statusPageId"] as ObjectID;
|
||||
const projectId: ObjectID = bearerData["projectId"] as ObjectID;
|
||||
const scimConfig: StatusPageSCIM = bearerData["scimConfig"] as StatusPageSCIM;
|
||||
const userIdParam: string = req.params["userId"]!;
|
||||
const scimUser: JSONObject = req.body;
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - statusPageId: ${statusPageId}, userIdParam: ${userIdParam}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Request body for Status Page SCIM Update user: ${JSON.stringify(scimUser, null, 2)}`,
|
||||
);
|
||||
|
||||
if (!userIdParam) {
|
||||
throw new BadRequestException("User ID is required");
|
||||
}
|
||||
|
||||
// Resolve user ID (could be internal ID or external ID)
|
||||
const userId: ObjectID | null = await resolveUserId(
|
||||
userIdParam,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
if (!userId) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - could not resolve user ID for param: ${userIdParam}`,
|
||||
);
|
||||
throw new NotFoundException(
|
||||
"User not found or not part of this status page",
|
||||
);
|
||||
}
|
||||
|
||||
// Check if user exists and belongs to this status page
|
||||
const statusPageUser: StatusPagePrivateUser | null =
|
||||
await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
_id: userId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (!statusPageUser) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - user not found for resolved userId: ${userId}`,
|
||||
);
|
||||
throw new NotFoundException(
|
||||
"User not found or not part of this status page",
|
||||
);
|
||||
}
|
||||
|
||||
// Update user information
|
||||
const userName: string = extractEmailFromSCIM(scimUser);
|
||||
const externalId: string | null = extractExternalIdFromSCIM(scimUser);
|
||||
const active: boolean = scimUser["active"] as boolean;
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - userName: ${userName}, externalId: ${externalId}, active: ${active}`,
|
||||
);
|
||||
|
||||
// Extract email from emails array if userName is not an email
|
||||
let email: string = "";
|
||||
if (isUserNameEmail(userName)) {
|
||||
email = userName;
|
||||
} else {
|
||||
// Look for email in the emails array
|
||||
const emailsArray: JSONObject[] = scimUser["emails"] as JSONObject[];
|
||||
if (emailsArray && emailsArray.length > 0) {
|
||||
email = emailsArray[0]?.["value"] as string;
|
||||
}
|
||||
}
|
||||
|
||||
// Create or update SCIM user mapping if we have an external ID
|
||||
if (externalId) {
|
||||
await createOrUpdateSCIMUserMapping(
|
||||
statusPageUser,
|
||||
externalId,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
}
|
||||
|
||||
// Handle user deactivation by deleting from status page
|
||||
if (active === false) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - user marked as inactive, removing from status page`,
|
||||
);
|
||||
|
||||
if (scimConfig.autoDeprovisionUsers) {
|
||||
await StatusPagePrivateUserService.deleteOneById({
|
||||
id: userId,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - user removed from status page`,
|
||||
);
|
||||
|
||||
// Return empty response for deleted user
|
||||
res.status(204);
|
||||
return Response.sendJsonObjectResponse(req, res, {
|
||||
message: "User deprovisioned",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update email if provided and changed
|
||||
if (email && email !== statusPageUser.email?.toString()) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - updating email from ${statusPageUser.email?.toString()} to ${email}`,
|
||||
);
|
||||
|
||||
await StatusPagePrivateUserService.updateOneById({
|
||||
id: userId,
|
||||
data: { email: new Email(email) },
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
// Fetch updated user
|
||||
const updatedUser: StatusPagePrivateUser | null = await StatusPagePrivateUserService.findOneById({
|
||||
id: userId,
|
||||
select: {
|
||||
_id: true,
|
||||
email: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (updatedUser) {
|
||||
const userExternalId: string | null = await getExternalIdForUser(
|
||||
updatedUser.id!,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
const user: JSONObject = formatUserForSCIM(
|
||||
updatedUser,
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
userExternalId,
|
||||
);
|
||||
return Response.sendJsonObjectResponse(req, res, user);
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Update user - no updates made, returning existing user`,
|
||||
);
|
||||
|
||||
// If no updates were made, return the existing user
|
||||
const userExternalId: string | null = await getExternalIdForUser(
|
||||
statusPageUser.id!,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
const user: JSONObject = formatUserForSCIM(
|
||||
statusPageUser,
|
||||
req,
|
||||
req.params["statusPageScimId"]!,
|
||||
"status-page",
|
||||
userExternalId,
|
||||
);
|
||||
|
||||
return Response.sendJsonObjectResponse(req, res, user);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
// Delete Status Page User - DELETE /status-page-scim/v2/Users/{id}
|
||||
router.delete(
|
||||
"/status-page-scim/v2/:statusPageScimId/Users/:userId",
|
||||
SCIMMiddleware.isAuthorizedSCIMRequest,
|
||||
async (req: ExpressRequest, res: ExpressResponse): Promise<void> => {
|
||||
try {
|
||||
logger.debug(
|
||||
`🔗 STATUS PAGE SCIM API HIT: DELETE User - statusPageScimId: ${req.params["statusPageScimId"]}, userId: ${req.params["userId"]}`,
|
||||
);
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Delete user request for userId: ${req.params["userId"]}, statusPageScimId: ${req.params["statusPageScimId"]}`,
|
||||
);
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
const bearerData: JSONObject =
|
||||
oneuptimeRequest.bearerTokenData as JSONObject;
|
||||
const statusPageId: ObjectID = bearerData["statusPageId"] as ObjectID;
|
||||
const projectId: ObjectID = bearerData["projectId"] as ObjectID;
|
||||
const scimConfig: StatusPageSCIM = bearerData["scimConfig"] as StatusPageSCIM;
|
||||
const userIdParam: string = req.params["userId"]!;
|
||||
|
||||
if (!scimConfig.autoDeprovisionUsers) {
|
||||
throw new BadRequestException(
|
||||
"Auto-deprovisioning is disabled for this status page",
|
||||
);
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Delete user - statusPageId: ${statusPageId}, userIdParam: ${userIdParam}`,
|
||||
);
|
||||
|
||||
if (!userIdParam) {
|
||||
throw new BadRequestException("User ID is required");
|
||||
}
|
||||
|
||||
// Resolve user ID (could be internal ID or external ID)
|
||||
const userId: ObjectID | null = await resolveUserId(
|
||||
userIdParam,
|
||||
statusPageId,
|
||||
projectId,
|
||||
scimConfig.id!,
|
||||
);
|
||||
|
||||
if (!userId) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Delete user - could not resolve user ID for param: ${userIdParam}`,
|
||||
);
|
||||
throw new NotFoundException("User not found");
|
||||
}
|
||||
|
||||
// Check if user exists and belongs to this status page
|
||||
const statusPageUser: StatusPagePrivateUser | null =
|
||||
await StatusPagePrivateUserService.findOneBy({
|
||||
query: {
|
||||
statusPageId: statusPageId,
|
||||
_id: userId,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (!statusPageUser) {
|
||||
logger.debug(
|
||||
`Status Page SCIM Delete user - user not found for resolved userId: ${userId}`,
|
||||
);
|
||||
// SCIM spec says to return 404 for non-existent resources
|
||||
throw new NotFoundException("User not found");
|
||||
}
|
||||
|
||||
// Delete the user from status page
|
||||
await StatusPagePrivateUserService.deleteOneById({
|
||||
id: userId,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
logger.debug(
|
||||
`Status Page SCIM Delete user - user deleted successfully for userId: ${userId}`,
|
||||
);
|
||||
|
||||
// Return 204 No Content for successful deletion
|
||||
res.status(204);
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
return Response.sendErrorResponse(req, res, err as BadRequestException);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
export default router;
|
||||
@@ -1,8 +1,10 @@
|
||||
import AuthenticationAPI from "./API/Authentication";
|
||||
import ResellerAPI from "./API/Reseller";
|
||||
import SsoAPI from "./API/SSO";
|
||||
import SCIMAPI from "./API/SCIM";
|
||||
import StatusPageAuthenticationAPI from "./API/StatusPageAuthentication";
|
||||
import StatusPageSsoAPI from "./API/StatusPageSSO";
|
||||
import StatusPageSCIMAPI from "./API/StatusPageSCIM";
|
||||
import FeatureSet from "Common/Server/Types/FeatureSet";
|
||||
import Express, { ExpressApplication } from "Common/Server/Utils/Express";
|
||||
import "ejs";
|
||||
@@ -19,6 +21,10 @@ const IdentityFeatureSet: FeatureSet = {
|
||||
|
||||
app.use([`/${APP_NAME}`, "/"], SsoAPI);
|
||||
|
||||
app.use([`/${APP_NAME}`, "/"], SCIMAPI);
|
||||
|
||||
app.use([`/${APP_NAME}`, "/"], StatusPageSCIMAPI);
|
||||
|
||||
app.use([`/${APP_NAME}`, "/"], StatusPageSsoAPI);
|
||||
|
||||
app.use(
|
||||
|
||||
301
App/FeatureSet/Identity/Utils/SCIMUtils.ts
Normal file
301
App/FeatureSet/Identity/Utils/SCIMUtils.ts
Normal file
@@ -0,0 +1,301 @@
|
||||
import { ExpressRequest } from "Common/Server/Utils/Express";
|
||||
import logger from "Common/Server/Utils/Logger";
|
||||
import { JSONObject } from "Common/Types/JSON";
|
||||
import Email from "Common/Types/Email";
|
||||
import Name from "Common/Types/Name";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
|
||||
/**
|
||||
* Shared SCIM utility functions for both Project SCIM and Status Page SCIM
|
||||
*/
|
||||
|
||||
// Base interface for SCIM user-like objects - compatible with User model
|
||||
export interface SCIMUser {
|
||||
id?: ObjectID | null;
|
||||
email?: Email;
|
||||
name?: Name | string;
|
||||
createdAt?: Date;
|
||||
updatedAt?: Date;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse name information from SCIM user payload
|
||||
*/
|
||||
export const parseNameFromSCIM: (scimUser: JSONObject) => string = (
|
||||
scimUser: JSONObject,
|
||||
): string => {
|
||||
logger.debug(
|
||||
`SCIM - Parsing name from SCIM user: ${JSON.stringify(scimUser, null, 2)}`,
|
||||
);
|
||||
|
||||
const givenName: string =
|
||||
((scimUser["name"] as JSONObject)?.["givenName"] as string) || "";
|
||||
const familyName: string =
|
||||
((scimUser["name"] as JSONObject)?.["familyName"] as string) || "";
|
||||
const formattedName: string = (scimUser["name"] as JSONObject)?.[
|
||||
"formatted"
|
||||
] as string;
|
||||
|
||||
// Construct full name: prefer formatted, then combine given+family, then fallback to displayName
|
||||
if (formattedName) {
|
||||
return formattedName;
|
||||
} else if (givenName || familyName) {
|
||||
return `${givenName} ${familyName}`.trim();
|
||||
} else if (scimUser["displayName"]) {
|
||||
return scimUser["displayName"] as string;
|
||||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse full name into SCIM name format
|
||||
*/
|
||||
export const parseNameToSCIMFormat: (fullName: string) => {
|
||||
givenName: string;
|
||||
familyName: string;
|
||||
formatted: string;
|
||||
} = (
|
||||
fullName: string,
|
||||
): { givenName: string; familyName: string; formatted: string } => {
|
||||
const nameParts: string[] = fullName.trim().split(/\s+/);
|
||||
const givenName: string = nameParts[0] || "";
|
||||
const familyName: string = nameParts.slice(1).join(" ") || "";
|
||||
|
||||
return {
|
||||
givenName,
|
||||
familyName,
|
||||
formatted: fullName,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Format user object for SCIM response
|
||||
*/
|
||||
export const formatUserForSCIM: (
|
||||
user: SCIMUser,
|
||||
req: ExpressRequest,
|
||||
scimId: string,
|
||||
scimType: "project" | "status-page",
|
||||
externalId?: string | null,
|
||||
) => JSONObject = (
|
||||
user: SCIMUser,
|
||||
req: ExpressRequest,
|
||||
scimId: string,
|
||||
scimType: "project" | "status-page",
|
||||
externalId?: string | null,
|
||||
): JSONObject => {
|
||||
const baseUrl: string = `${req.protocol}://${req.get("host")}`;
|
||||
const userName: string = externalId || user.email?.toString() || "";
|
||||
const email: string = user.email?.toString() || "";
|
||||
const fullName: string =
|
||||
user.name?.toString() || email.split("@")[0] || "Unknown User";
|
||||
|
||||
const nameData: { givenName: string; familyName: string; formatted: string } =
|
||||
parseNameToSCIMFormat(fullName);
|
||||
|
||||
// Determine the correct endpoint path based on SCIM type
|
||||
const endpointPath: string =
|
||||
scimType === "project"
|
||||
? `/scim/v2/${scimId}/Users/${user.id?.toString()}`
|
||||
: `/status-page-scim/v2/${scimId}/Users/${user.id?.toString()}`;
|
||||
|
||||
return {
|
||||
schemas: ["urn:ietf:params:scim:schemas:core:2.0:User"],
|
||||
id: user.id?.toString(),
|
||||
userName: userName,
|
||||
displayName: nameData.formatted,
|
||||
name: {
|
||||
formatted: nameData.formatted,
|
||||
familyName: nameData.familyName,
|
||||
givenName: nameData.givenName,
|
||||
},
|
||||
emails: [
|
||||
{
|
||||
value: email,
|
||||
type: "work",
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
active: true,
|
||||
meta: {
|
||||
resourceType: "User",
|
||||
created: user.createdAt?.toISOString(),
|
||||
lastModified: user.updatedAt?.toISOString(),
|
||||
location: `${baseUrl}${endpointPath}`,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract email from SCIM user payload
|
||||
*/
|
||||
export const extractEmailFromSCIM: (scimUser: JSONObject) => string = (
|
||||
scimUser: JSONObject,
|
||||
): string => {
|
||||
return (
|
||||
(scimUser["userName"] as string) ||
|
||||
((scimUser["emails"] as JSONObject[])?.[0]?.["value"] as string) ||
|
||||
""
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract external ID from SCIM user payload (for non-email userNames)
|
||||
*/
|
||||
export const extractExternalIdFromSCIM: (scimUser: JSONObject) => string | null = (
|
||||
scimUser: JSONObject,
|
||||
): string | null => {
|
||||
const userName: string = scimUser["userName"] as string;
|
||||
if (!userName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Check if userName is not an email - if it's not a valid email format, treat it as external ID
|
||||
const emailRegex: RegExp = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
if (!emailRegex.test(userName)) {
|
||||
return userName;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a userName field contains an email or external ID
|
||||
*/
|
||||
export const isUserNameEmail: (userName: string) => boolean = (
|
||||
userName: string,
|
||||
): boolean => {
|
||||
if (!userName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const emailRegex: RegExp = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(userName);
|
||||
};
|
||||
|
||||
/**
|
||||
* Extract active status from SCIM user payload
|
||||
*/
|
||||
export const extractActiveFromSCIM: (scimUser: JSONObject) => boolean = (
|
||||
scimUser: JSONObject,
|
||||
): boolean => {
|
||||
return scimUser["active"] !== false; // Default to true if not specified
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate SCIM ServiceProviderConfig response
|
||||
*/
|
||||
export const generateServiceProviderConfig: (
|
||||
req: ExpressRequest,
|
||||
scimId: string,
|
||||
scimType: "project" | "status-page",
|
||||
documentationUrl?: string,
|
||||
) => JSONObject = (
|
||||
req: ExpressRequest,
|
||||
scimId: string,
|
||||
scimType: "project" | "status-page",
|
||||
documentationUrl: string = "https://oneuptime.com/docs/identity/scim",
|
||||
): JSONObject => {
|
||||
const baseUrl: string = `${req.protocol}://${req.get("host")}`;
|
||||
const endpointPath: string =
|
||||
scimType === "project"
|
||||
? `/scim/v2/${scimId}`
|
||||
: `/status-page-scim/v2/${scimId}`;
|
||||
|
||||
return {
|
||||
schemas: ["urn:ietf:params:scim:schemas:core:2.0:ServiceProviderConfig"],
|
||||
documentationUri: documentationUrl,
|
||||
patch: {
|
||||
supported: true,
|
||||
},
|
||||
bulk: {
|
||||
supported: true,
|
||||
maxOperations: 1000,
|
||||
maxPayloadSize: 1048576,
|
||||
},
|
||||
filter: {
|
||||
supported: true,
|
||||
maxResults: 200,
|
||||
},
|
||||
changePassword: {
|
||||
supported: false,
|
||||
},
|
||||
sort: {
|
||||
supported: true,
|
||||
},
|
||||
etag: {
|
||||
supported: false,
|
||||
},
|
||||
authenticationSchemes: [
|
||||
{
|
||||
type: "httpbearer",
|
||||
name: "HTTP Bearer",
|
||||
description: "Authentication scheme using HTTP Bearer Token",
|
||||
primary: true,
|
||||
},
|
||||
],
|
||||
meta: {
|
||||
location: `${baseUrl}${endpointPath}/ServiceProviderConfig`,
|
||||
resourceType: "ServiceProviderConfig",
|
||||
created: "2023-01-01T00:00:00Z",
|
||||
lastModified: "2023-01-01T00:00:00Z",
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate SCIM ListResponse for users
|
||||
*/
|
||||
export const generateUsersListResponse: (
|
||||
users: JSONObject[],
|
||||
startIndex: number,
|
||||
totalResults: number,
|
||||
) => JSONObject = (
|
||||
users: JSONObject[],
|
||||
startIndex: number,
|
||||
totalResults: number,
|
||||
): JSONObject => {
|
||||
return {
|
||||
schemas: ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
|
||||
totalResults: totalResults,
|
||||
startIndex: startIndex,
|
||||
itemsPerPage: users.length,
|
||||
Resources: users,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse query parameters for SCIM list requests
|
||||
*/
|
||||
export const parseSCIMQueryParams: (req: ExpressRequest) => {
|
||||
startIndex: number;
|
||||
count: number;
|
||||
} = (req: ExpressRequest): { startIndex: number; count: number } => {
|
||||
const startIndex: number = parseInt(req.query["startIndex"] as string) || 1;
|
||||
const count: number = Math.min(
|
||||
parseInt(req.query["count"] as string) || 100,
|
||||
200, // SCIM recommended max
|
||||
);
|
||||
|
||||
return { startIndex, count };
|
||||
};
|
||||
|
||||
/**
|
||||
* Log SCIM operation with consistent format
|
||||
*/
|
||||
export const logSCIMOperation: (
|
||||
operation: string,
|
||||
scimType: "project" | "status-page",
|
||||
scimId: string,
|
||||
details?: string,
|
||||
) => void = (
|
||||
operation: string,
|
||||
scimType: "project" | "status-page",
|
||||
scimId: string,
|
||||
details?: string,
|
||||
): void => {
|
||||
const logPrefix: string =
|
||||
scimType === "project" ? "Project SCIM" : "Status Page SCIM";
|
||||
const message: string = `${logPrefix} ${operation} - scimId: ${scimId}${details ? `, ${details}` : ""}`;
|
||||
logger.debug(message);
|
||||
};
|
||||
@@ -67,7 +67,6 @@
|
||||
<link rel="apple-touch-icon-precomposed" href="/img/ou-wb.svg">
|
||||
<link rel="icon" href="/img/ou-wb.svg">
|
||||
<link rel="image_src" type="image/png" href="/img/hou-wb.svg">
|
||||
<link rel="canonical" href="/">
|
||||
<link rel="manifest" href="/manifest.json">
|
||||
<meta property="og:title" content="OneUptime - One Complete Observability platform.">
|
||||
<meta property="og:url" content="https://oneuptime.com">
|
||||
|
||||
@@ -31,6 +31,22 @@ router.post(
|
||||
userOnCallLogTimelineId:
|
||||
(body["userOnCallLogTimelineId"] as ObjectID) || undefined,
|
||||
customTwilioConfig: body["customTwilioConfig"] as any,
|
||||
incidentId: (body["incidentId"] as ObjectID) || undefined,
|
||||
alertId: (body["alertId"] as ObjectID) || undefined,
|
||||
scheduledMaintenanceId:
|
||||
(body["scheduledMaintenanceId"] as ObjectID) || undefined,
|
||||
statusPageId: (body["statusPageId"] as ObjectID) || undefined,
|
||||
statusPageAnnouncementId:
|
||||
(body["statusPageAnnouncementId"] as ObjectID) || undefined,
|
||||
userId: (body["userId"] as ObjectID) || undefined,
|
||||
onCallPolicyId: (body["onCallPolicyId"] as ObjectID) || undefined,
|
||||
onCallPolicyEscalationRuleId:
|
||||
(body["onCallPolicyEscalationRuleId"] as ObjectID) || undefined,
|
||||
onCallDutyPolicyExecutionLogTimelineId:
|
||||
(body["onCallDutyPolicyExecutionLogTimelineId"] as ObjectID) ||
|
||||
undefined,
|
||||
onCallScheduleId: (body["onCallScheduleId"] as ObjectID) || undefined,
|
||||
teamId: (body["teamId"] as ObjectID) || undefined,
|
||||
});
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
|
||||
@@ -43,6 +43,43 @@ router.post(
|
||||
emailServer: mailServer,
|
||||
userOnCallLogTimelineId:
|
||||
(body["userOnCallLogTimelineId"] as ObjectID) || undefined,
|
||||
incidentId: body["incidentId"]
|
||||
? new ObjectID(body["incidentId"].toString())
|
||||
: undefined,
|
||||
alertId: body["alertId"]
|
||||
? new ObjectID(body["alertId"].toString())
|
||||
: undefined,
|
||||
scheduledMaintenanceId: body["scheduledMaintenanceId"]
|
||||
? new ObjectID(body["scheduledMaintenanceId"].toString())
|
||||
: undefined,
|
||||
statusPageId: body["statusPageId"]
|
||||
? new ObjectID(body["statusPageId"].toString())
|
||||
: undefined,
|
||||
statusPageAnnouncementId: body["statusPageAnnouncementId"]
|
||||
? new ObjectID(body["statusPageAnnouncementId"].toString())
|
||||
: undefined,
|
||||
userId: body["userId"]
|
||||
? new ObjectID(body["userId"].toString())
|
||||
: undefined,
|
||||
onCallPolicyId: body["onCallPolicyId"]
|
||||
? new ObjectID(body["onCallPolicyId"].toString())
|
||||
: undefined,
|
||||
onCallPolicyEscalationRuleId: body["onCallPolicyEscalationRuleId"]
|
||||
? new ObjectID(body["onCallPolicyEscalationRuleId"].toString())
|
||||
: undefined,
|
||||
onCallDutyPolicyExecutionLogTimelineId: body[
|
||||
"onCallDutyPolicyExecutionLogTimelineId"
|
||||
]
|
||||
? new ObjectID(
|
||||
body["onCallDutyPolicyExecutionLogTimelineId"].toString(),
|
||||
)
|
||||
: undefined,
|
||||
onCallScheduleId: body["onCallScheduleId"]
|
||||
? new ObjectID(body["onCallScheduleId"].toString())
|
||||
: undefined,
|
||||
teamId: body["teamId"]
|
||||
? new ObjectID(body["teamId"].toString())
|
||||
: undefined,
|
||||
});
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import PushService from "../Services/PushNotificationService";
|
||||
import ClusterKeyAuthorization from "Common/Server/Middleware/ClusterKeyAuthorization";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
import Express, {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
ExpressRouter,
|
||||
} from "Common/Server/Utils/Express";
|
||||
import Response from "Common/Server/Utils/Response";
|
||||
import { JSONObject } from "Common/Types/JSON";
|
||||
import JSONFunctions from "Common/Types/JSONFunctions";
|
||||
|
||||
const router: ExpressRouter = Express.getRouter();
|
||||
|
||||
router.post(
|
||||
"/send",
|
||||
ClusterKeyAuthorization.isAuthorizedServiceMiddleware,
|
||||
async (req: ExpressRequest, res: ExpressResponse) => {
|
||||
const body: JSONObject = JSONFunctions.deserialize(req.body);
|
||||
|
||||
// Support both new devices format and legacy deviceTokens/deviceNames format
|
||||
let devices: Array<{ token: string; name?: string }> = [];
|
||||
|
||||
if (body["devices"]) {
|
||||
// New format: devices as array of objects
|
||||
devices = body["devices"] as Array<{ token: string; name?: string }>;
|
||||
} else {
|
||||
throw new Error("Invalid request format: 'devices' array is required.");
|
||||
}
|
||||
|
||||
await PushService.send(
|
||||
{
|
||||
devices,
|
||||
deviceType: (body["deviceType"] as any) || "web",
|
||||
message: body["message"] as any,
|
||||
},
|
||||
{
|
||||
projectId: (body["projectId"] as ObjectID) || undefined,
|
||||
isSensitive: (body["isSensitive"] as boolean) || false,
|
||||
userOnCallLogTimelineId:
|
||||
(body["userOnCallLogTimelineId"] as ObjectID) || undefined,
|
||||
incidentId: (body["incidentId"] as ObjectID) || undefined,
|
||||
alertId: (body["alertId"] as ObjectID) || undefined,
|
||||
scheduledMaintenanceId:
|
||||
(body["scheduledMaintenanceId"] as ObjectID) || undefined,
|
||||
statusPageId: (body["statusPageId"] as ObjectID) || undefined,
|
||||
statusPageAnnouncementId:
|
||||
(body["statusPageAnnouncementId"] as ObjectID) || undefined,
|
||||
userId: (body["userId"] as ObjectID) || undefined,
|
||||
onCallPolicyId: (body["onCallPolicyId"] as ObjectID) || undefined,
|
||||
onCallPolicyEscalationRuleId:
|
||||
(body["onCallPolicyEscalationRuleId"] as ObjectID) || undefined,
|
||||
onCallDutyPolicyExecutionLogTimelineId:
|
||||
(body["onCallDutyPolicyExecutionLogTimelineId"] as ObjectID) ||
|
||||
undefined,
|
||||
onCallScheduleId: (body["onCallScheduleId"] as ObjectID) || undefined,
|
||||
teamId: (body["teamId"] as ObjectID) || undefined,
|
||||
},
|
||||
);
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
},
|
||||
);
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -30,6 +30,22 @@ router.post(
|
||||
userOnCallLogTimelineId:
|
||||
(body["userOnCallLogTimelineId"] as ObjectID) || undefined,
|
||||
customTwilioConfig: body["customTwilioConfig"] as any,
|
||||
incidentId: (body["incidentId"] as ObjectID) || undefined,
|
||||
alertId: (body["alertId"] as ObjectID) || undefined,
|
||||
scheduledMaintenanceId:
|
||||
(body["scheduledMaintenanceId"] as ObjectID) || undefined,
|
||||
statusPageId: (body["statusPageId"] as ObjectID) || undefined,
|
||||
statusPageAnnouncementId:
|
||||
(body["statusPageAnnouncementId"] as ObjectID) || undefined,
|
||||
userId: (body["userId"] as ObjectID) || undefined,
|
||||
onCallPolicyId: (body["onCallPolicyId"] as ObjectID) || undefined,
|
||||
onCallPolicyEscalationRuleId:
|
||||
(body["onCallPolicyEscalationRuleId"] as ObjectID) || undefined,
|
||||
onCallDutyPolicyExecutionLogTimelineId:
|
||||
(body["onCallDutyPolicyExecutionLogTimelineId"] as ObjectID) ||
|
||||
undefined,
|
||||
onCallScheduleId: (body["onCallScheduleId"] as ObjectID) || undefined,
|
||||
teamId: (body["teamId"] as ObjectID) || undefined,
|
||||
});
|
||||
|
||||
return Response.sendEmptySuccessResponse(req, res);
|
||||
|
||||
@@ -2,6 +2,7 @@ import CallAPI from "./API/Call";
|
||||
// API
|
||||
import MailAPI from "./API/Mail";
|
||||
import SmsAPI from "./API/SMS";
|
||||
import PushNotificationAPI from "./API/PushNotification";
|
||||
import SMTPConfigAPI from "./API/SMTPConfig";
|
||||
import "./Utils/Handlebars";
|
||||
import FeatureSet from "Common/Server/Types/FeatureSet";
|
||||
@@ -15,6 +16,7 @@ const NotificationFeatureSet: FeatureSet = {
|
||||
|
||||
app.use([`/${APP_NAME}/email`, "/email"], MailAPI);
|
||||
app.use([`/${APP_NAME}/sms`, "/sms"], SmsAPI);
|
||||
app.use([`/${APP_NAME}/push`, "/push"], PushNotificationAPI);
|
||||
app.use([`/${APP_NAME}/call`, "/call"], CallAPI);
|
||||
app.use([`/${APP_NAME}/smtp-config`, "/smtp-config"], SMTPConfigAPI);
|
||||
},
|
||||
|
||||
@@ -28,6 +28,36 @@ import Twilio from "twilio";
|
||||
import { CallInstance } from "twilio/lib/rest/api/v2010/account/call";
|
||||
import Phone from "Common/Types/Phone";
|
||||
|
||||
/**
|
||||
* Extracts the main sayMessage values from a CallRequest's data array for call summary.
|
||||
* Excludes acknowledgment responses, error messages, and other system messages.
|
||||
* @param callRequest The call request containing data array with various objects
|
||||
* @returns A string containing main call content messages separated by newlines
|
||||
*/
|
||||
function extractSayMessagesFromCallRequest(callRequest: CallRequest): string {
|
||||
const sayMessages: string[] = [];
|
||||
|
||||
if (callRequest.data && Array.isArray(callRequest.data)) {
|
||||
for (const item of callRequest.data) {
|
||||
// Check if the item is a Say object with sayMessage
|
||||
if ((item as Say).sayMessage) {
|
||||
sayMessages.push((item as Say).sayMessage);
|
||||
}
|
||||
// Check if the item is a GatherInput with introMessage
|
||||
if ((item as GatherInput).introMessage) {
|
||||
sayMessages.push((item as GatherInput).introMessage);
|
||||
}
|
||||
// NOTE: Excluding noInputMessage and onInputCallRequest messages from summary
|
||||
// as they contain system responses like "Good bye", "Invalid input", "You have acknowledged"
|
||||
// which should not be included in the call summary according to user requirements
|
||||
}
|
||||
}
|
||||
|
||||
return sayMessages.length > 0
|
||||
? sayMessages.join(" ")
|
||||
: "No message content found";
|
||||
}
|
||||
|
||||
export default class CallService {
|
||||
public static async makeCall(
|
||||
callRequest: CallRequest,
|
||||
@@ -36,6 +66,18 @@ export default class CallService {
|
||||
isSensitive?: boolean; // if true, message will not be logged
|
||||
userOnCallLogTimelineId?: ObjectID | undefined; // user notification log timeline id
|
||||
customTwilioConfig?: TwilioConfig | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
},
|
||||
): Promise<void> {
|
||||
let callError: Error | null = null;
|
||||
@@ -82,14 +124,58 @@ export default class CallService {
|
||||
callLog.fromNumber = fromNumber;
|
||||
callLog.callData =
|
||||
options && options.isSensitive
|
||||
? { message: "This call is sensitive and is not logged" }
|
||||
: JSON.parse(JSON.stringify(callRequest));
|
||||
? ({ message: "This call is sensitive and is not logged" } as any)
|
||||
: ({
|
||||
message: extractSayMessagesFromCallRequest(callRequest),
|
||||
} as any);
|
||||
callLog.callCostInUSDCents = 0;
|
||||
|
||||
if (options.projectId) {
|
||||
callLog.projectId = options.projectId;
|
||||
}
|
||||
|
||||
if (options.incidentId) {
|
||||
callLog.incidentId = options.incidentId;
|
||||
}
|
||||
|
||||
if (options.alertId) {
|
||||
callLog.alertId = options.alertId;
|
||||
}
|
||||
|
||||
if (options.scheduledMaintenanceId) {
|
||||
callLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
|
||||
}
|
||||
|
||||
if (options.statusPageId) {
|
||||
callLog.statusPageId = options.statusPageId;
|
||||
}
|
||||
|
||||
if (options.statusPageAnnouncementId) {
|
||||
callLog.statusPageAnnouncementId = options.statusPageAnnouncementId;
|
||||
}
|
||||
|
||||
if (options.userId) {
|
||||
callLog.userId = options.userId;
|
||||
}
|
||||
|
||||
if (options.teamId) {
|
||||
callLog.teamId = options.teamId;
|
||||
}
|
||||
|
||||
// Set OnCall-related fields
|
||||
if (options.onCallPolicyId) {
|
||||
callLog.onCallDutyPolicyId = options.onCallPolicyId;
|
||||
}
|
||||
|
||||
if (options.onCallPolicyEscalationRuleId) {
|
||||
callLog.onCallDutyPolicyEscalationRuleId =
|
||||
options.onCallPolicyEscalationRuleId;
|
||||
}
|
||||
|
||||
if (options.onCallScheduleId) {
|
||||
callLog.onCallDutyPolicyScheduleId = options.onCallScheduleId;
|
||||
}
|
||||
|
||||
let project: Project | null = null;
|
||||
|
||||
// make sure project has enough balance.
|
||||
|
||||
@@ -345,6 +345,18 @@ export default class MailService {
|
||||
emailServer?: EmailServer | undefined;
|
||||
userOnCallLogTimelineId?: ObjectID | undefined;
|
||||
timeout?: number | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
}
|
||||
| undefined,
|
||||
): Promise<void> {
|
||||
@@ -359,6 +371,48 @@ export default class MailService {
|
||||
if (options.emailServer?.id) {
|
||||
emailLog.projectSmtpConfigId = options.emailServer?.id;
|
||||
}
|
||||
|
||||
if (options.incidentId) {
|
||||
emailLog.incidentId = options.incidentId;
|
||||
}
|
||||
|
||||
if (options.alertId) {
|
||||
emailLog.alertId = options.alertId;
|
||||
}
|
||||
|
||||
if (options.scheduledMaintenanceId) {
|
||||
emailLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
|
||||
}
|
||||
|
||||
if (options.statusPageId) {
|
||||
emailLog.statusPageId = options.statusPageId;
|
||||
}
|
||||
|
||||
if (options.statusPageAnnouncementId) {
|
||||
emailLog.statusPageAnnouncementId = options.statusPageAnnouncementId;
|
||||
}
|
||||
|
||||
if (options.userId) {
|
||||
emailLog.userId = options.userId;
|
||||
}
|
||||
|
||||
if (options.teamId) {
|
||||
emailLog.teamId = options.teamId;
|
||||
}
|
||||
|
||||
// Set OnCall-related fields
|
||||
if (options.onCallPolicyId) {
|
||||
emailLog.onCallDutyPolicyId = options.onCallPolicyId;
|
||||
}
|
||||
|
||||
if (options.onCallPolicyEscalationRuleId) {
|
||||
emailLog.onCallDutyPolicyEscalationRuleId =
|
||||
options.onCallPolicyEscalationRuleId;
|
||||
}
|
||||
|
||||
if (options.onCallScheduleId) {
|
||||
emailLog.onCallDutyPolicyScheduleId = options.onCallScheduleId;
|
||||
}
|
||||
}
|
||||
|
||||
// default vars.
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import PushNotificationRequest from "Common/Types/PushNotification/PushNotificationRequest";
|
||||
import ObjectID from "Common/Types/ObjectID";
|
||||
import PushNotificationServiceCommon from "Common/Server/Services/PushNotificationService";
|
||||
|
||||
export default class PushNotificationService {
|
||||
public static async send(
|
||||
request: PushNotificationRequest,
|
||||
options: {
|
||||
projectId?: ObjectID | undefined;
|
||||
isSensitive?: boolean;
|
||||
userOnCallLogTimelineId?: ObjectID | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
} = {},
|
||||
): Promise<void> {
|
||||
// Delegate to Common service which now handles logging and timeline updates
|
||||
await PushNotificationServiceCommon.sendPushNotification(request, {
|
||||
projectId: options.projectId,
|
||||
isSensitive: Boolean(options.isSensitive),
|
||||
userOnCallLogTimelineId: options.userOnCallLogTimelineId,
|
||||
incidentId: options.incidentId,
|
||||
alertId: options.alertId,
|
||||
scheduledMaintenanceId: options.scheduledMaintenanceId,
|
||||
statusPageId: options.statusPageId,
|
||||
statusPageAnnouncementId: options.statusPageAnnouncementId,
|
||||
userId: options.userId,
|
||||
onCallPolicyId: options.onCallPolicyId,
|
||||
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
||||
onCallDutyPolicyExecutionLogTimelineId:
|
||||
options.onCallDutyPolicyExecutionLogTimelineId,
|
||||
onCallScheduleId: options.onCallScheduleId,
|
||||
teamId: options.teamId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,18 @@ export default class SmsService {
|
||||
customTwilioConfig?: TwilioConfig | undefined;
|
||||
isSensitive?: boolean; // if true, message will not be logged
|
||||
userOnCallLogTimelineId?: ObjectID | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
},
|
||||
): Promise<void> {
|
||||
let smsError: Error | null = null;
|
||||
@@ -71,6 +83,48 @@ export default class SmsService {
|
||||
smsLog.projectId = options.projectId;
|
||||
}
|
||||
|
||||
if (options.incidentId) {
|
||||
smsLog.incidentId = options.incidentId;
|
||||
}
|
||||
|
||||
if (options.alertId) {
|
||||
smsLog.alertId = options.alertId;
|
||||
}
|
||||
|
||||
if (options.scheduledMaintenanceId) {
|
||||
smsLog.scheduledMaintenanceId = options.scheduledMaintenanceId;
|
||||
}
|
||||
|
||||
if (options.statusPageId) {
|
||||
smsLog.statusPageId = options.statusPageId;
|
||||
}
|
||||
|
||||
if (options.statusPageAnnouncementId) {
|
||||
smsLog.statusPageAnnouncementId = options.statusPageAnnouncementId;
|
||||
}
|
||||
|
||||
if (options.userId) {
|
||||
smsLog.userId = options.userId;
|
||||
}
|
||||
|
||||
if (options.teamId) {
|
||||
smsLog.teamId = options.teamId;
|
||||
}
|
||||
|
||||
// Set OnCall-related fields
|
||||
if (options.onCallPolicyId) {
|
||||
smsLog.onCallDutyPolicyId = options.onCallPolicyId;
|
||||
}
|
||||
|
||||
if (options.onCallPolicyEscalationRuleId) {
|
||||
smsLog.onCallDutyPolicyEscalationRuleId =
|
||||
options.onCallPolicyEscalationRuleId;
|
||||
}
|
||||
|
||||
if (options.onCallScheduleId) {
|
||||
smsLog.onCallDutyPolicyScheduleId = options.onCallScheduleId;
|
||||
}
|
||||
|
||||
const twilioConfig: TwilioConfig | null =
|
||||
options.customTwilioConfig || (await getTwilioConfig());
|
||||
|
||||
|
||||
@@ -4,5 +4,13 @@
|
||||
"ignore": [
|
||||
"greenlock.d/*"
|
||||
],
|
||||
"exec": "node --inspect=0.0.0.0:9229 --require ts-node/register Index.ts"
|
||||
"watchOptions": {
|
||||
"useFsEvents": false,
|
||||
"interval": 500
|
||||
},
|
||||
"env": {
|
||||
"TS_NODE_TRANSPILE_ONLY": "1",
|
||||
"TS_NODE_FILES": "false"
|
||||
},
|
||||
"exec": "node --inspect=0.0.0.0:9229 -r ts-node/register/transpile-only Index.ts"
|
||||
}
|
||||
@@ -1,5 +1,14 @@
|
||||
import Project from "./Project";
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
import User from "./User";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicySchedule from "./OnCallDutyPolicySchedule";
|
||||
import Team from "./Team";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import CallStatus from "../../Types/Call/CallStatus";
|
||||
@@ -256,6 +265,575 @@ export default class CallLog extends BaseModel {
|
||||
})
|
||||
public callCostInUSDCents?: number = undefined;
|
||||
|
||||
// Relations to resources that triggered this Call (nullable)
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Incident associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of Incident associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who initiated this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "User ID",
|
||||
description: "ID of User who initiated this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Alert associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of Alert associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "Scheduled Maintenance",
|
||||
description: "Scheduled Maintenance associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled Maintenance ID",
|
||||
description:
|
||||
"ID of Scheduled Maintenance associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Status Page associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of Status Page associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageAnnouncementId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageAnnouncement,
|
||||
title: "Status Page Announcement",
|
||||
description: "Status Page Announcement associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageAnnouncement;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageAnnouncementId" })
|
||||
public statusPageAnnouncement?: StatusPageAnnouncement = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page Announcement ID",
|
||||
description:
|
||||
"ID of Status Page Announcement associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageAnnouncementId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicy,
|
||||
title: "On-Call Duty Policy",
|
||||
description: "On-Call Duty Policy associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicy;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyId" })
|
||||
public onCallDutyPolicy?: OnCallDutyPolicy = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy ID",
|
||||
description: "ID of On-Call Duty Policy associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyEscalationRuleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicyEscalationRule,
|
||||
title: "On-Call Duty Policy Escalation Rule",
|
||||
description:
|
||||
"On-Call Duty Policy Escalation Rule associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicyEscalationRule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyEscalationRuleId" })
|
||||
public onCallDutyPolicyEscalationRule?: OnCallDutyPolicyEscalationRule =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Escalation Rule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Escalation Rule associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyEscalationRuleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyScheduleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicySchedule,
|
||||
title: "On-Call Duty Policy Schedule",
|
||||
description:
|
||||
"On-Call Duty Policy Schedule associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicySchedule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyScheduleId" })
|
||||
public onCallDutyPolicySchedule?: OnCallDutyPolicySchedule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Schedule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Schedule associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyScheduleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "teamId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Team,
|
||||
title: "Team",
|
||||
description: "Team associated with this Call (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "teamId" })
|
||||
public team?: Team = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadCallLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Team ID",
|
||||
description: "ID of Team associated with this Call (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public teamId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
|
||||
@@ -729,6 +729,7 @@ export default class CopilotAction extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Is Priority",
|
||||
description: "Is Priority",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
|
||||
@@ -1,6 +1,15 @@
|
||||
import Project from "./Project";
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import StatusPage from "./StatusPage";
|
||||
import ProjectSmtpConfig from "./ProjectSmtpConfig";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
import User from "./User";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicySchedule from "./OnCallDutyPolicySchedule";
|
||||
import Team from "./Team";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
@@ -289,6 +298,576 @@ export default class EmailLog extends BaseModel {
|
||||
})
|
||||
public projectSmtpConfigId?: ObjectID = undefined;
|
||||
|
||||
// Relations to resources that triggered this email (nullable)
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Incident associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of Incident associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who initiated this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "User ID",
|
||||
description: "ID of User who initiated this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Alert associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of Alert associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "Scheduled Maintenance",
|
||||
description: "Scheduled Maintenance associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled Maintenance ID",
|
||||
description:
|
||||
"ID of Scheduled Maintenance associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Status Page associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of Status Page associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageAnnouncementId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageAnnouncement,
|
||||
title: "Status Page Announcement",
|
||||
description: "Status Page Announcement associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageAnnouncement;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageAnnouncementId" })
|
||||
public statusPageAnnouncement?: StatusPageAnnouncement = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page Announcement ID",
|
||||
description:
|
||||
"ID of Status Page Announcement associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageAnnouncementId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicy,
|
||||
title: "On-Call Duty Policy",
|
||||
description: "On-Call Duty Policy associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicy;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyId" })
|
||||
public onCallDutyPolicy?: OnCallDutyPolicy = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyEscalationRuleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicyEscalationRule,
|
||||
title: "On-Call Duty Policy Escalation Rule",
|
||||
description:
|
||||
"On-Call Duty Policy Escalation Rule associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicyEscalationRule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyEscalationRuleId" })
|
||||
public onCallDutyPolicyEscalationRule?: OnCallDutyPolicyEscalationRule =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Escalation Rule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Escalation Rule associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyEscalationRuleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyScheduleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicySchedule,
|
||||
title: "On-Call Duty Policy Schedule",
|
||||
description:
|
||||
"On-Call Duty Policy Schedule associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicySchedule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyScheduleId" })
|
||||
public onCallDutyPolicySchedule?: OnCallDutyPolicySchedule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Schedule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Schedule associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyScheduleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "teamId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Team,
|
||||
title: "Team",
|
||||
description: "Team associated with this email (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "teamId" })
|
||||
public team?: Team = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadEmailLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Team ID",
|
||||
description: "ID of Team associated with this email (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public teamId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
|
||||
@@ -48,6 +48,7 @@ export default class GlobalConfig extends GlobalConfigModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Disable Signup",
|
||||
description: "Should we disable new user sign up to this server?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -338,6 +339,7 @@ export default class GlobalConfig extends GlobalConfigModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Is Master API Key Enabled",
|
||||
description: "Is Master API Key Enabled?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -27,6 +27,7 @@ import IconProp from "../../Types/Icon/IconProp";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
@@ -733,29 +734,74 @@ export default class Incident extends BaseModel {
|
||||
public changeMonitorStatusToId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectIncident,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectIncident,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectIncident,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Are subscribers notified?",
|
||||
description: "Are subscribers notified about this incident?",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status",
|
||||
description:
|
||||
"Status of notification sent to subscribers about this incident",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotifiedOnIncidentCreated?: boolean = undefined;
|
||||
public subscriberNotificationStatusOnIncidentCreated?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectIncident,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectIncident,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectIncident,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
|
||||
@@ -17,6 +17,7 @@ import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@@ -341,29 +342,73 @@ export default class IncidentPublicNote extends BaseModel {
|
||||
public note?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentPublicNote,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentPublicNote,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditIncidentPublicNote,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Are subscribers notified?",
|
||||
description: "Are subscribers notified about this note?",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status",
|
||||
description: "Status of notification sent to subscribers about this note",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotifiedOnNoteCreated?: boolean = undefined;
|
||||
public subscriberNotificationStatusOnNoteCreated?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentPublicNote,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentPublicNote,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditIncidentPublicNote,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
|
||||
@@ -19,6 +19,7 @@ import IconProp from "../../Types/Icon/IconProp";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@@ -391,29 +392,74 @@ export default class IncidentStateTimeline extends BaseModel {
|
||||
public incidentStateId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentStateTimeline,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentStateTimeline,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditIncidentStateTimeline,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Are subscribers notified?",
|
||||
description: "Are subscribers notified about this incident state change?",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status",
|
||||
description:
|
||||
"Status of notification sent to subscribers about this incident state change",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotified?: boolean = undefined;
|
||||
public subscriberNotificationStatus?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentStateTimeline,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadIncidentStateTimeline,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditIncidentStateTimeline,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
@@ -435,6 +481,7 @@ export default class IncidentStateTimeline extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Should subscribers be notified?",
|
||||
description: "Should subscribers be notified about this state change?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -461,6 +508,7 @@ export default class IncidentStateTimeline extends BaseModel {
|
||||
isDefaultValueColumn: true,
|
||||
title: "Are Owners Notified",
|
||||
description: "Are owners notified of state change?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -100,6 +100,8 @@ import ServiceCopilotCodeRepository from "./ServiceCopilotCodeRepository";
|
||||
import ShortLink from "./ShortLink";
|
||||
// SMS
|
||||
import SmsLog from "./SmsLog";
|
||||
import PushNotificationLog from "./PushNotificationLog";
|
||||
import WorkspaceNotificationLog from "./WorkspaceNotificationLog";
|
||||
// Status Page
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
@@ -114,6 +116,7 @@ import StatusPageOwnerTeam from "./StatusPageOwnerTeam";
|
||||
import StatusPageOwnerUser from "./StatusPageOwnerUser";
|
||||
import StatusPagePrivateUser from "./StatusPagePrivateUser";
|
||||
import StatusPageResource from "./StatusPageResource";
|
||||
import StatusPageSCIM from "./StatusPageSCIM";
|
||||
import StatusPageSSO from "./StatusPageSso";
|
||||
import StatusPageSubscriber from "./StatusPageSubscriber";
|
||||
// Team
|
||||
@@ -175,10 +178,13 @@ import WorkspaceUserAuthToken from "./WorkspaceUserAuthToken";
|
||||
import WorkspaceProjectAuthToken from "./WorkspaceProjectAuthToken";
|
||||
import WorkspaceSetting from "./WorkspaceSetting";
|
||||
import WorkspaceNotificationRule from "./WorkspaceNotificationRule";
|
||||
import ProjectUser from "./ProjectUser";
|
||||
|
||||
import OnCallDutyPolicyUserOverride from "./OnCallDutyPolicyUserOverride";
|
||||
import MonitorFeed from "./MonitorFeed";
|
||||
import MetricType from "./MetricType";
|
||||
import ProjectSCIM from "./ProjectSCIM";
|
||||
import SCIMUser from "./SCIMUser";
|
||||
import StatusPageSCIMUser from "./StatusPageSCIMUser";
|
||||
|
||||
const AllModelTypes: Array<{
|
||||
new (): BaseModel;
|
||||
@@ -276,6 +282,7 @@ const AllModelTypes: Array<{
|
||||
|
||||
ProjectSSO,
|
||||
StatusPageSSO,
|
||||
StatusPageSCIM,
|
||||
|
||||
MonitorProbe,
|
||||
|
||||
@@ -289,6 +296,8 @@ const AllModelTypes: Array<{
|
||||
StatusPageOwnerUser,
|
||||
|
||||
SmsLog,
|
||||
PushNotificationLog,
|
||||
WorkspaceNotificationLog,
|
||||
CallLog,
|
||||
EmailLog,
|
||||
|
||||
@@ -373,13 +382,16 @@ const AllModelTypes: Array<{
|
||||
WorkspaceSetting,
|
||||
WorkspaceNotificationRule,
|
||||
|
||||
ProjectUser,
|
||||
|
||||
MonitorFeed,
|
||||
|
||||
MetricType,
|
||||
|
||||
OnCallDutyPolicyTimeLog,
|
||||
|
||||
ProjectSCIM,
|
||||
SCIMUser,
|
||||
|
||||
StatusPageSCIMUser
|
||||
];
|
||||
|
||||
const modelTypeMap: { [key: string]: { new (): BaseModel } } = {};
|
||||
|
||||
@@ -456,6 +456,7 @@ export default class MonitorStatus extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Is Offline State",
|
||||
description: "Is this monitor in offline state?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -455,7 +455,7 @@ export default class OnCallDutyPolicy extends BaseModel {
|
||||
@TableColumn({
|
||||
required: true,
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
type: TableColumnType.Number,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Repeat Policy Times If No One Acknowledges",
|
||||
description:
|
||||
|
||||
@@ -248,6 +248,84 @@ export default class Project extends TenantModel {
|
||||
})
|
||||
public paymentProviderCustomerId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProject,
|
||||
Permission.UnAuthorizedSsoUser,
|
||||
Permission.ProjectUser,
|
||||
],
|
||||
update: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.LongText,
|
||||
title: "Business Details / Billing Address",
|
||||
description:
|
||||
"Business legal name, address and any tax information to appear on invoices.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public businessDetails?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProject,
|
||||
Permission.UnAuthorizedSsoUser,
|
||||
Permission.ProjectUser,
|
||||
],
|
||||
update: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Business Country (ISO Alpha-2)",
|
||||
description:
|
||||
"Two-letter ISO country code for billing address (e.g., US, GB, DE).",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public businessDetailsCountry?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProject,
|
||||
Permission.UnAuthorizedSsoUser,
|
||||
Permission.ProjectUser,
|
||||
],
|
||||
update: [Permission.ProjectOwner, Permission.ManageProjectBilling],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Email,
|
||||
title: "Finance / Accounting Email",
|
||||
description:
|
||||
"Invoices, receipts and billing related notifications will be sent to this email in addition to project owner.",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Email,
|
||||
length: ColumnLength.Email,
|
||||
nullable: true,
|
||||
unique: false,
|
||||
})
|
||||
public financeAccountingEmail?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
|
||||
451
Common/Models/DatabaseModels/ProjectSCIM.ts
Normal file
451
Common/Models/DatabaseModels/ProjectSCIM.ts
Normal file
@@ -0,0 +1,451 @@
|
||||
import Project from "./Project";
|
||||
import Team from "./Team";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
|
||||
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 UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
|
||||
@TableBillingAccessControl({
|
||||
create: PlanType.Scale,
|
||||
read: PlanType.Scale,
|
||||
update: PlanType.Scale,
|
||||
delete: PlanType.Scale,
|
||||
})
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.DeleteProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/project-scim"))
|
||||
@TableMetadata({
|
||||
tableName: "ProjectSCIM",
|
||||
singularName: "SCIM",
|
||||
pluralName: "SCIM",
|
||||
icon: IconProp.Lock,
|
||||
tableDescription: "Manage SCIM auto-provisioning for your project",
|
||||
})
|
||||
@Entity({
|
||||
name: "ProjectSCIM",
|
||||
})
|
||||
export default class ProjectSCIM extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Name",
|
||||
description: "Any friendly name for this SCIM configuration",
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
@UniqueColumnBy("projectId")
|
||||
public name?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Description",
|
||||
description: "Friendly description to help you remember",
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public description?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Bearer Token",
|
||||
description: "Bearer token for SCIM authentication. Keep this secure.",
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public bearerToken?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.EntityArray,
|
||||
modelType: Team,
|
||||
title: "Default Teams",
|
||||
description: "Default teams that new users will be added to via SCIM",
|
||||
})
|
||||
@ManyToMany(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{ eager: false },
|
||||
)
|
||||
@JoinTable({
|
||||
name: "ProjectScimTeam",
|
||||
inverseJoinColumn: {
|
||||
name: "teamId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
joinColumn: {
|
||||
name: "projectScimId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
})
|
||||
public teams?: Array<Team> = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Auto Provision Users",
|
||||
description: "Automatically create users when they are added via SCIM",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: true,
|
||||
})
|
||||
public autoProvisionUsers?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Auto Deprovision Users",
|
||||
description: "Automatically remove users when they are removed via SCIM",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: true,
|
||||
})
|
||||
public autoDeprovisionUsers?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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;
|
||||
}
|
||||
@@ -578,7 +578,11 @@ export default class ProjectSSO extends BaseModel {
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({ isDefaultValueColumn: true, type: TableColumnType.Boolean })
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
|
||||
@@ -1,336 +0,0 @@
|
||||
import Project from "./Project";
|
||||
import Team from "./Team";
|
||||
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 AllowUserQueryWithoutTenant from "../../Types/Database/AllowUserQueryWithoutTenant";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import CurrentUserCanAccessRecordBy from "../../Types/Database/CurrentUserCanAccessRecordBy";
|
||||
import MultiTenentQueryAllowed from "../../Types/Database/MultiTenentQueryAllowed";
|
||||
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,
|
||||
JoinTable,
|
||||
ManyToMany,
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
|
||||
@TableAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
Permission.CurrentUser,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@MultiTenentQueryAllowed(true)
|
||||
@AllowUserQueryWithoutTenant(true)
|
||||
@CurrentUserCanAccessRecordBy("userId")
|
||||
@TenantColumn("projectId")
|
||||
@CrudApiEndpoint(new Route("/project-user"))
|
||||
@Entity({
|
||||
name: "ProjectUser",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "ProjectUser",
|
||||
singularName: "User",
|
||||
pluralName: "Users",
|
||||
icon: IconProp.User,
|
||||
tableDescription:
|
||||
"This model connects users and teams. This is an internal table. Its a view on TeamMembers table.",
|
||||
})
|
||||
export default class ProjectUser extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
Permission.CurrentUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.EntityArray,
|
||||
modelType: Team,
|
||||
title: "Teams",
|
||||
description: "Teams to which this user belongs.",
|
||||
})
|
||||
@ManyToMany(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{ eager: false },
|
||||
)
|
||||
@JoinTable({
|
||||
name: "ProjectUserAcceptedTeams",
|
||||
inverseJoinColumn: {
|
||||
name: "teamId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
joinColumn: {
|
||||
name: "projectUserId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
})
|
||||
public acceptedTeams?: Array<Team> = undefined; // user is accepted to these teams. This is a view on TeamMembers table.
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
Permission.CurrentUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.EntityArray,
|
||||
modelType: Team,
|
||||
title: "Teams",
|
||||
description: "Teams to which this user belongs.",
|
||||
})
|
||||
@ManyToMany(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{ eager: false },
|
||||
)
|
||||
@JoinTable({
|
||||
name: "ProjectUserInvitedTeams",
|
||||
inverseJoinColumn: {
|
||||
name: "teamId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
joinColumn: {
|
||||
name: "projectUserId",
|
||||
referencedColumnName: "_id",
|
||||
},
|
||||
})
|
||||
public invitedTeams?: Array<Team> = undefined; // user is invited to these teams.
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
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: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
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: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ReadProjectTeam,
|
||||
Permission.ProjectMember,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who belongs to this team.",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectTeam,
|
||||
Permission.CurrentUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "User ID",
|
||||
description: "ID of User who belongs to this team",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = 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",
|
||||
modelType: 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;
|
||||
}
|
||||
877
Common/Models/DatabaseModels/PushNotificationLog.ts
Normal file
877
Common/Models/DatabaseModels/PushNotificationLog.ts
Normal file
@@ -0,0 +1,877 @@
|
||||
import Project from "./Project";
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
import User from "./User";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicySchedule from "./OnCallDutyPolicySchedule";
|
||||
import Team from "./Team";
|
||||
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 ColumnLength from "../../Types/Database/ColumnLength";
|
||||
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 PushStatus from "../../Types/PushNotification/PushStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/push-notification-log"))
|
||||
@Entity({
|
||||
name: "PushNotificationLog",
|
||||
})
|
||||
@EnableWorkflow({
|
||||
create: true,
|
||||
delete: false,
|
||||
update: false,
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "PushNotificationLog",
|
||||
singularName: "Push Notification Log",
|
||||
pluralName: "Push Notification Logs",
|
||||
icon: IconProp.Bell,
|
||||
tableDescription:
|
||||
"Logs of all the Push Notifications sent out to all users and subscribers for this project.",
|
||||
})
|
||||
export default class PushNotificationLog extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Title",
|
||||
description: "Title of the push notification",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public title?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Body",
|
||||
description: "Body of the push notification",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.VeryLongText,
|
||||
})
|
||||
public body?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Device Type",
|
||||
description: "Type of device this was sent to (e.g., web)",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public deviceType?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Device Name",
|
||||
description: "Name of the device this was sent to",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public deviceName?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Status Message",
|
||||
description: "Status Message (if any)",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public statusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Status",
|
||||
description: "Status of the push notification",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public status?: PushStatus = undefined;
|
||||
|
||||
// Relations to resources that triggered this push notification (nullable)
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Incident associated with this Push (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of Incident associated with this Push (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who initiated this Push notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "User ID",
|
||||
description: "ID of User who initiated this Push notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Alert associated with this Push (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of Alert associated with this Push (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "Scheduled Maintenance",
|
||||
description: "Scheduled Maintenance associated with this Push (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled Maintenance ID",
|
||||
description:
|
||||
"ID of Scheduled Maintenance associated with this Push (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Status Page associated with this Push (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of Status Page associated with this Push (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageAnnouncementId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageAnnouncement,
|
||||
title: "Status Page Announcement",
|
||||
description: "Status Page Announcement associated with this Push (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageAnnouncement;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageAnnouncementId" })
|
||||
public statusPageAnnouncement?: StatusPageAnnouncement = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page Announcement ID",
|
||||
description:
|
||||
"ID of Status Page Announcement associated with this Push (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageAnnouncementId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicy,
|
||||
title: "On-Call Duty Policy",
|
||||
description:
|
||||
"On-Call Duty Policy associated with this Push Notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicy;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyId" })
|
||||
public onCallDutyPolicy?: OnCallDutyPolicy = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy associated with this Push Notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyEscalationRuleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicyEscalationRule,
|
||||
title: "On-Call Duty Policy Escalation Rule",
|
||||
description:
|
||||
"On-Call Duty Policy Escalation Rule associated with this Push Notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicyEscalationRule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyEscalationRuleId" })
|
||||
public onCallDutyPolicyEscalationRule?: OnCallDutyPolicyEscalationRule =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Escalation Rule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Escalation Rule associated with this Push Notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyEscalationRuleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyScheduleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicySchedule,
|
||||
title: "On-Call Duty Policy Schedule",
|
||||
description:
|
||||
"On-Call Duty Policy Schedule associated with this Push Notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicySchedule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyScheduleId" })
|
||||
public onCallDutyPolicySchedule?: OnCallDutyPolicySchedule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Schedule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Schedule associated with this Push Notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyScheduleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "teamId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Team,
|
||||
title: "Team",
|
||||
description: "Team associated with this Push Notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "teamId" })
|
||||
public team?: Team = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Team ID",
|
||||
description: "ID of Team associated with this Push Notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public teamId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
modelType: 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;
|
||||
}
|
||||
@@ -269,6 +269,7 @@ export default class Reseller extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Enable Telemetry Features",
|
||||
description: "Should we enable telemetry features for this reseller?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
|
||||
287
Common/Models/DatabaseModels/SCIMUser.ts
Normal file
287
Common/Models/DatabaseModels/SCIMUser.ts
Normal file
@@ -0,0 +1,287 @@
|
||||
import Project from "./Project";
|
||||
import ProjectSCIM from "./ProjectSCIM";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
|
||||
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 Permission from "../../Types/Permission";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
|
||||
@TableBillingAccessControl({
|
||||
create: PlanType.Scale,
|
||||
read: PlanType.Scale,
|
||||
update: PlanType.Scale,
|
||||
delete: PlanType.Scale,
|
||||
})
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.DeleteProjectSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditProjectSSO,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/scim-user"))
|
||||
@Entity({
|
||||
name: "SCIMUser",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "SCIMUser",
|
||||
singularName: "SCIM User",
|
||||
pluralName: "SCIM Users",
|
||||
icon: IconProp.User,
|
||||
tableDescription: "SCIM User mapping to store external provider user IDs",
|
||||
})
|
||||
export default class SCIMUser extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
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.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scimConfigId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ProjectSCIM,
|
||||
title: "SCIM Config",
|
||||
description: "Relation to Project SCIM Config Resource",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ProjectSCIM;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scimConfigId" })
|
||||
public scimConfig?: ProjectSCIM = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "SCIM Config ID",
|
||||
description: "ID of the SCIM Config this user mapping belongs to",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scimConfigId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "Relation to User Resource",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "User ID",
|
||||
description: "ID of the OneUptime User this external ID maps to",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateProjectSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.LongText,
|
||||
required: true,
|
||||
title: "External ID",
|
||||
description: "External user ID from SCIM provider (e.g., Azure AD user ID)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
nullable: false,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public externalId?: string = undefined;
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import IconProp from "../../Types/Icon/IconProp";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
@@ -715,29 +716,74 @@ export default class ScheduledMaintenance extends BaseModel {
|
||||
public endsAt?: Date = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectScheduledMaintenance,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectScheduledMaintenance,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectScheduledMaintenance,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Status Page Subscribers Notified On Event Scheduled",
|
||||
description: "Status Page Subscribers Notified On Event Scheduled",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status On Event Scheduled",
|
||||
description:
|
||||
"Status of notification sent to subscribers when event was scheduled",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotifiedOnEventScheduled?: boolean = undefined;
|
||||
public subscriberNotificationStatusOnEventScheduled?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateIncidentPublicNote,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadProjectScheduledMaintenance,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditProjectScheduledMaintenance,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message On Event Scheduled",
|
||||
description:
|
||||
"Status message for subscriber notifications when event is scheduled - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
|
||||
@@ -17,6 +17,7 @@ import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@@ -342,29 +343,73 @@ export default class ScheduledMaintenancePublicNote extends BaseModel {
|
||||
public note?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenancePublicNote,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenancePublicNote,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditScheduledMaintenancePublicNote,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Are subscribers notified?",
|
||||
description: "Are subscribers notified about this note?",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status",
|
||||
description: "Status of notification sent to subscribers about this note",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotifiedOnNoteCreated?: boolean = undefined;
|
||||
public subscriberNotificationStatusOnNoteCreated?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenancePublicNote,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenancePublicNote,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditScheduledMaintenancePublicNote,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
|
||||
@@ -423,6 +423,7 @@ export default class ScheduledMaintenanceState extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled State",
|
||||
description: "Is this state a scheduled state?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -456,6 +457,7 @@ export default class ScheduledMaintenanceState extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Ongoing State",
|
||||
description: "Is this state a ongoing state?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -489,6 +491,7 @@ export default class ScheduledMaintenanceState extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Ended State",
|
||||
description: "Is this state a ended state?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -522,6 +525,7 @@ export default class ScheduledMaintenanceState extends BaseModel {
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Resolved State",
|
||||
description: "Is this state a resolved state?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -18,6 +18,7 @@ import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@@ -388,29 +389,74 @@ export default class ScheduledMaintenanceStateTimeline extends BaseModel {
|
||||
public scheduledMaintenanceStateId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Are subscribers notified?",
|
||||
description: "Are subscribers notified about this incident state change?",
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Subscriber Notification Status",
|
||||
description:
|
||||
"Status of notification sent to subscribers about this scheduled maintenance state change",
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotified?: boolean = undefined;
|
||||
public subscriberNotificationStatus?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditScheduledMaintenanceStateTimeline,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
import Project from "./Project";
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
import User from "./User";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicySchedule from "./OnCallDutyPolicySchedule";
|
||||
import Team from "./Team";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
@@ -256,6 +265,575 @@ export default class SmsLog extends BaseModel {
|
||||
})
|
||||
public smsCostInUSDCents?: number = undefined;
|
||||
|
||||
// Relations to resources that triggered this SMS (nullable)
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Incident associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of Incident associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who initiated this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "User ID",
|
||||
description: "ID of User who initiated this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Alert associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of Alert associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "Scheduled Maintenance",
|
||||
description: "Scheduled Maintenance associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled Maintenance ID",
|
||||
description:
|
||||
"ID of Scheduled Maintenance associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Status Page associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of Status Page associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageAnnouncementId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageAnnouncement,
|
||||
title: "Status Page Announcement",
|
||||
description: "Status Page Announcement associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageAnnouncement;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageAnnouncementId" })
|
||||
public statusPageAnnouncement?: StatusPageAnnouncement = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page Announcement ID",
|
||||
description:
|
||||
"ID of Status Page Announcement associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageAnnouncementId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicy,
|
||||
title: "On-Call Duty Policy",
|
||||
description: "On-Call Duty Policy associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicy;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyId" })
|
||||
public onCallDutyPolicy?: OnCallDutyPolicy = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy ID",
|
||||
description: "ID of On-Call Duty Policy associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyEscalationRuleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicyEscalationRule,
|
||||
title: "On-Call Duty Policy Escalation Rule",
|
||||
description:
|
||||
"On-Call Duty Policy Escalation Rule associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicyEscalationRule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyEscalationRuleId" })
|
||||
public onCallDutyPolicyEscalationRule?: OnCallDutyPolicyEscalationRule =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Escalation Rule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Escalation Rule associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyEscalationRuleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyScheduleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicySchedule,
|
||||
title: "On-Call Duty Policy Schedule",
|
||||
description:
|
||||
"On-Call Duty Policy Schedule associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicySchedule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyScheduleId" })
|
||||
public onCallDutyPolicySchedule?: OnCallDutyPolicySchedule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Schedule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Schedule associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyScheduleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "teamId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Team,
|
||||
title: "Team",
|
||||
description: "Team associated with this SMS (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "teamId" })
|
||||
public team?: Team = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadSmsLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Team ID",
|
||||
description: "ID of Team associated with this SMS (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public teamId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
|
||||
@@ -1179,6 +1179,45 @@ export default class StatusPage extends BaseModel {
|
||||
})
|
||||
public enableSlackSubscribers?: boolean = 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({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Enable Microsoft Teams Subscribers",
|
||||
description:
|
||||
"Can Microsoft Teams subscribers subscribe to this Status Page?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
})
|
||||
@ColumnBillingAccessControl({
|
||||
read: PlanType.Free,
|
||||
update: PlanType.Scale,
|
||||
create: PlanType.Free,
|
||||
})
|
||||
public enableMicrosoftTeamsSubscribers?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
@@ -1438,7 +1477,12 @@ export default class StatusPage extends BaseModel {
|
||||
public callSmsConfigId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateProjectStatusPage,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
@@ -1490,6 +1534,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Number,
|
||||
required: true,
|
||||
isDefaultValueColumn: true,
|
||||
defaultValue: 14,
|
||||
title: "Show incident history in days",
|
||||
description:
|
||||
"How many days of incident history should be shown on the status page (in days)?",
|
||||
@@ -1526,6 +1571,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Number,
|
||||
required: true,
|
||||
isDefaultValueColumn: true,
|
||||
defaultValue: 14,
|
||||
title: "Show announcement history in days",
|
||||
description:
|
||||
"How many days of announcement history should be shown on the status page (in days)?",
|
||||
@@ -1562,6 +1608,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Number,
|
||||
required: true,
|
||||
isDefaultValueColumn: true,
|
||||
defaultValue: 14,
|
||||
title: "Show scheduled event history in days",
|
||||
description:
|
||||
"How many days of scheduled event history should be shown on the status page (in days)?",
|
||||
@@ -1633,6 +1680,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Hide Powered By OneUptime Branding",
|
||||
description: "Hide Powered By OneUptime Branding?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -1706,6 +1754,7 @@ export default class StatusPage extends BaseModel {
|
||||
required: false,
|
||||
type: TableColumnType.EntityArray,
|
||||
modelType: MonitorStatus,
|
||||
isDefaultValueColumn: true,
|
||||
title: "Downtime Monitor Statuses",
|
||||
description:
|
||||
'List of monitors statuses that are considered as "down" for this status page.',
|
||||
@@ -1788,6 +1837,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Is Report Enabled",
|
||||
description: "Is Report Enabled for this Status Page?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -1931,6 +1981,7 @@ export default class StatusPage extends BaseModel {
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.Number,
|
||||
defaultValue: 30,
|
||||
title: "Report data for the last N days",
|
||||
description: "How many days of data should be included in the report?",
|
||||
})
|
||||
@@ -1971,6 +2022,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Show Overall Uptime Percent on Status Page",
|
||||
description: "Show Overall Uptime Percent on Status Page?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -2007,6 +2059,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Overall Uptime Percent Precision",
|
||||
required: false,
|
||||
defaultValue: UptimePrecision.TWO_DECIMAL,
|
||||
description: "Overall Precision of uptime percent for this status page.",
|
||||
})
|
||||
@Column({
|
||||
@@ -2109,6 +2162,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Show Incidents on Status Page",
|
||||
description: "Show Incidents on Status Page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -2147,6 +2201,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Show Announcements on Status Page",
|
||||
description: "Show Announcements on Status Page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -2185,6 +2240,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Show Scheduled Maintenance Events on Status Page",
|
||||
description: "Show Scheduled Maintenance Events on Status Page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -2223,6 +2279,7 @@ export default class StatusPage extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Show Subscriber Page on Status Page",
|
||||
description: "Show Subscriber Page on Status Page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -21,6 +21,7 @@ import TenantColumn from "../../Types/Database/TenantColumn";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
@@ -443,27 +444,71 @@ export default class StatusPageAnnouncement extends BaseModel {
|
||||
public deletedByUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageAnnouncement,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageAnnouncement,
|
||||
],
|
||||
update: [],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditStatusPageAnnouncement,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
computed: true,
|
||||
hideColumnInDocumentation: true,
|
||||
type: TableColumnType.Boolean,
|
||||
defaultValue: false,
|
||||
type: TableColumnType.ShortText,
|
||||
defaultValue: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
type: ColumnType.ShortText,
|
||||
default: StatusPageSubscriberNotificationStatus.Pending,
|
||||
})
|
||||
public isStatusPageSubscribersNotified?: boolean = undefined;
|
||||
public subscriberNotificationStatus?: StatusPageSubscriberNotificationStatus =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageAnnouncement,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageAnnouncement,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.EditStatusPageAnnouncement,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Notification Status Message",
|
||||
description:
|
||||
"Status message for subscriber notifications - includes success messages, failure reasons, or skip reasons",
|
||||
required: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.VeryLongText,
|
||||
nullable: true,
|
||||
})
|
||||
public subscriberNotificationStatusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
@@ -485,6 +530,7 @@ export default class StatusPageAnnouncement extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Should subscribers be notified?",
|
||||
description: "Should subscribers be notified about this announcement?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -493,7 +539,12 @@ export default class StatusPageAnnouncement extends BaseModel {
|
||||
public shouldStatusPageSubscribersBeNotified?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageAnnouncement,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
@@ -511,6 +562,7 @@ export default class StatusPageAnnouncement extends BaseModel {
|
||||
isDefaultValueColumn: true,
|
||||
title: "Are Owners Notified",
|
||||
description: "Are owners notified of this announcement?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -474,7 +474,12 @@ export default class StatusPageDomain extends BaseModel {
|
||||
public isCnameVerified?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageDomain,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
@@ -489,6 +494,7 @@ export default class StatusPageDomain extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "SSL Ordered",
|
||||
description: "Is SSL ordered?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -499,7 +505,12 @@ export default class StatusPageDomain extends BaseModel {
|
||||
public isSslOrdered?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageDomain,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
@@ -514,6 +525,7 @@ export default class StatusPageDomain extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "SSL Provisioned",
|
||||
description: "Is SSL provisioned?",
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
469
Common/Models/DatabaseModels/StatusPageSCIM.ts
Normal file
469
Common/Models/DatabaseModels/StatusPageSCIM.ts
Normal file
@@ -0,0 +1,469 @@
|
||||
import Project from "./Project";
|
||||
import StatusPage from "./StatusPage";
|
||||
import User from "./User";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
|
||||
import CanAccessIfCanReadOn from "../../Types/Database/CanAccessIfCanReadOn";
|
||||
import ColumnLength from "../../Types/Database/ColumnLength";
|
||||
import ColumnType from "../../Types/Database/ColumnType";
|
||||
import CrudApiEndpoint from "../../Types/Database/CrudApiEndpoint";
|
||||
import EnableDocumentation from "../../Types/Database/EnableDocumentation";
|
||||
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 UniqueColumnBy from "../../Types/Database/UniqueColumnBy";
|
||||
import IconProp from "../../Types/Icon/IconProp";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import Permission from "../../Types/Permission";
|
||||
import { Column, Entity, Index, JoinColumn, ManyToOne } from "typeorm";
|
||||
|
||||
@EnableDocumentation()
|
||||
@TableBillingAccessControl({
|
||||
create: PlanType.Scale,
|
||||
read: PlanType.Scale,
|
||||
update: PlanType.Scale,
|
||||
delete: PlanType.Scale,
|
||||
})
|
||||
@CanAccessIfCanReadOn("statusPage")
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.DeleteStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/status-page-scim"))
|
||||
@TableMetadata({
|
||||
tableName: "StatusPageSCIM",
|
||||
singularName: "Status Page SCIM",
|
||||
pluralName: "Status Page SCIM",
|
||||
icon: IconProp.Lock,
|
||||
tableDescription: "Manage SCIM auto-provisioning for your status page",
|
||||
})
|
||||
@Entity({
|
||||
name: "StatusPageSCIM",
|
||||
})
|
||||
export default class StatusPageSCIM extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
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.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
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.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description:
|
||||
"Relation to Status Page Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of your Status Page resource where this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Name",
|
||||
description: "Any friendly name for this SCIM configuration",
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
@UniqueColumnBy("statusPageId")
|
||||
public name?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Description",
|
||||
description: "Friendly description to help you remember",
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public description?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Bearer Token",
|
||||
description: "Bearer token for SCIM authentication. Keep this secure.",
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public bearerToken?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Auto Provision Users",
|
||||
description:
|
||||
"Automatically create status page users when they are added via SCIM",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: true,
|
||||
})
|
||||
public autoProvisionUsers?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPageSSO,
|
||||
],
|
||||
})
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Auto Deprovision Users",
|
||||
description:
|
||||
"Automatically remove status page users when they are removed via SCIM",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: true,
|
||||
})
|
||||
public autoDeprovisionUsers?: boolean = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
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.CreateStatusPageSSO,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPageSSO,
|
||||
],
|
||||
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;
|
||||
}
|
||||
352
Common/Models/DatabaseModels/StatusPageSCIMUser.ts
Normal file
352
Common/Models/DatabaseModels/StatusPageSCIMUser.ts
Normal file
@@ -0,0 +1,352 @@
|
||||
import Project from "./Project";
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageSCIM from "./StatusPageSCIM";
|
||||
import StatusPagePrivateUser from "./StatusPagePrivateUser";
|
||||
import BaseModel from "./DatabaseBaseModel/DatabaseBaseModel";
|
||||
import Route from "../../Types/API/Route";
|
||||
import { PlanType } from "../../Types/Billing/SubscriptionPlan";
|
||||
import ColumnAccessControl from "../../Types/Database/AccessControl/ColumnAccessControl";
|
||||
import TableAccessControl from "../../Types/Database/AccessControl/TableAccessControl";
|
||||
import TableBillingAccessControl from "../../Types/Database/AccessControl/TableBillingAccessControl";
|
||||
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 Permission from "../../Types/Permission";
|
||||
import {
|
||||
Column,
|
||||
Entity,
|
||||
Index,
|
||||
JoinColumn,
|
||||
ManyToOne,
|
||||
} from "typeorm";
|
||||
|
||||
@TableBillingAccessControl({
|
||||
create: PlanType.Scale,
|
||||
read: PlanType.Scale,
|
||||
update: PlanType.Scale,
|
||||
delete: PlanType.Scale,
|
||||
})
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
delete: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.DeleteStatusPagePrivateUser,
|
||||
],
|
||||
update: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.EditStatusPagePrivateUser,
|
||||
],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/status-page-scim-user"))
|
||||
@Entity({
|
||||
name: "StatusPageSCIMUser",
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "StatusPageSCIMUser",
|
||||
singularName: "Status Page SCIM User",
|
||||
pluralName: "Status Page SCIM Users",
|
||||
icon: IconProp.User,
|
||||
tableDescription: "Status Page SCIM User mapping to store external provider user IDs",
|
||||
})
|
||||
export default class StatusPageSCIMUser extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
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: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "projectId" })
|
||||
public project?: Project = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
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.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Relation to Status Page Resource in which this object belongs",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of your Status Page in which this object belongs",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scimConfigId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageSCIM,
|
||||
title: "SCIM Config",
|
||||
description: "Relation to Status Page SCIM Config Resource",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageSCIM;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scimConfigId" })
|
||||
public scimConfig?: StatusPageSCIM = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "SCIM Config ID",
|
||||
description: "ID of the Status Page SCIM Config this user mapping belongs to",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scimConfigId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPagePrivateUserId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPagePrivateUser,
|
||||
title: "Status Page Private User",
|
||||
description: "Relation to Status Page Private User Resource",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPagePrivateUser;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: false,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "delete",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPagePrivateUserId" })
|
||||
public statusPagePrivateUser?: StatusPagePrivateUser = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: true,
|
||||
title: "Status Page Private User ID",
|
||||
description: "ID of the Status Page Private User this external ID maps to",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: false,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPagePrivateUserId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.CreateStatusPagePrivateUser,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadStatusPagePrivateUser,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.LongText,
|
||||
required: true,
|
||||
title: "External ID",
|
||||
description: "External user ID from SCIM provider (e.g., Azure AD user ID)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.LongText,
|
||||
nullable: false,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public externalId?: string = undefined;
|
||||
}
|
||||
@@ -379,6 +379,65 @@ export default class StatusPageSubscriber extends BaseModel {
|
||||
})
|
||||
public slackWorkspaceName?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.CreateStatusPageSubscriber,
|
||||
Permission.Public,
|
||||
],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.LongURL,
|
||||
title: "Microsoft Teams Incoming Webhook URL",
|
||||
description:
|
||||
"Microsoft Teams incoming webhook URL to send notifications to Teams channel",
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.LongURL,
|
||||
transformer: URL.getDatabaseTransformer(),
|
||||
})
|
||||
public microsoftTeamsIncomingWebhookUrl?: URL = 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({
|
||||
required: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Microsoft Teams Workspace Name",
|
||||
description:
|
||||
"Name of the Microsoft Teams workspace for validation and identification",
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.VeryLongText,
|
||||
})
|
||||
public microsoftTeamsWorkspaceName?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
@@ -608,6 +667,7 @@ export default class StatusPageSubscriber extends BaseModel {
|
||||
type: TableColumnType.Boolean,
|
||||
title: "Send You Have Subscribed Message",
|
||||
description: "Send You Have Subscribed Message when subscriber is created?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -642,6 +702,7 @@ export default class StatusPageSubscriber extends BaseModel {
|
||||
title: "Is Subscribed to All Resources",
|
||||
description:
|
||||
"Is Subscriber Subscribed to All Resources on this status page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
@@ -676,6 +737,7 @@ export default class StatusPageSubscriber extends BaseModel {
|
||||
title: "Is Subscribed to All Event Types",
|
||||
description:
|
||||
"Is Subscriber Subscribed to All Event Types (like Incidents, Scheduled Events, Announcements) on this status page?",
|
||||
defaultValue: true,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
|
||||
@@ -442,6 +442,7 @@ export default class TableView extends BaseModel {
|
||||
type: TableColumnType.Number,
|
||||
canReadOnRelationQuery: true,
|
||||
description: "Items on page",
|
||||
defaultValue: 10,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Number,
|
||||
|
||||
@@ -146,7 +146,11 @@ export default class TelemetryUsageBilling extends BaseModel {
|
||||
public productType?: ProductType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
create: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ManageProjectBilling,
|
||||
],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
@@ -158,6 +162,7 @@ export default class TelemetryUsageBilling extends BaseModel {
|
||||
type: TableColumnType.Number,
|
||||
title: "Retain Telemetry Data For Days",
|
||||
description: "Number of days to retain telemetry data for this service.",
|
||||
defaultValue: DEFAULT_RETENTION_IN_DAYS,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Number,
|
||||
|
||||
@@ -278,7 +278,11 @@ class UserNotificationSetting extends BaseModel {
|
||||
read: [Permission.CurrentUser],
|
||||
update: [Permission.CurrentUser],
|
||||
})
|
||||
@TableColumn({ isDefaultValueColumn: true, type: TableColumnType.Boolean })
|
||||
@TableColumn({
|
||||
isDefaultValueColumn: true,
|
||||
type: TableColumnType.Boolean,
|
||||
defaultValue: false,
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.Boolean,
|
||||
default: false,
|
||||
|
||||
931
Common/Models/DatabaseModels/WorkspaceNotificationLog.ts
Normal file
931
Common/Models/DatabaseModels/WorkspaceNotificationLog.ts
Normal file
@@ -0,0 +1,931 @@
|
||||
import Project from "./Project";
|
||||
import Incident from "./Incident";
|
||||
import Alert from "./Alert";
|
||||
import ScheduledMaintenance from "./ScheduledMaintenance";
|
||||
import StatusPage from "./StatusPage";
|
||||
import StatusPageAnnouncement from "./StatusPageAnnouncement";
|
||||
import User from "./User";
|
||||
import OnCallDutyPolicy from "./OnCallDutyPolicy";
|
||||
import OnCallDutyPolicyEscalationRule from "./OnCallDutyPolicyEscalationRule";
|
||||
import OnCallDutyPolicySchedule from "./OnCallDutyPolicySchedule";
|
||||
import Team from "./Team";
|
||||
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 ColumnLength from "../../Types/Database/ColumnLength";
|
||||
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 WorkspaceType from "../../Types/Workspace/WorkspaceType";
|
||||
import WorkspaceNotificationStatus from "../../Types/Workspace/WorkspaceNotificationStatus";
|
||||
import WorkspaceNotificationActionType from "../../Types/Workspace/WorkspaceNotificationActionType";
|
||||
|
||||
@EnableDocumentation()
|
||||
@TenantColumn("projectId")
|
||||
@TableAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
delete: [],
|
||||
update: [],
|
||||
})
|
||||
@CrudApiEndpoint(new Route("/workspace-notification-log"))
|
||||
@Entity({
|
||||
name: "WorkspaceNotificationLog",
|
||||
})
|
||||
@EnableWorkflow({
|
||||
create: true,
|
||||
delete: false,
|
||||
update: false,
|
||||
})
|
||||
@TableMetadata({
|
||||
tableName: "WorkspaceNotificationLog",
|
||||
singularName: "Workspace Notification Log",
|
||||
pluralName: "Workspace Notification Logs",
|
||||
icon: IconProp.Chat,
|
||||
tableDescription:
|
||||
"Logs of all workspace activities including messages, channel creation, user invitations, and button interactions for Slack and Microsoft Teams.",
|
||||
})
|
||||
export default class WorkspaceNotificationLog extends BaseModel {
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
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: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Workspace Type",
|
||||
description: "Type of Workspace - Slack, Microsoft Teams",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public workspaceType?: WorkspaceType = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Channel ID",
|
||||
description: "Channel ID where the message was sent",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public channelId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Channel Name",
|
||||
description: "Channel Name where the message was sent",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public channelName?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Thread ID",
|
||||
description: "Thread ID of the message in the channel (if any)",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public threadId?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.VeryLongText,
|
||||
title: "Message",
|
||||
description: "Content of the message",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.VeryLongText,
|
||||
})
|
||||
public message?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: false,
|
||||
type: TableColumnType.LongText,
|
||||
title: "Status Message",
|
||||
description: "Status Message (if any)",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: true,
|
||||
type: ColumnType.LongText,
|
||||
length: ColumnLength.LongText,
|
||||
})
|
||||
public statusMessage?: string = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Status",
|
||||
description: "Status of the message",
|
||||
canReadOnRelationQuery: false,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public status?: WorkspaceNotificationStatus = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
required: true,
|
||||
type: TableColumnType.ShortText,
|
||||
title: "Action Type",
|
||||
description: "Type of workspace action performed",
|
||||
canReadOnRelationQuery: false,
|
||||
isDefaultValueColumn: true,
|
||||
defaultValue: WorkspaceNotificationActionType.SendMessage,
|
||||
})
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.ShortText,
|
||||
length: ColumnLength.ShortText,
|
||||
default: WorkspaceNotificationActionType.SendMessage,
|
||||
})
|
||||
public actionType?: WorkspaceNotificationActionType = undefined;
|
||||
|
||||
// Relations to resources that triggered this message (nullable)
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "incidentId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Incident,
|
||||
title: "Incident",
|
||||
description: "Incident associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Incident;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "incidentId" })
|
||||
public incident?: Incident = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Incident ID",
|
||||
description: "ID of Incident associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public incidentId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "userId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: User,
|
||||
title: "User",
|
||||
description: "User who initiated this workspace notification (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return User;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "userId" })
|
||||
public user?: User = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "User ID",
|
||||
description:
|
||||
"ID of User who initiated this workspace notification (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public userId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "alertId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Alert,
|
||||
title: "Alert",
|
||||
description: "Alert associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Alert;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "alertId" })
|
||||
public alert?: Alert = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Alert ID",
|
||||
description: "ID of Alert associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public alertId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "scheduledMaintenanceId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: ScheduledMaintenance,
|
||||
title: "Scheduled Maintenance",
|
||||
description: "Scheduled Maintenance associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return ScheduledMaintenance;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "scheduledMaintenanceId" })
|
||||
public scheduledMaintenance?: ScheduledMaintenance = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Scheduled Maintenance ID",
|
||||
description:
|
||||
"ID of Scheduled Maintenance associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public scheduledMaintenanceId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPage,
|
||||
title: "Status Page",
|
||||
description: "Status Page associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPage;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageId" })
|
||||
public statusPage?: StatusPage = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page ID",
|
||||
description: "ID of Status Page associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "statusPageAnnouncementId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: StatusPageAnnouncement,
|
||||
title: "Status Page Announcement",
|
||||
description:
|
||||
"Status Page Announcement associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return StatusPageAnnouncement;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "statusPageAnnouncementId" })
|
||||
public statusPageAnnouncement?: StatusPageAnnouncement = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadPushLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Status Page Announcement ID",
|
||||
description:
|
||||
"ID of Status Page Announcement associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public statusPageAnnouncementId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicy,
|
||||
title: "On-Call Duty Policy",
|
||||
description: "On-Call Duty Policy associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicy;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyId" })
|
||||
public onCallDutyPolicy?: OnCallDutyPolicy = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyEscalationRuleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicyEscalationRule,
|
||||
title: "On-Call Duty Policy Escalation Rule",
|
||||
description:
|
||||
"On-Call Duty Policy Escalation Rule associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicyEscalationRule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyEscalationRuleId" })
|
||||
public onCallDutyPolicyEscalationRule?: OnCallDutyPolicyEscalationRule =
|
||||
undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Escalation Rule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Escalation Rule associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyEscalationRuleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "onCallDutyPolicyScheduleId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: OnCallDutyPolicySchedule,
|
||||
title: "On-Call Duty Policy Schedule",
|
||||
description:
|
||||
"On-Call Duty Policy Schedule associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return OnCallDutyPolicySchedule;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "onCallDutyPolicyScheduleId" })
|
||||
public onCallDutyPolicySchedule?: OnCallDutyPolicySchedule = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "On-Call Duty Policy Schedule ID",
|
||||
description:
|
||||
"ID of On-Call Duty Policy Schedule associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public onCallDutyPolicyScheduleId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "teamId",
|
||||
type: TableColumnType.Entity,
|
||||
modelType: Team,
|
||||
title: "Team",
|
||||
description: "Team associated with this message (if any)",
|
||||
})
|
||||
@ManyToOne(
|
||||
() => {
|
||||
return Team;
|
||||
},
|
||||
{
|
||||
eager: false,
|
||||
nullable: true,
|
||||
onDelete: "CASCADE",
|
||||
orphanedRowAction: "nullify",
|
||||
},
|
||||
)
|
||||
@JoinColumn({ name: "teamId" })
|
||||
public team?: Team = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [
|
||||
Permission.ProjectOwner,
|
||||
Permission.ProjectAdmin,
|
||||
Permission.ProjectMember,
|
||||
Permission.ReadWorkspaceNotificationLog,
|
||||
],
|
||||
update: [],
|
||||
})
|
||||
@Index()
|
||||
@TableColumn({
|
||||
type: TableColumnType.ObjectID,
|
||||
required: false,
|
||||
canReadOnRelationQuery: true,
|
||||
title: "Team ID",
|
||||
description: "ID of Team associated with this message (if any)",
|
||||
})
|
||||
@Column({
|
||||
type: ColumnType.ObjectID,
|
||||
nullable: true,
|
||||
transformer: ObjectID.getDatabaseTransformer(),
|
||||
})
|
||||
public teamId?: ObjectID = undefined;
|
||||
|
||||
@ColumnAccessControl({
|
||||
create: [],
|
||||
read: [],
|
||||
update: [],
|
||||
})
|
||||
@TableColumn({
|
||||
manyToOneRelationColumn: "deletedByUserId",
|
||||
type: TableColumnType.Entity,
|
||||
title: "Deleted by User",
|
||||
modelType: 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;
|
||||
}
|
||||
@@ -502,6 +502,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
footerHTML: true,
|
||||
enableEmailSubscribers: true,
|
||||
enableSlackSubscribers: true,
|
||||
enableMicrosoftTeamsSubscribers: true,
|
||||
enableSmsSubscribers: true,
|
||||
isPublicStatusPage: true,
|
||||
allowSubscribersToChooseResources: true,
|
||||
@@ -2146,6 +2147,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
projectId: true,
|
||||
enableEmailSubscribers: true,
|
||||
enableSlackSubscribers: true,
|
||||
enableMicrosoftTeamsSubscribers: true,
|
||||
enableSmsSubscribers: true,
|
||||
allowSubscribersToChooseResources: true,
|
||||
allowSubscribersToChooseEventTypes: true,
|
||||
@@ -2357,6 +2359,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
statusPage.smtpConfig,
|
||||
),
|
||||
projectId: statusPage.projectId!,
|
||||
statusPageId: statusPage.id!,
|
||||
},
|
||||
);
|
||||
}
|
||||
@@ -2372,6 +2375,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
customTwilioConfig: ProjectCallSMSConfigService.toTwilioConfig(
|
||||
statusPage.callSmsConfig,
|
||||
),
|
||||
statusPageId: statusPage.id!,
|
||||
}).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
});
|
||||
@@ -2417,6 +2421,7 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
enableEmailSubscribers: true,
|
||||
enableSmsSubscribers: true,
|
||||
enableSlackSubscribers: true,
|
||||
enableMicrosoftTeamsSubscribers: true,
|
||||
allowSubscribersToChooseResources: true,
|
||||
allowSubscribersToChooseEventTypes: true,
|
||||
showSubscriberPageOnStatusPage: true,
|
||||
@@ -2478,15 +2483,28 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
}
|
||||
|
||||
if (
|
||||
!req.body.data["subscriberEmail"] &&
|
||||
!req.body.data["subscriberPhone"] &&
|
||||
!req.body.data["slackWorkspaceName"]
|
||||
req.body.data["microsoftTeamsWorkspaceName"] &&
|
||||
!statusPage.enableMicrosoftTeamsSubscribers
|
||||
) {
|
||||
logger.debug(
|
||||
`No email, phone, or slack workspace name provided for subscription to status page with ID: ${objectId}`,
|
||||
`Microsoft Teams subscribers not enabled for status page with ID: ${objectId}`,
|
||||
);
|
||||
throw new BadDataException(
|
||||
"Email, phone or slack workspace name is required to subscribe to this status page.",
|
||||
"Microsoft Teams subscribers not enabled for this status page.",
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!req.body.data["subscriberEmail"] &&
|
||||
!req.body.data["subscriberPhone"] &&
|
||||
!req.body.data["slackWorkspaceName"] &&
|
||||
!req.body.data["microsoftTeamsWorkspaceName"]
|
||||
) {
|
||||
logger.debug(
|
||||
`No email, phone, slack workspace name, or Microsoft Teams workspace name provided for subscription to status page with ID: ${objectId}`,
|
||||
);
|
||||
throw new BadDataException(
|
||||
"Email, phone, slack workspace name, or Microsoft Teams workspace name is required to subscribe to this status page.",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -2510,6 +2528,18 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
? (req.body.data["slackWorkspaceName"] as string)
|
||||
: undefined;
|
||||
|
||||
const microsoftTeamsIncomingWebhookUrl: string | undefined = req.body.data[
|
||||
"microsoftTeamsIncomingWebhookUrl"
|
||||
]
|
||||
? (req.body.data["microsoftTeamsIncomingWebhookUrl"] as string)
|
||||
: undefined;
|
||||
|
||||
const microsoftTeamsWorkspaceName: string | undefined = req.body.data[
|
||||
"microsoftTeamsWorkspaceName"
|
||||
]
|
||||
? (req.body.data["microsoftTeamsWorkspaceName"] as string)
|
||||
: undefined;
|
||||
|
||||
let statusPageSubscriber: StatusPageSubscriber | null = null;
|
||||
|
||||
let isUpdate: boolean = false;
|
||||
@@ -2568,6 +2598,23 @@ export default class StatusPageAPI extends BaseAPI<
|
||||
statusPageSubscriber.slackWorkspaceName = slackWorkspaceName;
|
||||
}
|
||||
|
||||
if (microsoftTeamsIncomingWebhookUrl) {
|
||||
logger.debug(
|
||||
`Setting subscriber Microsoft Teams webhook: ${microsoftTeamsIncomingWebhookUrl}`,
|
||||
);
|
||||
statusPageSubscriber.microsoftTeamsIncomingWebhookUrl = URL.fromString(
|
||||
microsoftTeamsIncomingWebhookUrl,
|
||||
);
|
||||
}
|
||||
|
||||
if (microsoftTeamsWorkspaceName) {
|
||||
logger.debug(
|
||||
`Setting subscriber Microsoft Teams workspace name: ${microsoftTeamsWorkspaceName}`,
|
||||
);
|
||||
statusPageSubscriber.microsoftTeamsWorkspaceName =
|
||||
microsoftTeamsWorkspaceName;
|
||||
}
|
||||
|
||||
if (
|
||||
req.body.data["statusPageResources"] &&
|
||||
!statusPage.allowSubscribersToChooseResources
|
||||
|
||||
@@ -127,9 +127,11 @@ export default class UserPushAPI extends BaseAPI<
|
||||
},
|
||||
select: {
|
||||
userId: true,
|
||||
deviceName: true,
|
||||
deviceToken: true,
|
||||
deviceType: true,
|
||||
isVerified: true,
|
||||
projectId: true,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -174,12 +176,21 @@ export default class UserPushAPI extends BaseAPI<
|
||||
|
||||
await PushNotificationService.sendPushNotification(
|
||||
{
|
||||
deviceTokens: [device.deviceToken!],
|
||||
devices: [
|
||||
{
|
||||
token: device.deviceToken!,
|
||||
...(device.deviceName && {
|
||||
name: device.deviceName,
|
||||
}),
|
||||
},
|
||||
],
|
||||
message: testMessage,
|
||||
deviceType: device.deviceType!,
|
||||
},
|
||||
{
|
||||
isSensitive: false,
|
||||
projectId: device.projectId!,
|
||||
userId: device.userId!,
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
DashboardRoute,
|
||||
AppApiRoute,
|
||||
StatusPageApiRoute,
|
||||
DocsRoute,
|
||||
} from "../ServiceRoute";
|
||||
import BillingConfig from "./BillingConfig";
|
||||
import Protocol from "../Types/API/Protocol";
|
||||
@@ -150,6 +151,12 @@ export const AdminDashboardHostname: Hostname = Hostname.fromString(
|
||||
}`,
|
||||
);
|
||||
|
||||
export const DocsHostname: Hostname = Hostname.fromString(
|
||||
`${process.env["SERVER_DOCS_HOSTNAME"] || "localhost"}:${
|
||||
process.env["DOCS_PORT"] || 80
|
||||
}`,
|
||||
);
|
||||
|
||||
export const Env: string = process.env["NODE_ENV"] || "production";
|
||||
|
||||
// Redis does not require password.
|
||||
@@ -318,6 +325,8 @@ export const AccountsClientUrl: URL = new URL(
|
||||
AccountsRoute,
|
||||
);
|
||||
|
||||
export const DocsClientUrl: URL = new URL(HttpProtocol, Host, DocsRoute);
|
||||
|
||||
export const DisableTelemetry: boolean =
|
||||
process.env["DISABLE_TELEMETRY"] === "true";
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754304193228 implements MigrationInterface {
|
||||
public name = "MigrationName1754304193228";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "ProjectSCIM" ("_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(100) NOT NULL, "description" character varying(500), "bearerToken" character varying(500) NOT NULL, "autoProvisionUsers" boolean NOT NULL DEFAULT true, "autoDeprovisionUsers" boolean NOT NULL DEFAULT true, "isEnabled" boolean NOT NULL DEFAULT false, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_51e71d70211675a5c918aee4e68" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_f916360335859c26c4d7051239" ON "ProjectSCIM" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "ProjectScimTeam" ("projectScimId" uuid NOT NULL, "teamId" uuid NOT NULL, CONSTRAINT "PK_db724b66b4fa8c880ce5ccf820b" PRIMARY KEY ("projectScimId", "teamId"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b9a28efd66600267f0e9de0731" ON "ProjectScimTeam" ("projectScimId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_bb0eda2ef0c773f975e9ad8448" ON "ProjectScimTeam" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" ADD CONSTRAINT "FK_f916360335859c26c4d7051239b" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" ADD CONSTRAINT "FK_5d5d587984f156e5215d51daff7" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" ADD CONSTRAINT "FK_9cadda4fc2af268b5670d02bf76" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectScimTeam" ADD CONSTRAINT "FK_b9a28efd66600267f0e9de0731b" FOREIGN KEY ("projectScimId") REFERENCES "ProjectSCIM"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectScimTeam" ADD CONSTRAINT "FK_bb0eda2ef0c773f975e9ad8448a" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectScimTeam" DROP CONSTRAINT "FK_bb0eda2ef0c773f975e9ad8448a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectScimTeam" DROP CONSTRAINT "FK_b9a28efd66600267f0e9de0731b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" DROP CONSTRAINT "FK_9cadda4fc2af268b5670d02bf76"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" DROP CONSTRAINT "FK_5d5d587984f156e5215d51daff7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" DROP CONSTRAINT "FK_f916360335859c26c4d7051239b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_bb0eda2ef0c773f975e9ad8448"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b9a28efd66600267f0e9de0731"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "ProjectScimTeam"`);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_f916360335859c26c4d7051239"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "ProjectSCIM"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754315774827 implements MigrationInterface {
|
||||
public name = "MigrationName1754315774827";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" DROP COLUMN "isEnabled"`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ProjectSCIM" ADD "isEnabled" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754384418632 implements MigrationInterface {
|
||||
public name = "MigrationName1754384418632";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "StatusPageSCIM" ("_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, "statusPageId" uuid NOT NULL, "name" character varying(100) NOT NULL, "description" character varying(500), "bearerToken" character varying(500) NOT NULL, "autoProvisionUsers" boolean NOT NULL DEFAULT true, "autoDeprovisionUsers" boolean NOT NULL DEFAULT true, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_9d65d486be515b9608347cf66d4" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_0a241118fe6b4a8665deef444b" ON "StatusPageSCIM" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_7200e368657773fde2836c57eb" ON "StatusPageSCIM" ("statusPageId") `,
|
||||
);
|
||||
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 "StatusPageSCIM" ADD CONSTRAINT "FK_0a241118fe6b4a8665deef444b2" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" ADD CONSTRAINT "FK_7200e368657773fde2836c57ebe" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" ADD CONSTRAINT "FK_adb05dd1cbe0e734a76b3dbdcf1" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" ADD CONSTRAINT "FK_2fded7c784a5c2f56ad2553cb80" 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 "StatusPageSCIM" DROP CONSTRAINT "FK_2fded7c784a5c2f56ad2553cb80"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" DROP CONSTRAINT "FK_adb05dd1cbe0e734a76b3dbdcf1"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" DROP CONSTRAINT "FK_7200e368657773fde2836c57ebe"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSCIM" DROP CONSTRAINT "FK_0a241118fe6b4a8665deef444b2"`,
|
||||
);
|
||||
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_7200e368657773fde2836c57eb"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_0a241118fe6b4a8665deef444b"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "StatusPageSCIM"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754671483948 implements MigrationInterface {
|
||||
public name =
|
||||
"RenameSubscriberNotificationFailedReasonToStatusMessage1754484441976";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "isStatusPageSubscribersNotifiedOnIncidentCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" DROP COLUMN "isStatusPageSubscribersNotifiedOnNoteCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" DROP COLUMN "isStatusPageSubscribersNotified"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "isStatusPageSubscribersNotifiedOnEventScheduled"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" DROP COLUMN "isStatusPageSubscribersNotifiedOnNoteCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" DROP COLUMN "isStatusPageSubscribersNotified"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageAnnouncement" DROP COLUMN "isStatusPageSubscribersNotified"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "subscriberNotificationStatusOnIncidentCreated" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" ADD "subscriberNotificationStatusOnNoteCreated" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" ADD "subscriberNotificationStatus" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "subscriberNotificationStatusOnEventScheduled" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" ADD "subscriberNotificationStatusOnNoteCreated" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" ADD "subscriberNotificationStatus" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageAnnouncement" ADD "subscriberNotificationStatus" character varying NOT NULL DEFAULT 'Pending'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageAnnouncement" ADD "subscriberNotificationStatusMessage" text`,
|
||||
);
|
||||
// Set all existing rows' subscriber notification statuses to 'Success' since they were previously considered notified
|
||||
await queryRunner.query(
|
||||
`UPDATE "Incident" SET "subscriberNotificationStatusOnIncidentCreated"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "IncidentPublicNote" SET "subscriberNotificationStatusOnNoteCreated"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "IncidentStateTimeline" SET "subscriberNotificationStatus"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "ScheduledMaintenance" SET "subscriberNotificationStatusOnEventScheduled"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "ScheduledMaintenancePublicNote" SET "subscriberNotificationStatusOnNoteCreated"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "ScheduledMaintenanceStateTimeline" SET "subscriberNotificationStatus"='Success'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`UPDATE "StatusPageAnnouncement" SET "subscriberNotificationStatus"='Success'`,
|
||||
);
|
||||
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":[]}}'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
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(
|
||||
`ALTER TABLE "StatusPageAnnouncement" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageAnnouncement" DROP COLUMN "subscriberNotificationStatus"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" DROP COLUMN "subscriberNotificationStatus"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" DROP COLUMN "subscriberNotificationStatusOnNoteCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" DROP COLUMN "subscriberNotificationStatusOnEventScheduled"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" DROP COLUMN "subscriberNotificationStatus"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" DROP COLUMN "subscriberNotificationStatusOnNoteCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "subscriberNotificationStatusMessage"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" DROP COLUMN "subscriberNotificationStatusOnIncidentCreated"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageAnnouncement" ADD "isStatusPageSubscribersNotified" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenanceStateTimeline" ADD "isStatusPageSubscribersNotified" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenancePublicNote" ADD "isStatusPageSubscribersNotifiedOnNoteCreated" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "ScheduledMaintenance" ADD "isStatusPageSubscribersNotifiedOnEventScheduled" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentStateTimeline" ADD "isStatusPageSubscribersNotified" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "IncidentPublicNote" ADD "isStatusPageSubscribersNotifiedOnNoteCreated" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Incident" ADD "isStatusPageSubscribersNotifiedOnIncidentCreated" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754776130988 implements MigrationInterface {
|
||||
public name = "MigrationName1754776130988";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" ADD "incidentId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" ADD "alertId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD "scheduledMaintenanceId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" ADD "statusPageId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD "statusPageAnnouncementId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" ADD "incidentId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" ADD "alertId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD "scheduledMaintenanceId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" ADD "statusPageId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD "statusPageAnnouncementId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" ADD "incidentId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" ADD "alertId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD "scheduledMaintenanceId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" ADD "statusPageId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD "statusPageAnnouncementId" uuid`,
|
||||
);
|
||||
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(
|
||||
`CREATE INDEX "IDX_a3c1be70374eb2d7bd4197b4e5" ON "CallLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_cbcb36c6bf371312ed3b4480d7" ON "CallLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_9b351b484c705ed28ff70c63da" ON "CallLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_52a2817222b04d171238c8d26f" ON "CallLog" ("statusPageId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c97514eeb34172cce672ebc4b4" ON "CallLog" ("statusPageAnnouncementId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_958516eeac015e262300985222" ON "EmailLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_41488030fe07b21423bf85c905" ON "EmailLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b9230ffb158999e3dc8809f522" ON "EmailLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_8f7cfcce7b39d0f82f6464eb4a" ON "EmailLog" ("statusPageId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_a1b7625a277725b4dde4e6914b" ON "EmailLog" ("statusPageAnnouncementId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_4ac2d86e7aa70bc0f7e56c29e8" ON "SmsLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_9ba525289a633e16eacc9252ba" ON "SmsLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_77668eecd28b8adb9bdef350b3" ON "SmsLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_515845fba2e880ab364efc3f41" ON "SmsLog" ("statusPageId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_42ee5d4d59b6d029610c45b375" ON "SmsLog" ("statusPageAnnouncementId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_a3c1be70374eb2d7bd4197b4e5e" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_cbcb36c6bf371312ed3b4480d7a" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_9b351b484c705ed28ff70c63da5" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_52a2817222b04d171238c8d26fd" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_c97514eeb34172cce672ebc4b40" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_958516eeac015e2623009852228" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_41488030fe07b21423bf85c9058" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_b9230ffb158999e3dc8809f5228" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_8f7cfcce7b39d0f82f6464eb4a4" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_a1b7625a277725b4dde4e6914b2" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_4ac2d86e7aa70bc0f7e56c29e87" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_9ba525289a633e16eacc9252ba3" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_77668eecd28b8adb9bdef350b3b" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_515845fba2e880ab364efc3f414" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_42ee5d4d59b6d029610c45b3757" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_42ee5d4d59b6d029610c45b3757"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_515845fba2e880ab364efc3f414"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_77668eecd28b8adb9bdef350b3b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_9ba525289a633e16eacc9252ba3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_4ac2d86e7aa70bc0f7e56c29e87"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_a1b7625a277725b4dde4e6914b2"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_8f7cfcce7b39d0f82f6464eb4a4"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_b9230ffb158999e3dc8809f5228"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_41488030fe07b21423bf85c9058"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_958516eeac015e2623009852228"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_c97514eeb34172cce672ebc4b40"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_52a2817222b04d171238c8d26fd"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_9b351b484c705ed28ff70c63da5"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_cbcb36c6bf371312ed3b4480d7a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_a3c1be70374eb2d7bd4197b4e5e"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_42ee5d4d59b6d029610c45b375"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_515845fba2e880ab364efc3f41"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_77668eecd28b8adb9bdef350b3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_9ba525289a633e16eacc9252ba"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_4ac2d86e7aa70bc0f7e56c29e8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a1b7625a277725b4dde4e6914b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_8f7cfcce7b39d0f82f6464eb4a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b9230ffb158999e3dc8809f522"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_41488030fe07b21423bf85c905"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_958516eeac015e262300985222"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_c97514eeb34172cce672ebc4b4"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_52a2817222b04d171238c8d26f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_9b351b484c705ed28ff70c63da"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_cbcb36c6bf371312ed3b4480d7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a3c1be70374eb2d7bd4197b4e5"`,
|
||||
);
|
||||
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(
|
||||
`ALTER TABLE "SmsLog" DROP COLUMN "statusPageAnnouncementId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" DROP COLUMN "statusPageId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP COLUMN "scheduledMaintenanceId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" DROP COLUMN "alertId"`);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" DROP COLUMN "incidentId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "statusPageAnnouncementId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "statusPageId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "scheduledMaintenanceId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" DROP COLUMN "alertId"`);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" DROP COLUMN "incidentId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP COLUMN "statusPageAnnouncementId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" DROP COLUMN "statusPageId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP COLUMN "scheduledMaintenanceId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" DROP COLUMN "alertId"`);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" DROP COLUMN "incidentId"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754828812691 implements MigrationInterface {
|
||||
public name = "MigrationName1754828812691";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "PushNotificationLog" ("_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, "title" character varying(500) NOT NULL, "body" text, "deviceType" character varying(100), "statusMessage" character varying(500), "status" character varying(100) NOT NULL, "incidentId" uuid, "alertId" uuid, "scheduledMaintenanceId" uuid, "statusPageId" uuid, "statusPageAnnouncementId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_48b086e2ca3ee9d745ecfe97c41" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_73168664b6ffced71ffa731981" ON "PushNotificationLog" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_59a4b45ae83418ceef477ef459" ON "PushNotificationLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c684177471f5d1a9a3051f21bf" ON "PushNotificationLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_5ad3e66a90d721ac387a7da5ca" ON "PushNotificationLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c48d5589256ff128b0965ab9e7" ON "PushNotificationLog" ("statusPageId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_c62bb260910d202548e36d7827" ON "PushNotificationLog" ("statusPageAnnouncementId") `,
|
||||
);
|
||||
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 "PushNotificationLog" ADD CONSTRAINT "FK_73168664b6ffced71ffa7319817" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_59a4b45ae83418ceef477ef4590" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_c684177471f5d1a9a3051f21bf0" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_5ad3e66a90d721ac387a7da5caa" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_c48d5589256ff128b0965ab9e78" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_c62bb260910d202548e36d7827a" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_e891a0077d446c86acee230959d" 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 "PushNotificationLog" DROP CONSTRAINT "FK_e891a0077d446c86acee230959d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_c62bb260910d202548e36d7827a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_c48d5589256ff128b0965ab9e78"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_5ad3e66a90d721ac387a7da5caa"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_c684177471f5d1a9a3051f21bf0"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_59a4b45ae83418ceef477ef4590"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_73168664b6ffced71ffa7319817"`,
|
||||
);
|
||||
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_c62bb260910d202548e36d7827"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_c48d5589256ff128b0965ab9e7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_5ad3e66a90d721ac387a7da5ca"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_c684177471f5d1a9a3051f21bf"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_59a4b45ae83418ceef477ef459"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_73168664b6ffced71ffa731981"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "PushNotificationLog"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1754910440587 implements MigrationInterface {
|
||||
public name = "MigrationName1754910440587";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`CREATE TABLE "WorkspaceNotificationLog" ("_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, "workspaceType" character varying(100) NOT NULL, "channelId" character varying(100), "channelName" character varying(100), "threadId" character varying(100), "messageSummary" character varying(500), "statusMessage" character varying(500), "status" character varying(100) NOT NULL, "incidentId" uuid, "alertId" uuid, "scheduledMaintenanceId" uuid, "statusPageId" uuid, "statusPageAnnouncementId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_8017cedff7ab932c1dc3d9c4c5f" PRIMARY KEY ("_id"))`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_88e90b94233cbe8563a4bbfe45" ON "WorkspaceNotificationLog" ("projectId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_872f735f983a70558c79c78ab7" ON "WorkspaceNotificationLog" ("incidentId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_346cb35ed758bd44e1e6e7405e" ON "WorkspaceNotificationLog" ("alertId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_31bc9b6754310f914c30e074d0" ON "WorkspaceNotificationLog" ("scheduledMaintenanceId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_ef2bf686464a74e9d759630b02" ON "WorkspaceNotificationLog" ("statusPageId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_bf6998abfbf0786aeeb870756f" ON "WorkspaceNotificationLog" ("statusPageAnnouncementId") `,
|
||||
);
|
||||
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 "WorkspaceNotificationLog" ADD CONSTRAINT "FK_88e90b94233cbe8563a4bbfe45a" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_872f735f983a70558c79c78ab71" FOREIGN KEY ("incidentId") REFERENCES "Incident"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_346cb35ed758bd44e1e6e7405eb" FOREIGN KEY ("alertId") REFERENCES "Alert"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_31bc9b6754310f914c30e074d00" FOREIGN KEY ("scheduledMaintenanceId") REFERENCES "ScheduledMaintenance"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_ef2bf686464a74e9d759630b02a" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_bf6998abfbf0786aeeb870756f8" FOREIGN KEY ("statusPageAnnouncementId") REFERENCES "StatusPageAnnouncement"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_a99d29c3dfd37e7d2838436f702" 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 "WorkspaceNotificationLog" DROP CONSTRAINT "FK_a99d29c3dfd37e7d2838436f702"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_bf6998abfbf0786aeeb870756f8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_ef2bf686464a74e9d759630b02a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_31bc9b6754310f914c30e074d00"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_346cb35ed758bd44e1e6e7405eb"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_872f735f983a70558c79c78ab71"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_88e90b94233cbe8563a4bbfe45a"`,
|
||||
);
|
||||
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_bf6998abfbf0786aeeb870756f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_ef2bf686464a74e9d759630b02"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_31bc9b6754310f914c30e074d0"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_346cb35ed758bd44e1e6e7405e"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_872f735f983a70558c79c78ab7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_88e90b94233cbe8563a4bbfe45"`,
|
||||
);
|
||||
await queryRunner.query(`DROP TABLE "WorkspaceNotificationLog"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755030730926 implements MigrationInterface {
|
||||
public name = "MigrationName1755030730926";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" ADD "userId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" ADD "userId" uuid`);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" ADD "userId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "userId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "userId" uuid`,
|
||||
);
|
||||
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(
|
||||
`CREATE INDEX "IDX_47f0ed650c5e09da943caea60c" ON "CallLog" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_d1fb84d0e16365609457eb1c7b" ON "EmailLog" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_a2d58057bf9933c84b4fb0bafd" ON "SmsLog" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_6da1247dee5e3bfa4cfd4d11ed" ON "PushNotificationLog" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_0debc118df807b42cb4b274ff8" ON "WorkspaceNotificationLog" ("userId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_47f0ed650c5e09da943caea60c3" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_d1fb84d0e16365609457eb1c7ba" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_a2d58057bf9933c84b4fb0bafda" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_6da1247dee5e3bfa4cfd4d11ed6" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_0debc118df807b42cb4b274ff89" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_0debc118df807b42cb4b274ff89"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_6da1247dee5e3bfa4cfd4d11ed6"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_a2d58057bf9933c84b4fb0bafda"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_d1fb84d0e16365609457eb1c7ba"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_47f0ed650c5e09da943caea60c3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_0debc118df807b42cb4b274ff8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_6da1247dee5e3bfa4cfd4d11ed"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a2d58057bf9933c84b4fb0bafd"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_d1fb84d0e16365609457eb1c7b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_47f0ed650c5e09da943caea60c"`,
|
||||
);
|
||||
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(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "userId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "userId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" DROP COLUMN "userId"`);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" DROP COLUMN "userId"`);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" DROP COLUMN "userId"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,371 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755088852971 implements MigrationInterface {
|
||||
public name = "MigrationName1755088852971";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD "onCallDutyPolicyId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD "onCallDutyPolicyEscalationRuleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD "onCallDutyPolicyScheduleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" ADD "teamId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD "onCallDutyPolicyId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD "onCallDutyPolicyEscalationRuleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD "onCallDutyPolicyScheduleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" ADD "teamId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD "onCallDutyPolicyId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD "onCallDutyPolicyEscalationRuleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD "onCallDutyPolicyScheduleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" ADD "teamId" uuid`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "onCallDutyPolicyId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "onCallDutyPolicyEscalationRuleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "onCallDutyPolicyScheduleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "teamId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "onCallDutyPolicyId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "onCallDutyPolicyEscalationRuleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "onCallDutyPolicyScheduleId" uuid`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "teamId" uuid`,
|
||||
);
|
||||
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(
|
||||
`CREATE INDEX "IDX_6946bee33de8b45b86ebb0012e" ON "CallLog" ("onCallDutyPolicyId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_80d91b1551ba233574c0bcb622" ON "CallLog" ("onCallDutyPolicyEscalationRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_cd59580cf3a63b448174a1137d" ON "CallLog" ("onCallDutyPolicyScheduleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_05936c8c2d09e1d8b9e0ae4401" ON "CallLog" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_556a159f8352d88297a8d3e951" ON "EmailLog" ("onCallDutyPolicyId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b7304fe2449af401fb07cc8b1c" ON "EmailLog" ("onCallDutyPolicyEscalationRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_e8c3faceca2821e87fcccd43d2" ON "EmailLog" ("onCallDutyPolicyScheduleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_e394d08e87fb40b3a5d0b91250" ON "EmailLog" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_e40b9d395423a1f4426cf43bd8" ON "SmsLog" ("onCallDutyPolicyId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_31ebe9573e70ab953299403142" ON "SmsLog" ("onCallDutyPolicyEscalationRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_45577c7db6091e91e99d492854" ON "SmsLog" ("onCallDutyPolicyScheduleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_ea4117e6437e6ea9a742dd978b" ON "SmsLog" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_a2439761a3dbd16c5944743690" ON "PushNotificationLog" ("onCallDutyPolicyId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_a75ab085a0a948e113e120c468" ON "PushNotificationLog" ("onCallDutyPolicyEscalationRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b7709c3c7792047a57c4e3c090" ON "PushNotificationLog" ("onCallDutyPolicyScheduleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_dba4c943614d8fa262ca2f39bf" ON "PushNotificationLog" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_bfe40c4a4b25d4d68d53879f30" ON "WorkspaceNotificationLog" ("onCallDutyPolicyId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_8a1696a130d26efe72b215a1a7" ON "WorkspaceNotificationLog" ("onCallDutyPolicyEscalationRuleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_b8212e8152d5b38c1d5d284fc9" ON "WorkspaceNotificationLog" ("onCallDutyPolicyScheduleId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`CREATE INDEX "IDX_3881ce57f0bb88894ea33b77b1" ON "WorkspaceNotificationLog" ("teamId") `,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_6946bee33de8b45b86ebb0012e8" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_80d91b1551ba233574c0bcb622a" FOREIGN KEY ("onCallDutyPolicyEscalationRuleId") REFERENCES "OnCallDutyPolicyEscalationRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_cd59580cf3a63b448174a1137d5" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" ADD CONSTRAINT "FK_05936c8c2d09e1d8b9e0ae4401d" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_556a159f8352d88297a8d3e951f" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_b7304fe2449af401fb07cc8b1ce" FOREIGN KEY ("onCallDutyPolicyEscalationRuleId") REFERENCES "OnCallDutyPolicyEscalationRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_e8c3faceca2821e87fcccd43d28" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" ADD CONSTRAINT "FK_e394d08e87fb40b3a5d0b912505" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_e40b9d395423a1f4426cf43bd8a" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_31ebe9573e70ab9532994031422" FOREIGN KEY ("onCallDutyPolicyEscalationRuleId") REFERENCES "OnCallDutyPolicyEscalationRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_45577c7db6091e91e99d492854b" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" ADD CONSTRAINT "FK_ea4117e6437e6ea9a742dd978b3" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_a2439761a3dbd16c59447436905" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_a75ab085a0a948e113e120c468e" FOREIGN KEY ("onCallDutyPolicyEscalationRuleId") REFERENCES "OnCallDutyPolicyEscalationRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_b7709c3c7792047a57c4e3c0904" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD CONSTRAINT "FK_dba4c943614d8fa262ca2f39bf2" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_bfe40c4a4b25d4d68d53879f30d" FOREIGN KEY ("onCallDutyPolicyId") REFERENCES "OnCallDutyPolicy"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_8a1696a130d26efe72b215a1a78" FOREIGN KEY ("onCallDutyPolicyEscalationRuleId") REFERENCES "OnCallDutyPolicyEscalationRule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_b8212e8152d5b38c1d5d284fc9e" FOREIGN KEY ("onCallDutyPolicyScheduleId") REFERENCES "OnCallDutyPolicySchedule"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD CONSTRAINT "FK_3881ce57f0bb88894ea33b77b17" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_3881ce57f0bb88894ea33b77b17"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_b8212e8152d5b38c1d5d284fc9e"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_8a1696a130d26efe72b215a1a78"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP CONSTRAINT "FK_bfe40c4a4b25d4d68d53879f30d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_dba4c943614d8fa262ca2f39bf2"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_b7709c3c7792047a57c4e3c0904"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_a75ab085a0a948e113e120c468e"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP CONSTRAINT "FK_a2439761a3dbd16c59447436905"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_ea4117e6437e6ea9a742dd978b3"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_45577c7db6091e91e99d492854b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_31ebe9573e70ab9532994031422"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP CONSTRAINT "FK_e40b9d395423a1f4426cf43bd8a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_e394d08e87fb40b3a5d0b912505"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_e8c3faceca2821e87fcccd43d28"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_b7304fe2449af401fb07cc8b1ce"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP CONSTRAINT "FK_556a159f8352d88297a8d3e951f"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_05936c8c2d09e1d8b9e0ae4401d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_cd59580cf3a63b448174a1137d5"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_80d91b1551ba233574c0bcb622a"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP CONSTRAINT "FK_6946bee33de8b45b86ebb0012e8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_3881ce57f0bb88894ea33b77b1"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b8212e8152d5b38c1d5d284fc9"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_8a1696a130d26efe72b215a1a7"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_bfe40c4a4b25d4d68d53879f30"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_dba4c943614d8fa262ca2f39bf"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b7709c3c7792047a57c4e3c090"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a75ab085a0a948e113e120c468"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_a2439761a3dbd16c5944743690"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_ea4117e6437e6ea9a742dd978b"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_45577c7db6091e91e99d492854"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_31ebe9573e70ab953299403142"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_e40b9d395423a1f4426cf43bd8"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_e394d08e87fb40b3a5d0b91250"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_e8c3faceca2821e87fcccd43d2"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_b7304fe2449af401fb07cc8b1c"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_556a159f8352d88297a8d3e951"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_05936c8c2d09e1d8b9e0ae4401"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_cd59580cf3a63b448174a1137d"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_80d91b1551ba233574c0bcb622"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`DROP INDEX "public"."IDX_6946bee33de8b45b86ebb0012e"`,
|
||||
);
|
||||
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(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "teamId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "onCallDutyPolicyScheduleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "onCallDutyPolicyEscalationRuleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "onCallDutyPolicyId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "teamId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "onCallDutyPolicyScheduleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "onCallDutyPolicyEscalationRuleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "onCallDutyPolicyId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "SmsLog" DROP COLUMN "teamId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP COLUMN "onCallDutyPolicyScheduleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP COLUMN "onCallDutyPolicyEscalationRuleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "SmsLog" DROP COLUMN "onCallDutyPolicyId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "EmailLog" DROP COLUMN "teamId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "onCallDutyPolicyScheduleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "onCallDutyPolicyEscalationRuleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "EmailLog" DROP COLUMN "onCallDutyPolicyId"`,
|
||||
);
|
||||
await queryRunner.query(`ALTER TABLE "CallLog" DROP COLUMN "teamId"`);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP COLUMN "onCallDutyPolicyScheduleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP COLUMN "onCallDutyPolicyEscalationRuleId"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "CallLog" DROP COLUMN "onCallDutyPolicyId"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755093133870 implements MigrationInterface {
|
||||
public name = "MigrationName1755093133870";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "actionType" character varying(100) NOT NULL DEFAULT 'SendMessage'`,
|
||||
);
|
||||
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":[]}}'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
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(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "actionType"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755109893911 implements MigrationInterface {
|
||||
public name = "MigrationName1755109893911";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" ADD "deviceName" character varying(100)`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ALTER COLUMN "actionType" SET DEFAULT 'SendMessage'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ALTER COLUMN "actionType" SET DEFAULT 'MessageSent'`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "PushNotificationLog" DROP COLUMN "deviceName"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755110936888 implements MigrationInterface {
|
||||
public name = "MigrationName1755110936888";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" RENAME COLUMN "messageSummary" TO "message"`,
|
||||
);
|
||||
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 "WorkspaceNotificationLog" DROP COLUMN "message"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "message" text`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" DROP COLUMN "message"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" ADD "message" character varying(500)`,
|
||||
);
|
||||
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(
|
||||
`ALTER TABLE "WorkspaceNotificationLog" RENAME COLUMN "message" TO "messageSummary"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755775040650 implements MigrationInterface {
|
||||
public name = "MigrationName1755775040650";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" ADD "enableMicrosoftTeamsSubscribers" boolean NOT NULL DEFAULT false`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "microsoftTeamsIncomingWebhookUrl" character varying`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "microsoftTeamsWorkspaceName" character varying(100)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "microsoftTeamsWorkspaceName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "microsoftTeamsIncomingWebhookUrl"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPage" DROP COLUMN "enableMicrosoftTeamsSubscribers"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755778495455 implements MigrationInterface {
|
||||
public name = "MigrationName1755778495455";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "microsoftTeamsWorkspaceName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "microsoftTeamsWorkspaceName" text`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "microsoftTeamsWorkspaceName"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "microsoftTeamsWorkspaceName" character varying(100)`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1755778934927 implements MigrationInterface {
|
||||
public name = "MigrationName1755778934927";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" DROP COLUMN "microsoftTeamsIncomingWebhookUrl"`,
|
||||
);
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "StatusPageSubscriber" ADD "microsoftTeamsIncomingWebhookUrl" text`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
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}}}'`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1756293325324 implements MigrationInterface {
|
||||
public name = "MigrationName1756293325324";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Project" ADD "businessDetails" character varying(500)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Project" DROP COLUMN "businessDetails"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1756296282627 implements MigrationInterface {
|
||||
public name = "MigrationName1756296282627";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Project" ADD "businessDetailsCountry" character varying(100)`,
|
||||
);
|
||||
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":[]}}'`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
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(
|
||||
`ALTER TABLE "Project" DROP COLUMN "businessDetailsCountry"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1756300358095 implements MigrationInterface {
|
||||
public name = "MigrationName1756300358095";
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Project" ADD "financeAccountingEmail" character varying(100)`,
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
`ALTER TABLE "Project" DROP COLUMN "financeAccountingEmail"`,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class MigrationName1756740910798 implements MigrationInterface {
|
||||
public name = 'MigrationName1756740910798'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`CREATE TABLE "SCIMUser" ("_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, "scimConfigId" uuid NOT NULL, "userId" uuid NOT NULL, "externalId" character varying(500) NOT NULL, CONSTRAINT "PK_161711d359ba1935520b5aa313e" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_7561dd17a97f143cdffe341184" ON "SCIMUser" ("projectId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_ca31718fa40f6a1ac4aa63b5d8" ON "SCIMUser" ("scimConfigId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_c0bebe6a5b38293c297a6e2b1c" ON "SCIMUser" ("userId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_3593cbfcd05e591bfe131bf58a" ON "SCIMUser" ("externalId") `);
|
||||
await queryRunner.query(`CREATE TABLE "StatusPageSCIMUser" ("_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, "statusPageId" uuid NOT NULL, "scimConfigId" uuid NOT NULL, "statusPagePrivateUserId" uuid NOT NULL, "externalId" character varying(500) NOT NULL, CONSTRAINT "PK_e2fb21d6da5fc881f7adf2310f6" PRIMARY KEY ("_id"))`);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_e0f38e455921c08948b9402e8f" ON "StatusPageSCIMUser" ("projectId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_4282ed65830c3301d7b91297b3" ON "StatusPageSCIMUser" ("statusPageId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_43712b2bba1e0f13970353bee6" ON "StatusPageSCIMUser" ("scimConfigId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_8e7127bd5155fd551b218076e0" ON "StatusPageSCIMUser" ("statusPagePrivateUserId") `);
|
||||
await queryRunner.query(`CREATE INDEX "IDX_3cbb3996ed387428369f45b3cb" ON "StatusPageSCIMUser" ("externalId") `);
|
||||
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 "SCIMUser" ADD CONSTRAINT "FK_7561dd17a97f143cdffe341184f" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "SCIMUser" ADD CONSTRAINT "FK_ca31718fa40f6a1ac4aa63b5d8f" FOREIGN KEY ("scimConfigId") REFERENCES "ProjectSCIM"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "SCIMUser" ADD CONSTRAINT "FK_c0bebe6a5b38293c297a6e2b1c7" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" ADD CONSTRAINT "FK_e0f38e455921c08948b9402e8ff" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" ADD CONSTRAINT "FK_4282ed65830c3301d7b91297b3f" FOREIGN KEY ("statusPageId") REFERENCES "StatusPage"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" ADD CONSTRAINT "FK_43712b2bba1e0f13970353bee64" FOREIGN KEY ("scimConfigId") REFERENCES "StatusPageSCIM"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" ADD CONSTRAINT "FK_8e7127bd5155fd551b218076e0e" FOREIGN KEY ("statusPagePrivateUserId") REFERENCES "StatusPagePrivateUser"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" DROP CONSTRAINT "FK_8e7127bd5155fd551b218076e0e"`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" DROP CONSTRAINT "FK_43712b2bba1e0f13970353bee64"`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" DROP CONSTRAINT "FK_4282ed65830c3301d7b91297b3f"`);
|
||||
await queryRunner.query(`ALTER TABLE "StatusPageSCIMUser" DROP CONSTRAINT "FK_e0f38e455921c08948b9402e8ff"`);
|
||||
await queryRunner.query(`ALTER TABLE "SCIMUser" DROP CONSTRAINT "FK_c0bebe6a5b38293c297a6e2b1c7"`);
|
||||
await queryRunner.query(`ALTER TABLE "SCIMUser" DROP CONSTRAINT "FK_ca31718fa40f6a1ac4aa63b5d8f"`);
|
||||
await queryRunner.query(`ALTER TABLE "SCIMUser" DROP CONSTRAINT "FK_7561dd17a97f143cdffe341184f"`);
|
||||
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_3cbb3996ed387428369f45b3cb"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_8e7127bd5155fd551b218076e0"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_43712b2bba1e0f13970353bee6"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_4282ed65830c3301d7b91297b3"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_e0f38e455921c08948b9402e8f"`);
|
||||
await queryRunner.query(`DROP TABLE "StatusPageSCIMUser"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_3593cbfcd05e591bfe131bf58a"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_c0bebe6a5b38293c297a6e2b1c"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_ca31718fa40f6a1ac4aa63b5d8"`);
|
||||
await queryRunner.query(`DROP INDEX "public"."IDX_7561dd17a97f143cdffe341184"`);
|
||||
await queryRunner.query(`DROP TABLE "SCIMUser"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -146,6 +146,25 @@ import { MigrationName1753343522987 } from "./1753343522987-MigrationName";
|
||||
import { MigrationName1753377161288 } from "./1753377161288-MigrationName";
|
||||
import { AddPerformanceIndexes1753378524062 } from "./1753378524062-AddPerformanceIndexes";
|
||||
import { MigrationName1753383711511 } from "./1753383711511-MigrationName";
|
||||
import { MigrationName1754304193228 } from "./1754304193228-MigrationName";
|
||||
import { MigrationName1754315774827 } from "./1754315774827-MigrationName";
|
||||
import { MigrationName1754384418632 } from "./1754384418632-MigrationName";
|
||||
import { MigrationName1754671483948 } from "./1754671483948-MigrationName";
|
||||
import { MigrationName1754776130988 } from "./1754776130988-MigrationName";
|
||||
import { MigrationName1754828812691 } from "./1754828812691-MigrationName";
|
||||
import { MigrationName1754910440587 } from "./1754910440587-MigrationName";
|
||||
import { MigrationName1755030730926 } from "./1755030730926-MigrationName";
|
||||
import { MigrationName1755088852971 } from "./1755088852971-MigrationName";
|
||||
import { MigrationName1755093133870 } from "./1755093133870-MigrationName";
|
||||
import { MigrationName1755109893911 } from "./1755109893911-MigrationName";
|
||||
import { MigrationName1755110936888 } from "./1755110936888-MigrationName";
|
||||
import { MigrationName1755775040650 } from "./1755775040650-MigrationName";
|
||||
import { MigrationName1755778495455 } from "./1755778495455-MigrationName";
|
||||
import { MigrationName1755778934927 } from "./1755778934927-MigrationName";
|
||||
import { MigrationName1756293325324 } from "./1756293325324-MigrationName";
|
||||
import { MigrationName1756296282627 } from "./1756296282627-MigrationName";
|
||||
import { MigrationName1756300358095 } from "./1756300358095-MigrationName";
|
||||
import { MigrationName1756740910798 } from "./1756740910798-MigrationName";
|
||||
|
||||
export default [
|
||||
InitialMigration,
|
||||
@@ -296,4 +315,23 @@ export default [
|
||||
MigrationName1753377161288,
|
||||
AddPerformanceIndexes1753378524062,
|
||||
MigrationName1753383711511,
|
||||
MigrationName1754304193228,
|
||||
MigrationName1754315774827,
|
||||
MigrationName1754384418632,
|
||||
MigrationName1754671483948,
|
||||
MigrationName1754776130988,
|
||||
MigrationName1754828812691,
|
||||
MigrationName1754910440587,
|
||||
MigrationName1755030730926,
|
||||
MigrationName1755088852971,
|
||||
MigrationName1755093133870,
|
||||
MigrationName1755109893911,
|
||||
MigrationName1755110936888,
|
||||
MigrationName1755775040650,
|
||||
MigrationName1755778495455,
|
||||
MigrationName1755778934927,
|
||||
MigrationName1756293325324,
|
||||
MigrationName1756296282627,
|
||||
MigrationName1756300358095,
|
||||
MigrationName1756740910798
|
||||
];
|
||||
|
||||
@@ -27,6 +27,8 @@ export type QueueJob = Job;
|
||||
|
||||
export default class Queue {
|
||||
private static queueDict: Dictionary<BullQueue> = {};
|
||||
// track queues we have already run initial cleanup on
|
||||
private static cleanedQueueNames: Set<string> = new Set<string>();
|
||||
|
||||
@CaptureSpan()
|
||||
public static getQueue(queueName: QueueName): BullQueue {
|
||||
@@ -41,11 +43,37 @@ export default class Queue {
|
||||
port: RedisPort.toNumber(),
|
||||
password: RedisPassword,
|
||||
},
|
||||
// Keep BullMQ data under control to avoid Redis bloat
|
||||
defaultJobOptions: {
|
||||
// keep only recent completed/failed jobs
|
||||
removeOnComplete: { count: 500 }, // keep last 1000 completed jobs
|
||||
removeOnFail: { count: 100 }, // keep last 500 failed jobs
|
||||
},
|
||||
// Optionally cap the event stream length (supported in BullMQ >= v5)
|
||||
// This helps prevent the :events stream from growing indefinitely
|
||||
streams: {
|
||||
events: { maxLen: 1000 },
|
||||
},
|
||||
});
|
||||
|
||||
// save it to the dictionary
|
||||
this.queueDict[queueName] = queue;
|
||||
|
||||
// Fire-and-forget initial cleanup for legacy/old data if not done before
|
||||
if (!this.cleanedQueueNames.has(queueName)) {
|
||||
this.cleanedQueueNames.add(queueName);
|
||||
// Clean jobs older than 1 days to reclaim memory from historic runs
|
||||
const oneDaysMs: number = 1 * 24 * 60 * 60 * 1000;
|
||||
void (async () => {
|
||||
try {
|
||||
await queue.clean(oneDaysMs, 1000, "completed");
|
||||
await queue.clean(oneDaysMs, 1000, "failed");
|
||||
} catch {
|
||||
// ignore cleanup errors to not impact normal flow
|
||||
}
|
||||
})();
|
||||
}
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
@@ -193,6 +221,7 @@ export default class Queue {
|
||||
name: string;
|
||||
data: JSONObject;
|
||||
failedReason: string;
|
||||
stackTrace?: string;
|
||||
processedOn: Date | null;
|
||||
finishedOn: Date | null;
|
||||
attemptsMade: number;
|
||||
@@ -204,7 +233,16 @@ export default class Queue {
|
||||
const failed: Job[] = await queue.getFailed(start, end);
|
||||
|
||||
return failed.map((job: Job) => {
|
||||
return {
|
||||
const result: {
|
||||
id: string;
|
||||
name: string;
|
||||
data: JSONObject;
|
||||
failedReason: string;
|
||||
stackTrace?: string;
|
||||
processedOn: Date | null;
|
||||
finishedOn: Date | null;
|
||||
attemptsMade: number;
|
||||
} = {
|
||||
id: job.id || "unknown",
|
||||
name: job.name || "unknown",
|
||||
data: job.data as JSONObject,
|
||||
@@ -213,6 +251,12 @@ export default class Queue {
|
||||
finishedOn: job.finishedOn ? new Date(job.finishedOn) : null,
|
||||
attemptsMade: job.attemptsMade || 0,
|
||||
};
|
||||
|
||||
if (job.stacktrace && job.stacktrace.length > 0) {
|
||||
result.stackTrace = job.stacktrace.join("\n");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,20 @@ export default class QueueWorker {
|
||||
public static getWorker(
|
||||
queueName: QueueName,
|
||||
onJobInQueue: (job: QueueJob) => Promise<void>,
|
||||
options: { concurrency: number },
|
||||
options: {
|
||||
concurrency: number;
|
||||
/**
|
||||
* How long (in ms) the worker will hold a lock on the job before it's considered stalled
|
||||
* if the event loop is blocked and the lock cannot be extended in time.
|
||||
* Defaults to BullMQ default (30s) if not provided.
|
||||
*/
|
||||
lockDuration?: number;
|
||||
/**
|
||||
* Maximum number of times a job can be re-processed due to stall detection
|
||||
* before being moved to failed. Defaults to BullMQ default (1) if not provided.
|
||||
*/
|
||||
maxStalledCount?: number;
|
||||
},
|
||||
): Worker {
|
||||
const worker: Worker = new Worker(queueName, onJobInQueue, {
|
||||
connection: {
|
||||
@@ -23,6 +36,11 @@ export default class QueueWorker {
|
||||
password: RedisPassword,
|
||||
},
|
||||
concurrency: options.concurrency,
|
||||
// Only set these values if provided so we do not override BullMQ defaults
|
||||
...(options.lockDuration ? { lockDuration: options.lockDuration } : {}),
|
||||
...(options.maxStalledCount !== undefined
|
||||
? { maxStalledCount: options.maxStalledCount }
|
||||
: {}),
|
||||
});
|
||||
|
||||
process.on("SIGINT", async () => {
|
||||
|
||||
127
Common/Server/Middleware/SCIMAuthorization.ts
Normal file
127
Common/Server/Middleware/SCIMAuthorization.ts
Normal file
@@ -0,0 +1,127 @@
|
||||
import ProjectSCIMService from "../Services/ProjectSCIMService";
|
||||
import StatusPageSCIMService from "../Services/StatusPageSCIMService";
|
||||
import {
|
||||
ExpressRequest,
|
||||
ExpressResponse,
|
||||
NextFunction,
|
||||
OneUptimeRequest,
|
||||
} from "../Utils/Express";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import ProjectSCIM from "../../Models/DatabaseModels/ProjectSCIM";
|
||||
import StatusPageSCIM from "../../Models/DatabaseModels/StatusPageSCIM";
|
||||
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
||||
import BadRequestException from "../../Types/Exception/BadRequestException";
|
||||
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
||||
import logger from "../Utils/Logger";
|
||||
|
||||
export default class SCIMMiddleware {
|
||||
@CaptureSpan()
|
||||
public static async isAuthorizedSCIMRequest(
|
||||
req: ExpressRequest,
|
||||
_res: ExpressResponse,
|
||||
next: NextFunction,
|
||||
): Promise<void> {
|
||||
try {
|
||||
const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
|
||||
|
||||
// Extract SCIM ID from URL path (could be project or status page)
|
||||
const scimId: string | undefined =
|
||||
req.params["projectScimId"] || req.params["statusPageScimId"];
|
||||
if (!scimId) {
|
||||
throw new BadRequestException("SCIM ID is required");
|
||||
}
|
||||
|
||||
// Extract bearer token from Authorization header
|
||||
let bearerToken: string | undefined;
|
||||
if (req.headers?.["authorization"]) {
|
||||
const authHeader: string = req.headers["authorization"] as string;
|
||||
if (authHeader.startsWith("Bearer ")) {
|
||||
bearerToken = authHeader.substring(7);
|
||||
}
|
||||
}
|
||||
|
||||
logger.debug(
|
||||
`SCIM Authorization: scimId=${scimId}, bearerToken=${
|
||||
bearerToken ? "***" : "missing"
|
||||
}`,
|
||||
);
|
||||
|
||||
if (!bearerToken) {
|
||||
throw new NotAuthorizedException(
|
||||
"Bearer token is required for SCIM authentication",
|
||||
);
|
||||
}
|
||||
|
||||
// Try to find Project SCIM configuration first
|
||||
const projectScimConfig: ProjectSCIM | null =
|
||||
await ProjectSCIMService.findOneBy({
|
||||
query: {
|
||||
_id: new ObjectID(scimId),
|
||||
bearerToken: bearerToken,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
projectId: true,
|
||||
autoProvisionUsers: true,
|
||||
autoDeprovisionUsers: true,
|
||||
teams: {
|
||||
_id: true,
|
||||
name: true,
|
||||
},
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (projectScimConfig) {
|
||||
// Store Project SCIM configuration
|
||||
oneuptimeRequest.bearerTokenData = {
|
||||
scimConfig: projectScimConfig,
|
||||
projectId: projectScimConfig.projectId,
|
||||
projectScimId: new ObjectID(scimId),
|
||||
type: "project-scim",
|
||||
};
|
||||
return next();
|
||||
}
|
||||
|
||||
// If not found, try Status Page SCIM configuration
|
||||
const statusPageScimConfig: StatusPageSCIM | null =
|
||||
await StatusPageSCIMService.findOneBy({
|
||||
query: {
|
||||
_id: new ObjectID(scimId),
|
||||
bearerToken: bearerToken,
|
||||
},
|
||||
select: {
|
||||
_id: true,
|
||||
projectId: true,
|
||||
statusPageId: true,
|
||||
autoProvisionUsers: true,
|
||||
autoDeprovisionUsers: true,
|
||||
},
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (statusPageScimConfig) {
|
||||
// Store Status Page SCIM configuration
|
||||
oneuptimeRequest.bearerTokenData = {
|
||||
scimConfig: statusPageScimConfig,
|
||||
projectId: statusPageScimConfig.projectId,
|
||||
statusPageId: statusPageScimConfig.statusPageId,
|
||||
statusPageScimId: new ObjectID(scimId),
|
||||
type: "status-page-scim",
|
||||
};
|
||||
return next();
|
||||
}
|
||||
|
||||
// If neither found, throw error
|
||||
throw new NotAuthorizedException(
|
||||
"Invalid bearer token or SCIM configuration not found",
|
||||
);
|
||||
} catch (err) {
|
||||
return next(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,6 +80,94 @@ export class BillingService extends BaseService {
|
||||
await this.stripe.customers.update(id, { name: newName });
|
||||
}
|
||||
|
||||
@CaptureSpan()
|
||||
public async updateCustomerBusinessDetails(
|
||||
id: string,
|
||||
businessDetails: string,
|
||||
countryCode?: string | null,
|
||||
financeAccountingEmail?: string | null,
|
||||
): Promise<void> {
|
||||
if (!this.isBillingEnabled()) {
|
||||
throw new BadDataException(Errors.BillingService.BILLING_NOT_ENABLED);
|
||||
}
|
||||
// Goal: Update Stripe Customer "Billing details" (address fields) rather than invoice footer.
|
||||
// We only have a single free-form textarea. We'll map:
|
||||
// First non-empty line -> address.line1
|
||||
// Second non-empty line (if any) and remaining (joined, truncated) -> address.line2
|
||||
// We also persist full text in metadata so we can reconstruct or improve parsing later.
|
||||
// NOTE: Because Stripe requires structured address, any city/state/postal/country detection
|
||||
// would be heuristic; we keep it simple unless we later add structured fields.
|
||||
|
||||
const lines: Array<string> = businessDetails
|
||||
.split(/\r?\n/)
|
||||
.map((l: string) => {
|
||||
return l.trim();
|
||||
})
|
||||
.filter((l: string) => {
|
||||
return l.length > 0;
|
||||
});
|
||||
|
||||
let line1: string | undefined = undefined;
|
||||
let line2: string | undefined = undefined;
|
||||
|
||||
if (lines && lines.length > 0) {
|
||||
const first: string = lines[0]!; // non-null
|
||||
line1 = first.substring(0, 200); // Stripe typical limit safeguard.
|
||||
}
|
||||
if (lines && lines.length > 1) {
|
||||
const rest: string = lines.slice(1).join(", ");
|
||||
line2 = rest.substring(0, 200);
|
||||
}
|
||||
|
||||
const metadata: Record<string, string> = {
|
||||
business_details_full: businessDetails.substring(0, 5000),
|
||||
};
|
||||
if (financeAccountingEmail) {
|
||||
metadata["finance_accounting_email"] = financeAccountingEmail.substring(
|
||||
0,
|
||||
200,
|
||||
);
|
||||
} else {
|
||||
// Remove if cleared
|
||||
metadata["finance_accounting_email"] = "";
|
||||
}
|
||||
|
||||
const updateParams: Stripe.CustomerUpdateParams = {
|
||||
metadata,
|
||||
address: {},
|
||||
};
|
||||
|
||||
// If finance / accounting email provided, set it as the customer email so Stripe sends
|
||||
// invoices / receipts there. (Stripe only supports a single email via API currently.)
|
||||
if (financeAccountingEmail && financeAccountingEmail.trim().length > 0) {
|
||||
updateParams.email = financeAccountingEmail.trim();
|
||||
}
|
||||
|
||||
if (line1) {
|
||||
updateParams.address = updateParams.address || {};
|
||||
updateParams.address.line1 = line1;
|
||||
}
|
||||
if (line2) {
|
||||
updateParams.address = updateParams.address || {};
|
||||
updateParams.address.line2 = line2;
|
||||
}
|
||||
if (countryCode) {
|
||||
updateParams.address = updateParams.address || {};
|
||||
// Stripe expects uppercase 2-letter ISO code
|
||||
updateParams.address.country = countryCode.toUpperCase();
|
||||
}
|
||||
|
||||
if (!line1 && !line2 && !countryCode) {
|
||||
// Clear address if empty details submitted.
|
||||
updateParams.address = {
|
||||
line1: "",
|
||||
line2: "",
|
||||
} as any;
|
||||
}
|
||||
|
||||
await this.stripe.customers.update(id, updateParams);
|
||||
}
|
||||
|
||||
@CaptureSpan()
|
||||
public async deleteCustomer(id: string): Promise<void> {
|
||||
if (!this.isBillingEnabled()) {
|
||||
|
||||
@@ -24,8 +24,20 @@ export class CallService extends BaseService {
|
||||
options: {
|
||||
projectId?: ObjectID | undefined; // project id for sms log
|
||||
isSensitive?: boolean; // if true, message will not be logged
|
||||
userOnCallLogTimelineId?: ObjectID;
|
||||
userOnCallLogTimelineId?: ObjectID | undefined;
|
||||
customTwilioConfig?: TwilioConfig | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
},
|
||||
): Promise<HTTPResponse<EmptyResponseData>> {
|
||||
const body: JSONObject = {
|
||||
@@ -43,6 +55,19 @@ export class CallService extends BaseService {
|
||||
options.customTwilioConfig.secondaryPhoneNumbers?.toString(),
|
||||
}
|
||||
: undefined,
|
||||
incidentId: options.incidentId?.toString(),
|
||||
alertId: options.alertId?.toString(),
|
||||
scheduledMaintenanceId: options.scheduledMaintenanceId?.toString(),
|
||||
statusPageId: options.statusPageId?.toString(),
|
||||
statusPageAnnouncementId: options.statusPageAnnouncementId?.toString(),
|
||||
userId: options.userId?.toString(),
|
||||
onCallPolicyId: options.onCallPolicyId?.toString(),
|
||||
onCallPolicyEscalationRuleId:
|
||||
options.onCallPolicyEscalationRuleId?.toString(),
|
||||
teamId: options.teamId?.toString(),
|
||||
onCallDutyPolicyExecutionLogTimelineId:
|
||||
options.onCallDutyPolicyExecutionLogTimelineId?.toString(),
|
||||
onCallScheduleId: options.onCallScheduleId?.toString(),
|
||||
};
|
||||
|
||||
return await API.post<EmptyResponseData>(
|
||||
|
||||
@@ -228,6 +228,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
||||
}
|
||||
|
||||
throw new BadDataException(`${requiredField} is required`);
|
||||
} else if (
|
||||
(data as any)[requiredField] === null &&
|
||||
data.isDefaultValueColumn(requiredField)
|
||||
) {
|
||||
delete (data as any)[requiredField];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
||||
import IncidentService from "./IncidentService";
|
||||
import Incident from "../../Models/DatabaseModels/Incident";
|
||||
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
@@ -47,6 +48,21 @@ export class Service extends DatabaseService<Model> {
|
||||
createBy.data.postedAt = OneUptimeDate.getCurrentDate();
|
||||
}
|
||||
|
||||
// Set notification status based on shouldStatusPageSubscribersBeNotifiedOnNoteCreated
|
||||
if (
|
||||
createBy.data.shouldStatusPageSubscribersBeNotifiedOnNoteCreated === false
|
||||
) {
|
||||
createBy.data.subscriberNotificationStatusOnNoteCreated =
|
||||
StatusPageSubscriberNotificationStatus.Skipped;
|
||||
createBy.data.subscriberNotificationStatusMessage =
|
||||
"Notifications skipped as subscribers are not to be notified for this incident note.";
|
||||
} else if (
|
||||
createBy.data.shouldStatusPageSubscribersBeNotifiedOnNoteCreated === true
|
||||
) {
|
||||
createBy.data.subscriberNotificationStatusOnNoteCreated =
|
||||
StatusPageSubscriberNotificationStatus.Pending;
|
||||
}
|
||||
|
||||
return {
|
||||
createBy: createBy,
|
||||
carryForward: null,
|
||||
|
||||
@@ -24,6 +24,7 @@ import ObjectID from "../../Types/ObjectID";
|
||||
import PositiveNumber from "../../Types/PositiveNumber";
|
||||
import Typeof from "../../Types/Typeof";
|
||||
import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import Model from "../../Models/DatabaseModels/Incident";
|
||||
import IncidentOwnerTeam from "../../Models/DatabaseModels/IncidentOwnerTeam";
|
||||
import IncidentOwnerUser from "../../Models/DatabaseModels/IncidentOwnerUser";
|
||||
@@ -426,6 +427,28 @@ export class Service extends DatabaseService<Model> {
|
||||
}
|
||||
}
|
||||
|
||||
// Set notification status based on shouldStatusPageSubscribersBeNotifiedOnIncidentCreated if it's being updated
|
||||
if (
|
||||
updateBy.data.shouldStatusPageSubscribersBeNotifiedOnIncidentCreated !==
|
||||
undefined
|
||||
) {
|
||||
if (
|
||||
updateBy.data.shouldStatusPageSubscribersBeNotifiedOnIncidentCreated ===
|
||||
false
|
||||
) {
|
||||
updateBy.data.subscriberNotificationStatusOnIncidentCreated =
|
||||
StatusPageSubscriberNotificationStatus.Skipped;
|
||||
updateBy.data.subscriberNotificationStatusMessage =
|
||||
"Notifications skipped as subscribers are not to be notified for this incident.";
|
||||
} else if (
|
||||
updateBy.data.shouldStatusPageSubscribersBeNotifiedOnIncidentCreated ===
|
||||
true
|
||||
) {
|
||||
updateBy.data.subscriberNotificationStatusOnIncidentCreated =
|
||||
StatusPageSubscriberNotificationStatus.Pending;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
updateBy: updateBy,
|
||||
carryForward: carryForward,
|
||||
@@ -523,6 +546,23 @@ export class Service extends DatabaseService<Model> {
|
||||
}
|
||||
}
|
||||
|
||||
// Set notification status based on shouldStatusPageSubscribersBeNotifiedOnIncidentCreated
|
||||
if (
|
||||
createBy.data.shouldStatusPageSubscribersBeNotifiedOnIncidentCreated ===
|
||||
false
|
||||
) {
|
||||
createBy.data.subscriberNotificationStatusOnIncidentCreated =
|
||||
StatusPageSubscriberNotificationStatus.Skipped;
|
||||
createBy.data.subscriberNotificationStatusMessage =
|
||||
"Notifications skipped as subscribers are not to be notified for this incident.";
|
||||
} else if (
|
||||
createBy.data.shouldStatusPageSubscribersBeNotifiedOnIncidentCreated ===
|
||||
true
|
||||
) {
|
||||
createBy.data.subscriberNotificationStatusOnIncidentCreated =
|
||||
StatusPageSubscriberNotificationStatus.Pending;
|
||||
}
|
||||
|
||||
return {
|
||||
createBy,
|
||||
carryForward: {
|
||||
@@ -1685,7 +1725,10 @@ ${incidentSeverity.name}
|
||||
statusTimeline.shouldStatusPageSubscribersBeNotified =
|
||||
shouldNotifyStatusPageSubscribers;
|
||||
|
||||
statusTimeline.isStatusPageSubscribersNotified = isSubscribersNotified;
|
||||
// Map boolean to enum value
|
||||
statusTimeline.subscriberNotificationStatus = isSubscribersNotified
|
||||
? StatusPageSubscriberNotificationStatus.Success
|
||||
: StatusPageSubscriberNotificationStatus.Pending;
|
||||
|
||||
if (stateChangeLog) {
|
||||
statusTimeline.stateChangeLog = stateChangeLog;
|
||||
|
||||
@@ -13,6 +13,7 @@ import BadDataException from "../../Types/Exception/BadDataException";
|
||||
import { JSONObject } from "../../Types/JSON";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import PositiveNumber from "../../Types/PositiveNumber";
|
||||
import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
||||
import Incident from "../../Models/DatabaseModels/Incident";
|
||||
import IncidentPublicNote from "../../Models/DatabaseModels/IncidentPublicNote";
|
||||
import IncidentState from "../../Models/DatabaseModels/IncidentState";
|
||||
@@ -245,10 +246,26 @@ export class Service extends DatabaseService<IncidentStateTimeline> {
|
||||
if (publicNote) {
|
||||
// mark status page subscribers as notified for this state change because we dont want to send duplicate (two) emails one for public note and one for state change.
|
||||
if (createBy.data.shouldStatusPageSubscribersBeNotified) {
|
||||
createBy.data.isStatusPageSubscribersNotified = true;
|
||||
createBy.data.subscriberNotificationStatus =
|
||||
StatusPageSubscriberNotificationStatus.Success;
|
||||
}
|
||||
}
|
||||
|
||||
// Set notification status based on shouldStatusPageSubscribersBeNotified
|
||||
if (createBy.data.shouldStatusPageSubscribersBeNotified === false) {
|
||||
createBy.data.subscriberNotificationStatus =
|
||||
StatusPageSubscriberNotificationStatus.Skipped;
|
||||
createBy.data.subscriberNotificationStatusMessage =
|
||||
"Notifications skipped as subscribers are not to be notified for this incident state change.";
|
||||
} else if (
|
||||
createBy.data.shouldStatusPageSubscribersBeNotified === true &&
|
||||
!publicNote
|
||||
) {
|
||||
// Only set to Pending if there's no public note (public note handling sets it to Success)
|
||||
createBy.data.subscriberNotificationStatus =
|
||||
StatusPageSubscriberNotificationStatus.Pending;
|
||||
}
|
||||
|
||||
return {
|
||||
createBy,
|
||||
carryForward: {
|
||||
|
||||
@@ -159,6 +159,7 @@ import WorkspaceProjectAuthTokenService from "./WorkspaceProjectAuthTokenService
|
||||
import WorkspaceUserAuthTokenService from "./WorkspaceUserAuthTokenService";
|
||||
import WorkspaceSettingService from "./WorkspaceSettingService";
|
||||
import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
|
||||
import WorkspaceNotificationLogService from "./WorkspaceNotificationLogService";
|
||||
import OnCallDutyPolicyUserOverrideService from "./OnCallDutyPolicyUserOverrideService";
|
||||
|
||||
import MonitorLogService from "./MonitorLogService";
|
||||
@@ -338,6 +339,7 @@ const services: Array<BaseService> = [
|
||||
WorkspaceUserAuthTokenService,
|
||||
WorkspaceSettingService,
|
||||
WorkspaceNotificationRuleService,
|
||||
WorkspaceNotificationLogService,
|
||||
];
|
||||
|
||||
export const AnalyticsServices: Array<
|
||||
|
||||
@@ -21,6 +21,18 @@ export class MailService extends BaseService {
|
||||
mailServer?: EmailServer | undefined;
|
||||
userOnCallLogTimelineId?: ObjectID;
|
||||
projectId?: ObjectID | undefined;
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
},
|
||||
): Promise<HTTPResponse<EmptyResponseData>> {
|
||||
const body: JSONObject = {
|
||||
@@ -48,6 +60,54 @@ export class MailService extends BaseService {
|
||||
body["projectId"] = options.projectId.toString();
|
||||
}
|
||||
|
||||
if (options?.incidentId) {
|
||||
body["incidentId"] = options.incidentId.toString();
|
||||
}
|
||||
|
||||
if (options?.alertId) {
|
||||
body["alertId"] = options.alertId.toString();
|
||||
}
|
||||
|
||||
if (options?.scheduledMaintenanceId) {
|
||||
body["scheduledMaintenanceId"] =
|
||||
options.scheduledMaintenanceId.toString();
|
||||
}
|
||||
|
||||
if (options?.statusPageId) {
|
||||
body["statusPageId"] = options.statusPageId.toString();
|
||||
}
|
||||
|
||||
if (options?.statusPageAnnouncementId) {
|
||||
body["statusPageAnnouncementId"] =
|
||||
options.statusPageAnnouncementId.toString();
|
||||
}
|
||||
|
||||
if (options?.userId) {
|
||||
body["userId"] = options.userId.toString();
|
||||
}
|
||||
|
||||
if (options?.onCallPolicyId) {
|
||||
body["onCallPolicyId"] = options.onCallPolicyId.toString();
|
||||
}
|
||||
|
||||
if (options?.onCallPolicyEscalationRuleId) {
|
||||
body["onCallPolicyEscalationRuleId"] =
|
||||
options.onCallPolicyEscalationRuleId.toString();
|
||||
}
|
||||
|
||||
if (options?.onCallDutyPolicyExecutionLogTimelineId) {
|
||||
body["onCallDutyPolicyExecutionLogTimelineId"] =
|
||||
options.onCallDutyPolicyExecutionLogTimelineId.toString();
|
||||
}
|
||||
|
||||
if (options?.onCallScheduleId) {
|
||||
body["onCallScheduleId"] = options.onCallScheduleId.toString();
|
||||
}
|
||||
|
||||
if (options?.teamId) {
|
||||
body["teamId"] = options.teamId.toString();
|
||||
}
|
||||
|
||||
return await API.post<EmptyResponseData>(
|
||||
new URL(
|
||||
Protocol.HTTP,
|
||||
|
||||
@@ -67,6 +67,7 @@ import QueryOperator from "../../Types/BaseDatabase/QueryOperator";
|
||||
import { FindWhere } from "../../Types/BaseDatabase/Query";
|
||||
import logger from "../Utils/Logger";
|
||||
import PushNotificationUtil from "../Utils/PushNotificationUtil";
|
||||
import ExceptionMessages from "../../Types/Exception/ExceptionMessages";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
@@ -162,11 +163,11 @@ export class Service extends DatabaseService<Model> {
|
||||
});
|
||||
|
||||
if (!monitor) {
|
||||
throw new BadDataException("Monitor not found.");
|
||||
throw new BadDataException(ExceptionMessages.MonitorNotFound);
|
||||
}
|
||||
|
||||
if (!monitor.id) {
|
||||
throw new BadDataException("Monitor id not found.");
|
||||
throw new BadDataException(ExceptionMessages.MonitorNotFound);
|
||||
}
|
||||
|
||||
projectId = monitor.projectId!;
|
||||
@@ -1389,7 +1390,7 @@ ${createdItem.description?.trim() || "No description provided."}
|
||||
});
|
||||
|
||||
if (!monitor) {
|
||||
throw new BadDataException("Monitor not found.");
|
||||
throw new BadDataException(ExceptionMessages.MonitorNotFound);
|
||||
}
|
||||
|
||||
return (monitor.postUpdatesToWorkspaceChannels || []).filter(
|
||||
@@ -1419,7 +1420,7 @@ ${createdItem.description?.trim() || "No description provided."}
|
||||
});
|
||||
|
||||
if (!monitor) {
|
||||
throw new BadDataException("Monitor not found.");
|
||||
throw new BadDataException(ExceptionMessages.MonitorNotFound);
|
||||
}
|
||||
|
||||
return monitor.name || "";
|
||||
|
||||
@@ -126,6 +126,9 @@ export class Service extends DatabaseService<Model> {
|
||||
pushNotificationMessage: pushMessage,
|
||||
eventType:
|
||||
NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY,
|
||||
onCallPolicyId: createdModel.onCallDutyPolicy!.id!,
|
||||
onCallPolicyEscalationRuleId:
|
||||
createdModel.onCallDutyPolicyEscalationRule!.id!,
|
||||
});
|
||||
|
||||
// add workspace message.
|
||||
@@ -328,6 +331,9 @@ export class Service extends DatabaseService<Model> {
|
||||
pushNotificationMessage: pushMessage,
|
||||
eventType:
|
||||
NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY,
|
||||
onCallPolicyId: deletedItem.onCallDutyPolicy!.id!,
|
||||
onCallPolicyEscalationRuleId:
|
||||
deletedItem.onCallDutyPolicyEscalationRule!.id!,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -272,6 +272,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
||||
pushNotificationMessage: pushMessage,
|
||||
eventType:
|
||||
NotificationSettingEventType.SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER,
|
||||
onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
|
||||
onCallPolicyEscalationRuleId:
|
||||
escalationRule.onCallDutyPolicyEscalationRule!.id!,
|
||||
onCallScheduleId: data.scheduleId,
|
||||
});
|
||||
|
||||
// add end log for user.
|
||||
@@ -388,6 +392,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
||||
pushNotificationMessage: pushMessage,
|
||||
eventType:
|
||||
NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER,
|
||||
onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
|
||||
onCallPolicyEscalationRuleId:
|
||||
escalationRule.onCallDutyPolicyEscalationRule!.id!,
|
||||
onCallScheduleId: data.scheduleId,
|
||||
});
|
||||
|
||||
// add start log for user.
|
||||
@@ -524,6 +532,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
||||
pushNotificationMessage: pushMessage,
|
||||
eventType:
|
||||
NotificationSettingEventType.SEND_WHEN_USER_IS_NEXT_ON_CALL_ROSTER,
|
||||
onCallPolicyId: escalationRule.onCallDutyPolicy!.id!,
|
||||
onCallPolicyEscalationRuleId:
|
||||
escalationRule.onCallDutyPolicyEscalationRule!.id!,
|
||||
onCallScheduleId: data.scheduleId,
|
||||
});
|
||||
|
||||
const onCallDutyPolicyId: ObjectID =
|
||||
|
||||
@@ -128,18 +128,50 @@ export default class OTelIngestService {
|
||||
Metric,
|
||||
) as Metric;
|
||||
|
||||
// Handle start timestamp safely
|
||||
if (datapoint["startTimeUnixNano"]) {
|
||||
newDbMetric.startTimeUnixNano = datapoint["startTimeUnixNano"] as number;
|
||||
newDbMetric.startTime = OneUptimeDate.fromUnixNano(
|
||||
datapoint["startTimeUnixNano"] as number,
|
||||
);
|
||||
try {
|
||||
let startTimeUnixNano: number;
|
||||
if (typeof datapoint["startTimeUnixNano"] === "string") {
|
||||
startTimeUnixNano = parseFloat(datapoint["startTimeUnixNano"]);
|
||||
if (isNaN(startTimeUnixNano)) {
|
||||
startTimeUnixNano = OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
}
|
||||
} else {
|
||||
startTimeUnixNano =
|
||||
(datapoint["startTimeUnixNano"] as number) ||
|
||||
OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
}
|
||||
newDbMetric.startTimeUnixNano = startTimeUnixNano;
|
||||
newDbMetric.startTime = OneUptimeDate.fromUnixNano(startTimeUnixNano);
|
||||
} catch {
|
||||
const currentNano: number = OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
newDbMetric.startTimeUnixNano = currentNano;
|
||||
newDbMetric.startTime = OneUptimeDate.getCurrentDate();
|
||||
}
|
||||
}
|
||||
|
||||
// Handle end timestamp safely
|
||||
if (datapoint["timeUnixNano"]) {
|
||||
newDbMetric.timeUnixNano = datapoint["timeUnixNano"] as number;
|
||||
newDbMetric.time = OneUptimeDate.fromUnixNano(
|
||||
datapoint["timeUnixNano"] as number,
|
||||
);
|
||||
try {
|
||||
let timeUnixNano: number;
|
||||
if (typeof datapoint["timeUnixNano"] === "string") {
|
||||
timeUnixNano = parseFloat(datapoint["timeUnixNano"]);
|
||||
if (isNaN(timeUnixNano)) {
|
||||
timeUnixNano = OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
}
|
||||
} else {
|
||||
timeUnixNano =
|
||||
(datapoint["timeUnixNano"] as number) ||
|
||||
OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
}
|
||||
newDbMetric.timeUnixNano = timeUnixNano;
|
||||
newDbMetric.time = OneUptimeDate.fromUnixNano(timeUnixNano);
|
||||
} catch {
|
||||
const currentNano: number = OneUptimeDate.getCurrentDateAsUnixNano();
|
||||
newDbMetric.timeUnixNano = currentNano;
|
||||
newDbMetric.time = OneUptimeDate.getCurrentDate();
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(datapoint).includes("asInt")) {
|
||||
@@ -174,7 +206,7 @@ export default class OTelIngestService {
|
||||
serviceName: data.telemetryServiceName,
|
||||
}),
|
||||
...TelemetryUtil.getAttributes({
|
||||
items: datapoint["attributes"] as JSONArray,
|
||||
items: (datapoint["attributes"] as JSONArray) || [],
|
||||
prefixKeysWithString: "metricAttributes",
|
||||
}),
|
||||
};
|
||||
|
||||
27
Common/Server/Services/ProjectSCIMService.ts
Normal file
27
Common/Server/Services/ProjectSCIMService.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import CreateBy from "../Types/Database/CreateBy";
|
||||
import { OnCreate } from "../Types/Database/Hooks";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "../../Models/DatabaseModels/ProjectSCIM";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
}
|
||||
|
||||
protected override async onBeforeCreate(
|
||||
createBy: CreateBy<Model>,
|
||||
): Promise<OnCreate<Model>> {
|
||||
if (!createBy.data.bearerToken) {
|
||||
// Generate a secure bearer token if not provided
|
||||
createBy.data.bearerToken = ObjectID.generate().toString();
|
||||
}
|
||||
|
||||
return {
|
||||
createBy: createBy,
|
||||
carryForward: {},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
@@ -45,7 +45,6 @@ import {
|
||||
import Color from "../../Types/Color";
|
||||
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
||||
import OneUptimeDate from "../../Types/Date";
|
||||
import Email from "../../Types/Email";
|
||||
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
|
||||
import BadDataException from "../../Types/Exception/BadDataException";
|
||||
import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
|
||||
@@ -274,6 +273,38 @@ export class ProjectService extends DatabaseService<Model> {
|
||||
updateBy: UpdateBy<Model>,
|
||||
): Promise<OnUpdate<Model>> {
|
||||
if (IsBillingEnabled) {
|
||||
if (
|
||||
updateBy.data.businessDetails ||
|
||||
updateBy.data.businessDetailsCountry ||
|
||||
updateBy.data.financeAccountingEmail
|
||||
) {
|
||||
// Sync to Stripe.
|
||||
const project: Model | null = await this.findOneById({
|
||||
id: new ObjectID(updateBy.query._id! as string),
|
||||
select: {
|
||||
paymentProviderCustomerId: true,
|
||||
financeAccountingEmail: true,
|
||||
},
|
||||
props: { isRoot: true },
|
||||
});
|
||||
|
||||
if (project?.paymentProviderCustomerId) {
|
||||
try {
|
||||
await BillingService.updateCustomerBusinessDetails(
|
||||
project.paymentProviderCustomerId,
|
||||
(updateBy.data.businessDetails as string) || "",
|
||||
(updateBy.data.businessDetailsCountry as string) || null,
|
||||
(updateBy.data.financeAccountingEmail as string) ||
|
||||
(project as any).financeAccountingEmail ||
|
||||
null,
|
||||
);
|
||||
} catch (err) {
|
||||
logger.error(
|
||||
"Failed to update Stripe customer business details: " + err,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateBy.data.enableAutoRechargeSmsOrCallBalance) {
|
||||
await NotificationService.rechargeIfBalanceIsLow(
|
||||
new ObjectID(updateBy.query._id! as string),
|
||||
@@ -1276,14 +1307,10 @@ export class ProjectService extends DatabaseService<Model> {
|
||||
return;
|
||||
}
|
||||
|
||||
const emails: Array<Email> = owners.map((owner: User) => {
|
||||
return owner.email!;
|
||||
});
|
||||
|
||||
for (const email of emails) {
|
||||
for (const owner of owners) {
|
||||
MailService.sendMail(
|
||||
{
|
||||
toEmail: email,
|
||||
toEmail: owner.email!,
|
||||
templateType: EmailTemplateType.SimpleMessage,
|
||||
vars: {
|
||||
subject: subject,
|
||||
@@ -1293,6 +1320,7 @@ export class ProjectService extends DatabaseService<Model> {
|
||||
},
|
||||
{
|
||||
projectId,
|
||||
userId: owner.id!,
|
||||
},
|
||||
).catch((err: Error) => {
|
||||
logger.error(err);
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
import TeamMember from "../../Models/DatabaseModels/TeamMember";
|
||||
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
||||
import ObjectID from "../../Types/ObjectID";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "../../Models/DatabaseModels/ProjectUser";
|
||||
import TeamMemberService from "./TeamMemberService";
|
||||
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
}
|
||||
|
||||
@CaptureSpan()
|
||||
public async refreshProjectUsersByProject(data: {
|
||||
projectId: ObjectID;
|
||||
}): Promise<void> {
|
||||
// get all team members by user
|
||||
|
||||
// first delete all project users by project id.
|
||||
await this.deleteBy({
|
||||
query: {
|
||||
projectId: data.projectId,
|
||||
},
|
||||
limit: LIMIT_MAX,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
|
||||
// get all team members by project.
|
||||
const teamMembers: Array<TeamMember> = await TeamMemberService.findBy({
|
||||
query: {
|
||||
projectId: data.projectId,
|
||||
},
|
||||
limit: LIMIT_MAX,
|
||||
skip: 0,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
select: {
|
||||
userId: true,
|
||||
teamId: true,
|
||||
team: {
|
||||
_id: true,
|
||||
},
|
||||
hasAcceptedInvitation: true,
|
||||
},
|
||||
});
|
||||
|
||||
// create project users by team members.
|
||||
|
||||
const projectUsersToCreate: Array<Model> = [];
|
||||
|
||||
for (const teamMember of teamMembers) {
|
||||
// check if the user already exists in the project users.
|
||||
|
||||
// if yes then add the team to the project user acceptedTeams, if the invitation is accepted.
|
||||
|
||||
// if no then create a new project user.
|
||||
|
||||
// if the user is not accepted the invitation then add the team to invitedTeams of the project user.
|
||||
|
||||
// if the user is accepted the invitation then add the team to acceptedTeams of the project user.
|
||||
|
||||
let doesProjectUserExist: boolean = false;
|
||||
|
||||
for (const item of projectUsersToCreate) {
|
||||
if (item.userId?.toString() === teamMember.userId?.toString()) {
|
||||
doesProjectUserExist = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (doesProjectUserExist) {
|
||||
// add the team to the project user acceptedTeams, if the invitation is accepted.
|
||||
if (teamMember.hasAcceptedInvitation) {
|
||||
for (const projectUser of projectUsersToCreate) {
|
||||
if (
|
||||
projectUser.userId?.toString() === teamMember.userId?.toString()
|
||||
) {
|
||||
if (!projectUser.acceptedTeams) {
|
||||
projectUser.acceptedTeams = [];
|
||||
}
|
||||
|
||||
projectUser.acceptedTeams?.push(teamMember.team!);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (const projectUser of projectUsersToCreate) {
|
||||
if (
|
||||
projectUser.userId?.toString() === teamMember.userId?.toString()
|
||||
) {
|
||||
if (!projectUser.invitedTeams) {
|
||||
projectUser.invitedTeams = [];
|
||||
}
|
||||
|
||||
projectUser.invitedTeams?.push(teamMember.team!);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// create a new project user.
|
||||
const projectUser: Model = new Model();
|
||||
projectUser.userId = teamMember.userId!;
|
||||
projectUser.projectId = data.projectId;
|
||||
|
||||
if (teamMember.hasAcceptedInvitation) {
|
||||
projectUser.acceptedTeams = [teamMember.team!];
|
||||
} else {
|
||||
projectUser.invitedTeams = [teamMember.team!];
|
||||
}
|
||||
|
||||
projectUsersToCreate.push(projectUser);
|
||||
}
|
||||
}
|
||||
|
||||
// now create the project users.
|
||||
|
||||
for (const projectUser of projectUsersToCreate) {
|
||||
await this.create({
|
||||
data: projectUser,
|
||||
props: {
|
||||
isRoot: true,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
14
Common/Server/Services/PushNotificationLogService.ts
Normal file
14
Common/Server/Services/PushNotificationLogService.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { IsBillingEnabled } from "../EnvironmentConfig";
|
||||
import DatabaseService from "./DatabaseService";
|
||||
import Model from "../../Models/DatabaseModels/PushNotificationLog";
|
||||
|
||||
export class Service extends DatabaseService<Model> {
|
||||
public constructor() {
|
||||
super(Model);
|
||||
if (IsBillingEnabled) {
|
||||
this.hardDeleteItemsOlderThanInDays("createdAt", 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default new Service();
|
||||
@@ -14,11 +14,27 @@ import webpush from "web-push";
|
||||
import PushNotificationUtil from "../Utils/PushNotificationUtil";
|
||||
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
||||
import UserPush from "../../Models/DatabaseModels/UserPush";
|
||||
import PushNotificationLog from "../../Models/DatabaseModels/PushNotificationLog";
|
||||
import PushNotificationLogService from "./PushNotificationLogService";
|
||||
import PushStatus from "../../Types/PushNotification/PushStatus";
|
||||
|
||||
export interface PushNotificationOptions {
|
||||
projectId?: ObjectID | undefined;
|
||||
isSensitive?: boolean;
|
||||
userOnCallLogTimelineId?: ObjectID | undefined;
|
||||
// Optional relations for richer logging
|
||||
incidentId?: ObjectID | undefined;
|
||||
alertId?: ObjectID | undefined;
|
||||
scheduledMaintenanceId?: ObjectID | undefined;
|
||||
statusPageId?: ObjectID | undefined;
|
||||
statusPageAnnouncementId?: ObjectID | undefined;
|
||||
userId?: ObjectID | undefined;
|
||||
// On-call policy related fields
|
||||
onCallPolicyId?: ObjectID | undefined;
|
||||
onCallPolicyEscalationRuleId?: ObjectID | undefined;
|
||||
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
||||
onCallScheduleId?: ObjectID | undefined;
|
||||
teamId?: ObjectID | undefined;
|
||||
}
|
||||
|
||||
export default class PushNotificationService {
|
||||
@@ -50,12 +66,12 @@ export default class PushNotificationService {
|
||||
options: PushNotificationOptions = {},
|
||||
): Promise<void> {
|
||||
logger.info(
|
||||
`Sending push notification to ${request.deviceTokens?.length} devices`,
|
||||
`Sending push notification to ${request.devices?.length} devices`,
|
||||
);
|
||||
|
||||
if (!request.deviceTokens || request.deviceTokens.length === 0) {
|
||||
logger.error("No device tokens provided for push notification");
|
||||
throw new Error("No device tokens provided");
|
||||
if (!request.devices || request.devices.length === 0) {
|
||||
logger.error("No devices provided for push notification");
|
||||
throw new Error("No devices provided");
|
||||
}
|
||||
|
||||
if (request.deviceType !== "web") {
|
||||
@@ -64,15 +80,24 @@ export default class PushNotificationService {
|
||||
}
|
||||
|
||||
logger.info(
|
||||
`Sending web push notifications to ${request.deviceTokens.length} devices`,
|
||||
`Sending web push notifications to ${request.devices.length} devices`,
|
||||
);
|
||||
logger.info(`Notification message: ${JSON.stringify(request.message)}`);
|
||||
|
||||
const deviceNames: (string | undefined)[] = request.devices
|
||||
.map((device: { token: string; name?: string }) => {
|
||||
return device.name;
|
||||
})
|
||||
.filter(Boolean);
|
||||
if (deviceNames.length > 0) {
|
||||
logger.info(`Device names: ${deviceNames.join(", ")}`);
|
||||
}
|
||||
|
||||
const promises: Promise<void>[] = [];
|
||||
|
||||
for (const deviceToken of request.deviceTokens) {
|
||||
for (const device of request.devices) {
|
||||
promises.push(
|
||||
this.sendWebPushNotification(deviceToken, request.message, options),
|
||||
this.sendWebPushNotification(device.token, request.message, options),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -82,13 +107,23 @@ export default class PushNotificationService {
|
||||
let errorCount: number = 0;
|
||||
|
||||
results.forEach((result: any, index: number) => {
|
||||
const device:
|
||||
| {
|
||||
token: string;
|
||||
name?: string;
|
||||
}
|
||||
| undefined = request.devices[index];
|
||||
const deviceInfo: string = device?.name
|
||||
? `device "${device.name}" (${index + 1})`
|
||||
: `device ${index + 1}`;
|
||||
|
||||
if (result.status === "fulfilled") {
|
||||
successCount++;
|
||||
logger.info(`Device ${index + 1}: Notification sent successfully`);
|
||||
logger.info(`${deviceInfo}: Notification sent successfully`);
|
||||
} else {
|
||||
errorCount++;
|
||||
logger.error(
|
||||
`Failed to send notification to device ${index + 1}: ${result.reason}`,
|
||||
`Failed to send notification to ${deviceInfo}: ${result.reason}`,
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -97,6 +132,83 @@ export default class PushNotificationService {
|
||||
`Push notification results: ${successCount} successful, ${errorCount} failed`,
|
||||
);
|
||||
|
||||
// Create one push log per device if projectId provided
|
||||
if (options.projectId) {
|
||||
for (let i: number = 0; i < results.length; i++) {
|
||||
const result: any = results[i];
|
||||
const device:
|
||||
| {
|
||||
token: string;
|
||||
name?: string;
|
||||
}
|
||||
| undefined = request.devices[i];
|
||||
const log: PushNotificationLog = new PushNotificationLog();
|
||||
log.projectId = options.projectId;
|
||||
log.title = request.message.title || "";
|
||||
log.body = options.isSensitive
|
||||
? "Sensitive message not logged"
|
||||
: request.message.body || "";
|
||||
log.deviceType = request.deviceType;
|
||||
|
||||
// Set device name if available
|
||||
if (device?.name) {
|
||||
log.deviceName = device.name;
|
||||
}
|
||||
|
||||
// relations if provided
|
||||
if (options.incidentId) {
|
||||
log.incidentId = options.incidentId;
|
||||
}
|
||||
if (options.alertId) {
|
||||
log.alertId = options.alertId;
|
||||
}
|
||||
if (options.scheduledMaintenanceId) {
|
||||
log.scheduledMaintenanceId = options.scheduledMaintenanceId;
|
||||
}
|
||||
if (options.statusPageId) {
|
||||
log.statusPageId = options.statusPageId;
|
||||
}
|
||||
if (options.statusPageAnnouncementId) {
|
||||
log.statusPageAnnouncementId = options.statusPageAnnouncementId;
|
||||
}
|
||||
if (options.userId) {
|
||||
log.userId = options.userId;
|
||||
}
|
||||
if (options.teamId) {
|
||||
log.teamId = options.teamId;
|
||||
}
|
||||
|
||||
// Set OnCall-related fields
|
||||
if (options.onCallPolicyId) {
|
||||
log.onCallDutyPolicyId = options.onCallPolicyId;
|
||||
}
|
||||
if (options.onCallPolicyEscalationRuleId) {
|
||||
log.onCallDutyPolicyEscalationRuleId =
|
||||
options.onCallPolicyEscalationRuleId;
|
||||
}
|
||||
if (options.onCallScheduleId) {
|
||||
log.onCallDutyPolicyScheduleId = options.onCallScheduleId;
|
||||
}
|
||||
|
||||
if (result.status === "fulfilled") {
|
||||
log.status = PushStatus.Success;
|
||||
log.statusMessage = "Push notification sent";
|
||||
} else {
|
||||
log.status = PushStatus.Error;
|
||||
const reason: string =
|
||||
(result &&
|
||||
(result.reason?.message || result.reason?.toString?.())) ||
|
||||
`Failed to send push notification`;
|
||||
log.statusMessage = reason;
|
||||
}
|
||||
|
||||
await PushNotificationLogService.create({
|
||||
data: log,
|
||||
props: { isRoot: true },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Update user on call log timeline status if provided
|
||||
if (options.userOnCallLogTimelineId) {
|
||||
const status: UserNotificationStatus =
|
||||
@@ -213,6 +325,7 @@ export default class PushNotificationService {
|
||||
select: {
|
||||
deviceToken: true,
|
||||
deviceType: true,
|
||||
deviceName: true,
|
||||
_id: true,
|
||||
},
|
||||
limit: LIMIT_PER_PROJECT,
|
||||
@@ -229,12 +342,15 @@ export default class PushNotificationService {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get web device tokens
|
||||
const webDevices: string[] = [];
|
||||
// Get web devices with tokens and names
|
||||
const webDevices: Array<{ token: string; name?: string }> = [];
|
||||
|
||||
for (const device of userPushDevices) {
|
||||
if (device.deviceType === "web") {
|
||||
webDevices.push(device.deviceToken!);
|
||||
webDevices.push({
|
||||
token: device.deviceToken!,
|
||||
name: device.deviceName || "Unknown Device",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +358,7 @@ export default class PushNotificationService {
|
||||
if (webDevices.length > 0) {
|
||||
await this.sendPushNotification(
|
||||
{
|
||||
deviceTokens: webDevices,
|
||||
devices: webDevices,
|
||||
message: message,
|
||||
deviceType: "web",
|
||||
},
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user