mirror of
https://github.com/Infisical/infisical.git
synced 2025-07-05 04:29:09 +00:00
Compare commits
824 Commits
docker-com
...
daniel/ui-
Author | SHA1 | Date | |
---|---|---|---|
d1dacd81aa | |||
e8b635ce37 | |||
1d3e03e308 | |||
88e2eff7eb | |||
cd192ee228 | |||
1e657968f6 | |||
b8ba51512c | |||
1ac8ddbd92 | |||
a257743fa5 | |||
b5a7240375 | |||
5c2a108c52 | |||
b78d8d28ed | |||
9c9ade52db | |||
4d229ec745 | |||
605dad29ca | |||
bebdad8159 | |||
b547309ae4 | |||
d1ebdbcc03 | |||
c94caa6fb5 | |||
f53fa46c51 | |||
c42d407cda | |||
80b4bc18ec | |||
1dbf80d4e6 | |||
700a072ec5 | |||
8f42914df5 | |||
831da10073 | |||
6904cd3bda | |||
52fd09b87b | |||
0081bbdf9e | |||
c9e5f2bb75 | |||
73cc97cf17 | |||
0c1d37cc75 | |||
60fbd8ac44 | |||
36efa6ba63 | |||
961a73f712 | |||
6e2f3800d4 | |||
258c9e45d4 | |||
8573263379 | |||
9a724db6ab | |||
60a37e784b | |||
14c60bd075 | |||
de715c03ad | |||
ddb1d5a1ab | |||
41323f205d | |||
771498b817 | |||
22b2fb4c98 | |||
9bbba92768 | |||
46eea972f7 | |||
9eb2a74bdf | |||
b80579fdef | |||
214894c88b | |||
8ff37e3ec9 | |||
926f719967 | |||
c3a56f469a | |||
2bd9914373 | |||
354bac486a | |||
ba22a7fca6 | |||
4aef8ab8ee | |||
e89503f00f | |||
f5f20fbdca | |||
4d4887059a | |||
c11c5ec85e | |||
f0e3c9a4b2 | |||
eace4f1bdc | |||
0bd3f32c6e | |||
ad0504e957 | |||
1e20d780ec | |||
7e2685d604 | |||
92fd2d080d | |||
6d60413593 | |||
f59a75d790 | |||
835c36d161 | |||
e4dba6d5c8 | |||
b9986be387 | |||
5f5d62a285 | |||
667fa7a9e3 | |||
27dcb06083 | |||
9b1a15331a | |||
65776b7ab9 | |||
a9c1f278a1 | |||
900facdb36 | |||
fe638ce2c1 | |||
750a43c978 | |||
08b5975f26 | |||
885d1fbd7f | |||
bb2413d659 | |||
dac5529b6c | |||
bd92e35729 | |||
5b7562a76d | |||
edbf459d04 | |||
560274bde8 | |||
7df614a018 | |||
47287be5bf | |||
6e96f2338c | |||
7fd6b63b5d | |||
995777d76f | |||
2a6032a8cf | |||
ec4d1dd1b2 | |||
143de12d67 | |||
52cf937826 | |||
dbd7561037 | |||
d287c3e152 | |||
8fc081973d | |||
c42bbbea8b | |||
29b2b12ec7 | |||
4f80234afa | |||
a1fa0c652d | |||
8327f41b8e | |||
c2bfeb89e8 | |||
4a0668e92e | |||
716e705c2a | |||
f860fd3abe | |||
30e7fe8a45 | |||
307b89e799 | |||
dbf498b44a | |||
5eb3258311 | |||
bd3cbb3c7b | |||
96abbd9f80 | |||
92441e018f | |||
a9bba02f44 | |||
aaca3ac229 | |||
f0383dd55c | |||
a766329de5 | |||
c0b0c0754b | |||
34618041ca | |||
f36a056c62 | |||
e7b11eac2b | |||
0f14fab915 | |||
12a6fba645 | |||
ce057f44ac | |||
2032063c24 | |||
bbceb37d06 | |||
e917b744f4 | |||
7438c114dd | |||
8e3fc044ca | |||
9473de2212 | |||
744c510a51 | |||
f845749a4d | |||
56fc5a2a8c | |||
7edebbabaa | |||
0e698e9355 | |||
00b99e7255 | |||
2b7784718d | |||
5f99e58674 | |||
f77942c702 | |||
2d3fddd0e9 | |||
519b92d592 | |||
c3d5e882f8 | |||
4c354eb3ea | |||
97eff2b480 | |||
c621592807 | |||
bd400a6196 | |||
a93c2d9236 | |||
11dfeda501 | |||
70bd64d54b | |||
0c88a5466c | |||
36266b30d5 | |||
288577b455 | |||
5194be14fd | |||
bab8f95fde | |||
b4f372f883 | |||
b13365ecf5 | |||
bb6e09a895 | |||
715b193a8e | |||
57be493da8 | |||
cc731fe031 | |||
70618420d7 | |||
7feb7ef9c6 | |||
ab1b9fb164 | |||
8c028889a6 | |||
7dc366baf0 | |||
2124d2669f | |||
af83fbea14 | |||
9657b64ab2 | |||
90b55a94e1 | |||
d83d249f29 | |||
151787c60a | |||
ce443b114c | |||
2ca03abec2 | |||
c8bb690736 | |||
6efbdaef9c | |||
7e90493cce | |||
1330c0455a | |||
407248c616 | |||
a6d7d32156 | |||
0f0e2b360c | |||
47906c4dd4 | |||
fc57884035 | |||
4152b3a524 | |||
f1f18e81cd | |||
929f91a738 | |||
fa41b8bb47 | |||
edbb7e2b1e | |||
1d53e0f21b | |||
a232450f20 | |||
6f65f2a63d | |||
9545960e6f | |||
cfa42017b1 | |||
1b74fdb232 | |||
ad1cae6aac | |||
e5d4328e2a | |||
635948c4f4 | |||
d6231d4649 | |||
041535bb47 | |||
3f0c4f0ca9 | |||
5c8b886d7b | |||
51a5bf8181 | |||
822d0692db | |||
e527d99654 | |||
628c641580 | |||
40ccab6576 | |||
9cc3e58561 | |||
1f3fded404 | |||
74b5e8cbeb | |||
522a03c2ad | |||
624fb3d46a | |||
8a27b1b5e6 | |||
56bf82e4f6 | |||
972b80e790 | |||
6cc0d79d8a | |||
163ccd6cdb | |||
06f3a6d262 | |||
b641bbf229 | |||
feb7563eab | |||
7594929042 | |||
f1b7653a52 | |||
0cb6d052e0 | |||
ceb135fc94 | |||
b75289f074 | |||
de86705e64 | |||
f9b6f78e8d | |||
2852a495c8 | |||
6ca56143d9 | |||
ef0e652557 | |||
89e109e404 | |||
48062d9680 | |||
d11fda3be5 | |||
0df5f845fb | |||
ca59488b62 | |||
3a05ae4b27 | |||
dd009182e8 | |||
8ac7a29893 | |||
8a17cd3f5d | |||
99fe43f459 | |||
2e3b10ccfc | |||
79196b0081 | |||
b76ff28414 | |||
2894cf791a | |||
c040b0ca9a | |||
15f60aa7dd | |||
6f68d304ea | |||
0b98feea50 | |||
43d40d7475 | |||
309a106f13 | |||
74d73590a1 | |||
b42b5614c9 | |||
72b89cb989 | |||
6305300b12 | |||
b4ae1e8f3b | |||
36d8b22598 | |||
201dcd971c | |||
ab90745312 | |||
622106045e | |||
e64302b789 | |||
901a7fc294 | |||
359694dd47 | |||
57489a7578 | |||
a4205a8662 | |||
dbf177d667 | |||
f078aec54c | |||
5dfe62e306 | |||
b89925c61c | |||
440a58a49b | |||
6d0bea6d5f | |||
10a40c8ab2 | |||
b910ceacfc | |||
cb66386e13 | |||
889df3dcb1 | |||
ae53f03f71 | |||
7ae024724d | |||
0b2bc1d345 | |||
da5eca3e68 | |||
3375d3ff85 | |||
35a5c9a67f | |||
7d495cfea5 | |||
2eca9d8200 | |||
4d707eee8a | |||
76bd85efa7 | |||
d140e4f3c9 | |||
80623c03f4 | |||
ed6c6e8d1e | |||
7e044ad9ff | |||
8f2b54514c | |||
5f5f46eddf | |||
3174896d37 | |||
919e184305 | |||
c7d08745fc | |||
d6d780a7b4 | |||
03e965ec5a | |||
cd0df2d617 | |||
e72e6dd6ee | |||
327c5e2429 | |||
f29dd6effa | |||
7987a1ea2b | |||
e6036175c1 | |||
171a70ddc1 | |||
a845f4ee5c | |||
71cd4425b4 | |||
deb22bf8ad | |||
8e25631fb0 | |||
0912903e0d | |||
1b1a95ab78 | |||
cf4f26ab90 | |||
84249f535b | |||
c7bbe82f4a | |||
d8d2741868 | |||
f45074a2dd | |||
564b6b8ef6 | |||
fafd963a8a | |||
9e38076d45 | |||
d3a6da187b | |||
7a90fa472d | |||
756c1e5098 | |||
0dd34eae60 | |||
846e2f21cc | |||
d8860e1ce3 | |||
68296c1b99 | |||
2192985291 | |||
16acace648 | |||
e3e4a98cd6 | |||
4afb20ad0d | |||
60134cf8ac | |||
22d5f97793 | |||
3fa529dcb0 | |||
d12c4b7580 | |||
5feb942d79 | |||
b6f3cf512e | |||
4dbee7df06 | |||
323c412f5e | |||
ae2706542c | |||
d5861493bf | |||
53044f3d39 | |||
93268f5767 | |||
318dedb987 | |||
291edf71aa | |||
342665783e | |||
6a7241d7d1 | |||
51fb680f9c | |||
0710c9a84a | |||
e46bce1520 | |||
3919393d33 | |||
c8b7c37aee | |||
2641fccce5 | |||
213f2ed29b | |||
4dcd000dd1 | |||
c2fe6eb90c | |||
f64cb10282 | |||
a0ea2627ed | |||
5c40b538af | |||
8dd94a4e10 | |||
041c4a20a0 | |||
4a2a5f42a8 | |||
9fcdf17a04 | |||
97ac8cb45a | |||
e952659415 | |||
1f3f061a06 | |||
5096ce3bdc | |||
621683f787 | |||
f63850e9e9 | |||
4ee0a2ec6c | |||
9569d3971a | |||
443b8f747b | |||
803393c385 | |||
8e95189fd2 | |||
c5f38b6ade | |||
30a1c5ac86 | |||
bbad2ba047 | |||
1445df7015 | |||
ae4a2089d5 | |||
0b924b6e45 | |||
1fcac4cadf | |||
155e315347 | |||
3dce03180f | |||
4748b546c2 | |||
96887cdbfa | |||
553b56e57e | |||
a33f542647 | |||
06b03fc450 | |||
031a834ab1 | |||
89e942fea3 | |||
3c0908a788 | |||
14e42b7ff2 | |||
9476594978 | |||
02be9ebd5e | |||
eb29d1dc28 | |||
21d5c44ea1 | |||
114a4b1412 | |||
fb8c4bd415 | |||
48bf41ac8c | |||
1ad916a784 | |||
c91456838e | |||
79efe64504 | |||
cde8cef8b0 | |||
7207997cea | |||
aaabfb7870 | |||
40cb5c4394 | |||
60b73879df | |||
4339ef4737 | |||
d98669700d | |||
162f339149 | |||
d3eb0c4cc9 | |||
4b4295f53d | |||
6c4d193b12 | |||
d08d412f54 | |||
bb4810470f | |||
24e9c0a39f | |||
3161d0ee67 | |||
8a7e18dc7c | |||
0497c3b49e | |||
db9f21be87 | |||
e6a89fb9d0 | |||
449617d271 | |||
d9828db2ec | |||
f11efc9e3f | |||
32bad10c0e | |||
41064920f7 | |||
8d8e23add2 | |||
a2a959cc32 | |||
d6cde48181 | |||
23966c12e2 | |||
2a233ea43c | |||
fe497d87c0 | |||
3641875b24 | |||
0c3060e1c6 | |||
5d64398e58 | |||
2f6f713c98 | |||
4f47d43801 | |||
6cf9a83c16 | |||
c3adc8b188 | |||
a723c456aa | |||
c455ef7ced | |||
f9d0680dc3 | |||
7a4e8b8c32 | |||
8e83b0f2dd | |||
59c6837071 | |||
d4d23e06a8 | |||
9d202e8501 | |||
1f9f15136e | |||
5d71b02f8d | |||
9d2a0f1d54 | |||
0f4da61aaa | |||
26abb7d89f | |||
892a25edfe | |||
a04a9a1bd3 | |||
04d729df92 | |||
5ca1b1d77e | |||
2d9526ad8d | |||
768cc64af6 | |||
a28431bfe7 | |||
91068229bf | |||
082a533cfa | |||
d71a8a35e5 | |||
59585dfea9 | |||
514304eed0 | |||
a0fc9e534c | |||
73323c0343 | |||
98cd71d421 | |||
ae6157dd78 | |||
9ba4b939a4 | |||
4bf7e8bbd1 | |||
6891d309da | |||
3b9ceff21c | |||
d64d935d7d | |||
8aaed739d5 | |||
7d8b399102 | |||
1cccbca0c5 | |||
2c2e1f5d2e | |||
6946f3901c | |||
1c088b3a58 | |||
a33c50b75a | |||
82a7010e29 | |||
a1e763fa28 | |||
0992117173 | |||
9419884a26 | |||
850f3a347c | |||
4c9101d18d | |||
06e8e90ad5 | |||
8c31566e17 | |||
1594165768 | |||
29d91d83ab | |||
fdd79c0568 | |||
4ef8abdb00 | |||
46f0fb7a41 | |||
bfee74ff4e | |||
97a7b66c6c | |||
2142f5736c | |||
ce764d70ad | |||
c2d0ddb2fc | |||
7ba9588509 | |||
cddb09e031 | |||
046dc83638 | |||
639c78358f | |||
5053069bfc | |||
320074ef6c | |||
e780ee6573 | |||
a5a881c382 | |||
200d4a5af6 | |||
07318ec54b | |||
92d237a714 | |||
6ef988fa86 | |||
70822d0d98 | |||
e91499b301 | |||
92acb4d943 | |||
76daa20d69 | |||
a231813f01 | |||
3eb2bdb191 | |||
cadf6e1157 | |||
ceb7fafc06 | |||
3063bb9982 | |||
3d82a43615 | |||
028541a18a | |||
66a631ff46 | |||
28adb8f0ac | |||
5c988c2cd5 | |||
acf8a54abb | |||
387094aa27 | |||
4251e95c15 | |||
f4386c2d93 | |||
ff4b943854 | |||
879a5ecfac | |||
a831a7d848 | |||
3138784d1a | |||
0b258e3918 | |||
d0545a01b9 | |||
d71398344f | |||
25e3cc047b | |||
17149de567 | |||
cca2fb7ff5 | |||
f1f2d62993 | |||
be49de5f34 | |||
acfa89ba8b | |||
389ec85554 | |||
2a6b0efe22 | |||
74d9a76f75 | |||
9c67d43ebe | |||
d8f3531b50 | |||
57be73c17e | |||
a10129e750 | |||
adc10cf675 | |||
49f7780e52 | |||
26482c6b0a | |||
1cf9aaeb1b | |||
fed022ed09 | |||
64fbe4161c | |||
bbe769a961 | |||
45772f0108 | |||
31cc3ece0c | |||
52cfa1ba39 | |||
d9888f9dd1 | |||
4553c6bb37 | |||
554f0cfd00 | |||
0a5112d302 | |||
bdb0ed3e5e | |||
7816d8593e | |||
816c793ae3 | |||
9f0d09f8ed | |||
2cbd2ee75f | |||
368974cf01 | |||
8be976a694 | |||
cab47d0b98 | |||
aa81711824 | |||
10fbb99a15 | |||
4657985468 | |||
68ac1d285a | |||
fe7524fca1 | |||
bf9b47ad66 | |||
8e49825e16 | |||
27b4749205 | |||
5b1f07a661 | |||
50128bbac6 | |||
debf80cfdc | |||
4ab47ca175 | |||
021413fbd9 | |||
8a39276e04 | |||
b5e64bc8b8 | |||
faa842c3d2 | |||
28b24115b7 | |||
198dc05753 | |||
178492e9bd | |||
fb9cdb591c | |||
4c5100de6b | |||
b587e6a4a1 | |||
773756d731 | |||
9efece1f01 | |||
bb6e8b1a51 | |||
0f98fc94f0 | |||
7f1963f1ac | |||
6064c393c6 | |||
0cecf05a5b | |||
dc6497f9eb | |||
e445970f36 | |||
c33741d588 | |||
5dfc84190d | |||
a1d11c0fcd | |||
863bbd420c | |||
4b37b2afba | |||
a366dbb16d | |||
423ad49490 | |||
2a4bda481d | |||
5b550a97a1 | |||
0fa0e4eb0f | |||
65e3f0ec95 | |||
c20f6e51ae | |||
cee8ead78a | |||
82fe0bb5c4 | |||
0b7efa57be | |||
9c11226b71 | |||
ae3606c9fb | |||
a0e25b8ea2 | |||
0931a17af5 | |||
c16bf2afdb | |||
04b4e80dd1 | |||
f178220c5a | |||
ed353d3263 | |||
ec6ec8813e | |||
3ea529d525 | |||
f35f10558b | |||
28287b8ed4 | |||
0f3ec51d14 | |||
75813deb81 | |||
66e57d5d11 | |||
fb2a213214 | |||
c0b11b8350 | |||
bea24d9654 | |||
a7bc62f8e4 | |||
2ef7e8f58e | |||
41d3b9314e | |||
1e9d49008b | |||
49d07a6762 | |||
9ce71371a9 | |||
c1c66da92b | |||
4121c1d573 | |||
108f3cf117 | |||
a6e263eded | |||
419916ee0c | |||
f7e6a96a02 | |||
b0356ba941 | |||
7ea5323a37 | |||
23e198d891 | |||
9f9849ccfd | |||
0c53eb8e22 | |||
9b62937db2 | |||
ebb8d632c4 | |||
43aae87fb0 | |||
3415514fde | |||
c0e0ddde76 | |||
39ae66a84f | |||
e8ec5b8b49 | |||
592271de3b | |||
5680b984cf | |||
f378d6cc2b | |||
04c12d9a75 | |||
31b5f779fb | |||
bb92cef764 | |||
6090f86b74 | |||
8c3569a047 | |||
6fa11fe637 | |||
9287eb7031 | |||
e54b261c0f | |||
60747b10b6 | |||
bf278355c4 | |||
d3d429db37 | |||
f2dcc83a56 | |||
26576b6bcd | |||
4cca82c3c8 | |||
1b82a157cc | |||
5409cffe33 | |||
45327f10b1 | |||
37645ba126 | |||
858b49d766 | |||
a3a1a0007d | |||
075f457bd1 | |||
5156971d75 | |||
8f3de3cc90 | |||
69cba4e6c7 | |||
6dcab6646c | |||
8e13eb6077 | |||
819a9b8d27 | |||
ec3cf0208c | |||
4aa5822ae2 | |||
5364480ca2 | |||
4802a36473 | |||
8333250b0b | |||
0cfab8ab6b | |||
8fd99855bd | |||
f2c36c58f9 | |||
f47fdfe386 | |||
8a11eebab8 | |||
3b1fc4b156 | |||
84cab17f5c | |||
db773864d5 | |||
b9840ceba9 | |||
729ec7866a | |||
a7140941ee | |||
34d1bbc2ed | |||
3ad0382cb0 | |||
ccc409e9cd | |||
fe21ba0e54 | |||
80a802386c | |||
aec0e86182 | |||
8e3cddc1ea | |||
3612e5834c | |||
031a2416a9 | |||
2eb9592b1a | |||
bbd9fa4a56 | |||
318ad25c11 | |||
c372eb7d20 | |||
68a99a0b32 | |||
7512231e20 | |||
f0e580d68b | |||
116015d3cf | |||
308ff50197 | |||
9df5cbbe85 | |||
a714a64bc2 | |||
ea18d99793 | |||
7c098529f7 | |||
e20c623e91 | |||
3260932741 | |||
f0e73474b7 | |||
7db829b0b5 | |||
ccaa9fd96e | |||
b4db06c763 | |||
3ebd2fdc6d | |||
8d06a6c969 | |||
2996efe9d5 | |||
43879f6813 | |||
72d4490ee7 | |||
6b92a5f4db | |||
2336a7265b | |||
d428fd055b | |||
e4b89371f0 | |||
6f9b30b46e | |||
35d589a15f | |||
8d77f2d8f3 | |||
7070a69711 | |||
81e961e8bc | |||
6a7a6ce942 | |||
7a65f8c837 | |||
678306b350 | |||
8864c811fe | |||
79206efcd0 | |||
b1d049c677 | |||
9012012503 | |||
06d30fc10f | |||
abd28d9269 | |||
c6c64b5499 | |||
5481b84a94 | |||
ab878e00c9 | |||
6773996d40 | |||
a8678c14e8 | |||
2e20b38bce | |||
bccbedfc31 | |||
0ab811194d | |||
7b54109168 | |||
2d088a865f | |||
0a8ec6b9da | |||
01b29c3917 | |||
5439ddeadf | |||
9d17d5277b | |||
c70fc7826a | |||
9ed2bb38c3 | |||
f458cf0d40 | |||
ce3dc86f78 | |||
d1927cb9cf | |||
e80426f72e | |||
97d2a15d3e | |||
1695412278 | |||
b4fa07334d | |||
29c244c635 | |||
f8a8ea2118 | |||
b80a5989a8 | |||
f5cd68168b | |||
b74ce14d80 | |||
afdc5e8531 | |||
b84579b866 | |||
4f3cf046fa | |||
c71af00146 | |||
793440feb6 | |||
b24d748462 | |||
4c49119ac5 | |||
90f09c7a78 | |||
00876f788c | |||
f09c48d79b | |||
dc696f8932 | |||
57daeb71e6 | |||
98b5f713a5 | |||
c8f0796952 | |||
120d7e42bf | |||
c2bd259c12 | |||
242d770098 | |||
1855fc769d | |||
217fef65e8 | |||
e15ed4cc58 | |||
9282dd08d9 | |||
a1cc118514 | |||
c73ee49425 | |||
ee69bccb6e | |||
0ff3ddb0c8 | |||
df459d456a | |||
c8cfb43316 | |||
3a7b697549 | |||
0fb87ab05f | |||
2ef8781378 | |||
3f96f0a8fb | |||
da377f6fda | |||
5cf1ec2400 | |||
6c1489a87b | |||
d5064fe75a | |||
541fa10964 | |||
00650df501 | |||
6ff5fb69d4 | |||
4057e2c6ab | |||
9fe2021d9f | |||
fe2f2f972e |
@ -4,7 +4,7 @@
|
|||||||
ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218
|
ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218
|
||||||
|
|
||||||
# Required
|
# Required
|
||||||
DB_CONNECTION_URI=postgres://infisical:infisical@db:5432/infisical
|
DB_CONNECTION_URI=postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@db:5432/${POSTGRES_DB}
|
||||||
|
|
||||||
# JWT
|
# JWT
|
||||||
# Required secrets to sign JWT tokens
|
# Required secrets to sign JWT tokens
|
||||||
@ -19,10 +19,6 @@ POSTGRES_DB=infisical
|
|||||||
# Redis
|
# Redis
|
||||||
REDIS_URL=redis://redis:6379
|
REDIS_URL=redis://redis:6379
|
||||||
|
|
||||||
# Optional credentials for MongoDB container instance and Mongo-Express
|
|
||||||
MONGO_USERNAME=root
|
|
||||||
MONGO_PASSWORD=example
|
|
||||||
|
|
||||||
# Website URL
|
# Website URL
|
||||||
# Required
|
# Required
|
||||||
SITE_URL=http://localhost:8080
|
SITE_URL=http://localhost:8080
|
||||||
|
4
.env.test.example
Normal file
4
.env.test.example
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
REDIS_URL=redis://localhost:6379
|
||||||
|
DB_CONNECTION_URI=postgres://infisical:infisical@localhost/infisical?sslmode=disable
|
||||||
|
AUTH_SECRET=4bnfe4e407b8921c104518903515b218
|
||||||
|
ENCRYPTION_KEY=4bnfe4e407b8921c104518903515b218
|
190
.github/resources/changelog-generator.py
vendored
Normal file
190
.github/resources/changelog-generator.py
vendored
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
# inspired by https://www.photoroom.com/inside-photoroom/how-we-automated-our-changelog-thanks-to-chatgpt
|
||||||
|
import os
|
||||||
|
import requests
|
||||||
|
import re
|
||||||
|
from openai import OpenAI
|
||||||
|
import subprocess
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
# Constants
|
||||||
|
REPO_OWNER = "infisical"
|
||||||
|
REPO_NAME = "infisical"
|
||||||
|
TOKEN = os.environ["GITHUB_TOKEN"]
|
||||||
|
SLACK_WEBHOOK_URL = os.environ["SLACK_WEBHOOK_URL"]
|
||||||
|
OPENAI_API_KEY = os.environ["OPENAI_API_KEY"]
|
||||||
|
SLACK_MSG_COLOR = "#36a64f"
|
||||||
|
|
||||||
|
headers = {
|
||||||
|
"Authorization": f"Bearer {TOKEN}",
|
||||||
|
"Accept": "application/vnd.github+json",
|
||||||
|
"X-GitHub-Api-Version": "2022-11-28",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def set_multiline_output(name, value):
|
||||||
|
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
|
||||||
|
delimiter = uuid.uuid1()
|
||||||
|
print(f'{name}<<{delimiter}', file=fh)
|
||||||
|
print(value, file=fh)
|
||||||
|
print(delimiter, file=fh)
|
||||||
|
|
||||||
|
def post_changelog_to_slack(changelog, tag):
|
||||||
|
slack_payload = {
|
||||||
|
"text": "Hey team, it's changelog time! :wave:",
|
||||||
|
"attachments": [
|
||||||
|
{
|
||||||
|
"color": SLACK_MSG_COLOR,
|
||||||
|
"title": f"🗓️Infisical Changelog - {tag}",
|
||||||
|
"text": changelog,
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
response = requests.post(SLACK_WEBHOOK_URL, json=slack_payload)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
raise Exception("Failed to post changelog to Slack.")
|
||||||
|
|
||||||
|
def find_previous_release_tag(release_tag:str):
|
||||||
|
previous_tag = subprocess.check_output(["git", "describe", "--tags", "--abbrev=0", f"{release_tag}^"]).decode("utf-8").strip()
|
||||||
|
while not(previous_tag.startswith("infisical/")):
|
||||||
|
previous_tag = subprocess.check_output(["git", "describe", "--tags", "--abbrev=0", f"{previous_tag}^"]).decode("utf-8").strip()
|
||||||
|
return previous_tag
|
||||||
|
|
||||||
|
def get_tag_creation_date(tag_name):
|
||||||
|
url = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/git/refs/tags/{tag_name}"
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
response.raise_for_status()
|
||||||
|
commit_sha = response.json()['object']['sha']
|
||||||
|
|
||||||
|
commit_url = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/commits/{commit_sha}"
|
||||||
|
commit_response = requests.get(commit_url, headers=headers)
|
||||||
|
commit_response.raise_for_status()
|
||||||
|
creation_date = commit_response.json()['commit']['author']['date']
|
||||||
|
|
||||||
|
return datetime.strptime(creation_date, '%Y-%m-%dT%H:%M:%SZ')
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_prs_between_tags(previous_tag_date:datetime, release_tag_date:datetime):
|
||||||
|
# Use GitHub API to fetch PRs merged between the commits
|
||||||
|
url = f"https://api.github.com/repos/{REPO_OWNER}/{REPO_NAME}/pulls?state=closed&merged=true"
|
||||||
|
response = requests.get(url, headers=headers)
|
||||||
|
|
||||||
|
if response.status_code != 200:
|
||||||
|
raise Exception("Error fetching PRs from GitHub API!")
|
||||||
|
|
||||||
|
prs = []
|
||||||
|
for pr in response.json():
|
||||||
|
# the idea is as tags happen recently we get last 100 closed PRs and then filter by tag creation date
|
||||||
|
if pr["merged_at"] and datetime.strptime(pr["merged_at"],'%Y-%m-%dT%H:%M:%SZ') < release_tag_date and datetime.strptime(pr["merged_at"],'%Y-%m-%dT%H:%M:%SZ') > previous_tag_date:
|
||||||
|
prs.append(pr)
|
||||||
|
|
||||||
|
return prs
|
||||||
|
|
||||||
|
|
||||||
|
def extract_commit_details_from_prs(prs):
|
||||||
|
commit_details = []
|
||||||
|
for pr in prs:
|
||||||
|
commit_message = pr["title"]
|
||||||
|
commit_url = pr["html_url"]
|
||||||
|
pr_number = pr["number"]
|
||||||
|
branch_name = pr["head"]["ref"]
|
||||||
|
issue_numbers = re.findall(r"(www-\d+|web-\d+)", branch_name)
|
||||||
|
|
||||||
|
# If no issue numbers are found, add the PR details without issue numbers and URLs
|
||||||
|
if not issue_numbers:
|
||||||
|
commit_details.append(
|
||||||
|
{
|
||||||
|
"message": commit_message,
|
||||||
|
"pr_number": pr_number,
|
||||||
|
"pr_url": commit_url,
|
||||||
|
"issue_number": None,
|
||||||
|
"issue_url": None,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
for issue in issue_numbers:
|
||||||
|
commit_details.append(
|
||||||
|
{
|
||||||
|
"message": commit_message,
|
||||||
|
"pr_number": pr_number,
|
||||||
|
"pr_url": commit_url,
|
||||||
|
"issue_number": issue,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return commit_details
|
||||||
|
|
||||||
|
# Function to generate changelog using OpenAI
|
||||||
|
def generate_changelog_with_openai(commit_details):
|
||||||
|
commit_messages = []
|
||||||
|
for details in commit_details:
|
||||||
|
base_message = f"{details['pr_url']} - {details['message']}"
|
||||||
|
# Add the issue URL if available
|
||||||
|
# if details["issue_url"]:
|
||||||
|
# base_message += f" (Linear Issue: {details['issue_url']})"
|
||||||
|
commit_messages.append(base_message)
|
||||||
|
|
||||||
|
commit_list = "\n".join(commit_messages)
|
||||||
|
prompt = """
|
||||||
|
Generate a changelog for Infisical, opensource secretops
|
||||||
|
The changelog should:
|
||||||
|
1. Be Informative: Using the provided list of GitHub commits, break them down into categories such as Features, Fixes & Improvements, and Technical Updates. Summarize each commit concisely, ensuring the key points are highlighted.
|
||||||
|
2. Have a Professional yet Friendly tone: The tone should be balanced, not too corporate or too informal.
|
||||||
|
3. Celebratory Introduction and Conclusion: Start the changelog with a celebratory note acknowledging the team's hard work and progress. End with a shoutout to the team and wishes for a pleasant weekend.
|
||||||
|
4. Formatting: you cannot use Markdown formatting, and you can only use emojis for the introductory paragraph or the conclusion paragraph, nowhere else.
|
||||||
|
5. Links: the syntax to create links is the following: `<http://www.example.com|This message is a link>`.
|
||||||
|
6. Linear Links: note that the Linear link is optional, include it only if provided.
|
||||||
|
7. Do not wrap your answer in a codeblock. Just output the text, nothing else
|
||||||
|
Here's a good example to follow, please try to match the formatting as closely as possible, only changing the content of the changelog and have some liberty with the introduction. Notice the importance of the formatting of a changelog item:
|
||||||
|
- <https://github.com/facebook/react/pull/27304/%7C#27304>: We optimize our ci to strip comments and minify production builds. (<https://linear.app/example/issue/WEB-1234/%7CWEB-1234>))
|
||||||
|
And here's an example of the full changelog:
|
||||||
|
|
||||||
|
*Features*
|
||||||
|
• <https://github.com/facebook/react/pull/27304/%7C#27304>: We optimize our ci to strip comments and minify production builds. (<https://linear.app/example/issue/WEB-1234/%7CWEB-1234>)
|
||||||
|
*Fixes & Improvements*
|
||||||
|
• <https://github.com/facebook/react/pull/27304/%7C#27304>: We optimize our ci to strip comments and minify production builds. (<https://linear.app/example/issue/WEB-1234/%7CWEB-1234>)
|
||||||
|
*Technical Updates*
|
||||||
|
• <https://github.com/facebook/react/pull/27304/%7C#27304>: We optimize our ci to strip comments and minify production builds. (<https://linear.app/example/issue/WEB-1234/%7CWEB-1234>)
|
||||||
|
|
||||||
|
Stay tuned for more exciting updates coming soon!
|
||||||
|
And here are the commits:
|
||||||
|
{}
|
||||||
|
""".format(
|
||||||
|
commit_list
|
||||||
|
)
|
||||||
|
|
||||||
|
client = OpenAI(api_key=OPENAI_API_KEY)
|
||||||
|
messages = [{"role": "user", "content": prompt}]
|
||||||
|
response = client.chat.completions.create(model="gpt-3.5-turbo", messages=messages)
|
||||||
|
|
||||||
|
if "error" in response.choices[0].message:
|
||||||
|
raise Exception("Error generating changelog with OpenAI!")
|
||||||
|
|
||||||
|
return response.choices[0].message.content.strip()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
try:
|
||||||
|
# Get the latest and previous release tags
|
||||||
|
latest_tag = subprocess.check_output(["git", "describe", "--tags", "--abbrev=0"]).decode("utf-8").strip()
|
||||||
|
previous_tag = find_previous_release_tag(latest_tag)
|
||||||
|
|
||||||
|
latest_tag_date = get_tag_creation_date(latest_tag)
|
||||||
|
previous_tag_date = get_tag_creation_date(previous_tag)
|
||||||
|
|
||||||
|
prs = fetch_prs_between_tags(previous_tag_date,latest_tag_date)
|
||||||
|
pr_details = extract_commit_details_from_prs(prs)
|
||||||
|
|
||||||
|
# Generate changelog
|
||||||
|
changelog = generate_changelog_with_openai(pr_details)
|
||||||
|
|
||||||
|
post_changelog_to_slack(changelog,latest_tag)
|
||||||
|
# Print or post changelog to Slack
|
||||||
|
# set_multiline_output("changelog", changelog)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(str(e))
|
15
.github/values.yaml
vendored
15
.github/values.yaml
vendored
@ -13,11 +13,10 @@ fullnameOverride: ""
|
|||||||
##
|
##
|
||||||
|
|
||||||
infisical:
|
infisical:
|
||||||
## @param backend.enabled Enable backend
|
autoDatabaseSchemaMigration: false
|
||||||
##
|
|
||||||
enabled: false
|
enabled: false
|
||||||
## @param backend.name Backend name
|
|
||||||
##
|
|
||||||
name: infisical
|
name: infisical
|
||||||
replicaCount: 3
|
replicaCount: 3
|
||||||
image:
|
image:
|
||||||
@ -28,7 +27,7 @@ infisical:
|
|||||||
deploymentAnnotations:
|
deploymentAnnotations:
|
||||||
secrets.infisical.com/auto-reload: "true"
|
secrets.infisical.com/auto-reload: "true"
|
||||||
|
|
||||||
kubeSecretRef: "infisical-gamma-secrets"
|
kubeSecretRef: "managed-secret"
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
## @param ingress.enabled Enable ingress
|
## @param ingress.enabled Enable ingress
|
||||||
@ -50,3 +49,9 @@ ingress:
|
|||||||
- secretName: letsencrypt-prod
|
- secretName: letsencrypt-prod
|
||||||
hosts:
|
hosts:
|
||||||
- gamma.infisical.com
|
- gamma.infisical.com
|
||||||
|
|
||||||
|
postgresql:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
redis:
|
||||||
|
enabled: false
|
||||||
|
@ -28,7 +28,7 @@ jobs:
|
|||||||
run: docker build --tag infisical-api .
|
run: docker build --tag infisical-api .
|
||||||
working-directory: backend
|
working-directory: backend
|
||||||
- name: Start postgres and redis
|
- name: Start postgres and redis
|
||||||
run: touch .env && docker-compose -f docker-compose.prod.yml up -d db redis
|
run: touch .env && docker-compose -f docker-compose.dev.yml up -d db redis
|
||||||
- name: Start the server
|
- name: Start the server
|
||||||
run: |
|
run: |
|
||||||
echo "SECRET_SCANNING_GIT_APP_ID=793712" >> .env
|
echo "SECRET_SCANNING_GIT_APP_ID=793712" >> .env
|
||||||
@ -70,6 +70,6 @@ jobs:
|
|||||||
run: oasdiff breaking https://app.infisical.com/api/docs/json http://localhost:4000/api/docs/json --fail-on ERR
|
run: oasdiff breaking https://app.infisical.com/api/docs/json http://localhost:4000/api/docs/json --fail-on ERR
|
||||||
- name: cleanup
|
- name: cleanup
|
||||||
run: |
|
run: |
|
||||||
docker-compose -f "docker-compose.pg.yml" down
|
docker-compose -f "docker-compose.dev.yml" down
|
||||||
docker stop infisical-api
|
docker stop infisical-api
|
||||||
docker remove infisical-api
|
docker remove infisical-api
|
@ -1,4 +1,4 @@
|
|||||||
name: Check Frontend Pull Request
|
name: Check Frontend Type and Lint check
|
||||||
|
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
@ -10,8 +10,8 @@ on:
|
|||||||
- "frontend/.eslintrc.js"
|
- "frontend/.eslintrc.js"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
check-fe-pr:
|
check-fe-ts-lint:
|
||||||
name: Check
|
name: Check Frontend Type and Lint check
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
|
|
||||||
@ -25,12 +25,11 @@ jobs:
|
|||||||
cache: "npm"
|
cache: "npm"
|
||||||
cache-dependency-path: frontend/package-lock.json
|
cache-dependency-path: frontend/package-lock.json
|
||||||
- name: 📦 Install dependencies
|
- name: 📦 Install dependencies
|
||||||
run: npm ci --only-production --ignore-scripts
|
run: npm install
|
||||||
working-directory: frontend
|
working-directory: frontend
|
||||||
# -
|
- name: 🏗️ Run Type check
|
||||||
# name: 🧪 Run tests
|
run: npm run type:check
|
||||||
# run: npm run test:ci
|
working-directory: frontend
|
||||||
# working-directory: frontend
|
- name: 🏗️ Run Link check
|
||||||
- name: 🏗️ Run build
|
run: npm run lint:fix
|
||||||
run: npm run build
|
|
||||||
working-directory: frontend
|
working-directory: frontend
|
34
.github/workflows/generate-release-changelog.yml
vendored
Normal file
34
.github/workflows/generate-release-changelog.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
name: Generate Changelog
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
generate_changelog:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-tags: true
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: Set up Python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: "3.12.0"
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install requests openai
|
||||||
|
- name: Generate Changelog and Post to Slack
|
||||||
|
id: gen-changelog
|
||||||
|
run: python .github/resources/changelog-generator.py
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
|
||||||
|
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
|
@ -5,9 +5,14 @@ on:
|
|||||||
- "infisical/v*.*.*-postgres"
|
- "infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
infisical-tests:
|
||||||
|
name: Run tests before deployment
|
||||||
|
# https://docs.github.com/en/actions/using-workflows/reusing-workflows#overview
|
||||||
|
uses: ./.github/workflows/run-backend-tests.yml
|
||||||
infisical-standalone:
|
infisical-standalone:
|
||||||
name: Build infisical standalone image postgres
|
name: Build infisical standalone image postgres
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: [infisical-tests]
|
||||||
steps:
|
steps:
|
||||||
- name: Extract version from tag
|
- name: Extract version from tag
|
||||||
id: extract_version
|
id: extract_version
|
||||||
|
@ -23,6 +23,8 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: 🔧 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
- run: git fetch --force --tags
|
- run: git fetch --force --tags
|
||||||
- run: echo "Ref name ${{github.ref_name}}"
|
- run: echo "Ref name ${{github.ref_name}}"
|
||||||
- uses: actions/setup-go@v3
|
- uses: actions/setup-go@v3
|
||||||
|
47
.github/workflows/run-backend-tests.yml
vendored
Normal file
47
.github/workflows/run-backend-tests.yml
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
name: "Run backend tests"
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
types: [opened, synchronize]
|
||||||
|
paths:
|
||||||
|
- "backend/**"
|
||||||
|
- "!backend/README.md"
|
||||||
|
- "!backend/.*"
|
||||||
|
- "backend/.eslintrc.js"
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
check-be-pr:
|
||||||
|
name: Run integration test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
|
steps:
|
||||||
|
- name: ☁️ Checkout source
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
- uses: KengoTODA/actions-setup-docker-compose@v1
|
||||||
|
if: ${{ env.ACT }}
|
||||||
|
name: Install `docker-compose` for local simulations
|
||||||
|
with:
|
||||||
|
version: "2.14.2"
|
||||||
|
- name: 🔧 Setup Node 20
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: "20"
|
||||||
|
cache: "npm"
|
||||||
|
cache-dependency-path: backend/package-lock.json
|
||||||
|
- name: Install dependencies
|
||||||
|
run: npm install
|
||||||
|
working-directory: backend
|
||||||
|
- name: Start postgres and redis
|
||||||
|
run: touch .env && docker-compose -f docker-compose.dev.yml up -d db redis
|
||||||
|
- name: Start integration test
|
||||||
|
run: npm run test:e2e
|
||||||
|
working-directory: backend
|
||||||
|
env:
|
||||||
|
REDIS_URL: redis://172.17.0.1:6379
|
||||||
|
DB_CONNECTION_URI: postgres://infisical:infisical@172.17.0.1:5432/infisical?sslmode=disable
|
||||||
|
AUTH_SECRET: something-random
|
||||||
|
ENCRYPTION_KEY: 4bnfe4e407b8921c104518903515b218
|
||||||
|
- name: cleanup
|
||||||
|
run: |
|
||||||
|
docker-compose -f "docker-compose.dev.yml" down
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -63,3 +63,5 @@ yarn-error.log*
|
|||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
||||||
frontend-build
|
frontend-build
|
||||||
|
|
||||||
|
*.tgz
|
||||||
|
@ -190,10 +190,34 @@ dockers:
|
|||||||
- dockerfile: docker/alpine
|
- dockerfile: docker/alpine
|
||||||
goos: linux
|
goos: linux
|
||||||
goarch: amd64
|
goarch: amd64
|
||||||
|
use: buildx
|
||||||
ids:
|
ids:
|
||||||
- all-other-builds
|
- all-other-builds
|
||||||
image_templates:
|
image_templates:
|
||||||
- "infisical/cli:{{ .Version }}"
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}-amd64"
|
||||||
- "infisical/cli:{{ .Major }}.{{ .Minor }}"
|
- "infisical/cli:latest-amd64"
|
||||||
- "infisical/cli:{{ .Major }}"
|
build_flag_templates:
|
||||||
- "infisical/cli:latest"
|
- "--pull"
|
||||||
|
- "--platform=linux/amd64"
|
||||||
|
- dockerfile: docker/alpine
|
||||||
|
goos: linux
|
||||||
|
goarch: amd64
|
||||||
|
use: buildx
|
||||||
|
ids:
|
||||||
|
- all-other-builds
|
||||||
|
image_templates:
|
||||||
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}-arm64"
|
||||||
|
- "infisical/cli:latest-arm64"
|
||||||
|
build_flag_templates:
|
||||||
|
- "--pull"
|
||||||
|
- "--platform=linux/arm64"
|
||||||
|
|
||||||
|
docker_manifests:
|
||||||
|
- name_template: "infisical/cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}"
|
||||||
|
image_templates:
|
||||||
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}-amd64"
|
||||||
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}.{{ .Patch }}-arm64"
|
||||||
|
- name_template: "infisical/cli:latest"
|
||||||
|
image_templates:
|
||||||
|
- "infisical/cli:latest-amd64"
|
||||||
|
- "infisical/cli:latest-arm64"
|
||||||
|
@ -2,6 +2,6 @@
|
|||||||
|
|
||||||
Thanks for taking the time to contribute! 😃 🚀
|
Thanks for taking the time to contribute! 😃 🚀
|
||||||
|
|
||||||
Please refer to our [Contributing Guide](https://infisical.com/docs/contributing/overview) for instructions on how to contribute.
|
Please refer to our [Contributing Guide](https://infisical.com/docs/contributing/getting-started/overview) for instructions on how to contribute.
|
||||||
|
|
||||||
We also have some 🔥amazing🔥 merch for our contributors. Please reach out to tony@infisical.com for more info 👀
|
We also have some 🔥amazing🔥 merch for our contributors. Please reach out to tony@infisical.com for more info 👀
|
||||||
|
5
Makefile
5
Makefile
@ -7,8 +7,11 @@ push:
|
|||||||
up-dev:
|
up-dev:
|
||||||
docker compose -f docker-compose.dev.yml up --build
|
docker compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
up-dev-ldap:
|
||||||
|
docker compose -f docker-compose.dev.yml --profile ldap up --build
|
||||||
|
|
||||||
up-prod:
|
up-prod:
|
||||||
docker-compose -f docker-compose.prod.yml up --build
|
docker-compose -f docker-compose.prod.yml up --build
|
||||||
|
|
||||||
down:
|
down:
|
||||||
docker-compose down
|
docker compose -f docker-compose.dev.yml down
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
vitest-environment-infisical.ts
|
vitest-environment-infisical.ts
|
||||||
vitest.config.ts
|
vitest.config.ts
|
||||||
|
vitest.e2e.config.ts
|
||||||
|
@ -21,6 +21,18 @@ module.exports = {
|
|||||||
tsconfigRootDir: __dirname
|
tsconfigRootDir: __dirname
|
||||||
},
|
},
|
||||||
root: true,
|
root: true,
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ["./e2e-test/**/*"],
|
||||||
|
rules: {
|
||||||
|
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||||
|
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||||
|
"@typescript-eslint/no-unsafe-argument": "off",
|
||||||
|
"@typescript-eslint/no-unsafe-return": "off",
|
||||||
|
"@typescript-eslint/no-unsafe-call": "off",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
rules: {
|
rules: {
|
||||||
"@typescript-eslint/no-empty-function": "off",
|
"@typescript-eslint/no-empty-function": "off",
|
||||||
"@typescript-eslint/no-unsafe-enum-comparison": "off",
|
"@typescript-eslint/no-unsafe-enum-comparison": "off",
|
||||||
|
30
backend/e2e-test/mocks/keystore.ts
Normal file
30
backend/e2e-test/mocks/keystore.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { TKeyStoreFactory } from "@app/keystore/keystore";
|
||||||
|
|
||||||
|
export const mockKeyStore = (): TKeyStoreFactory => {
|
||||||
|
const store: Record<string, string | number | Buffer> = {};
|
||||||
|
|
||||||
|
return {
|
||||||
|
setItem: async (key, value) => {
|
||||||
|
store[key] = value;
|
||||||
|
return "OK";
|
||||||
|
},
|
||||||
|
setItemWithExpiry: async (key, value) => {
|
||||||
|
store[key] = value;
|
||||||
|
return "OK";
|
||||||
|
},
|
||||||
|
deleteItem: async (key) => {
|
||||||
|
delete store[key];
|
||||||
|
return 1;
|
||||||
|
},
|
||||||
|
getItem: async (key) => {
|
||||||
|
const value = store[key];
|
||||||
|
if (typeof value === "string") {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
incrementBy: async () => {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
71
backend/e2e-test/routes/v1/identity.spec.ts
Normal file
71
backend/e2e-test/routes/v1/identity.spec.ts
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
import { OrgMembershipRole } from "@app/db/schemas";
|
||||||
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
|
||||||
|
export const createIdentity = async (name: string, role: string) => {
|
||||||
|
const createIdentityRes = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: "/api/v1/identities",
|
||||||
|
body: {
|
||||||
|
name,
|
||||||
|
role,
|
||||||
|
organizationId: seedData1.organization.id
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(createIdentityRes.statusCode).toBe(200);
|
||||||
|
return createIdentityRes.json().identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteIdentity = async (id: string) => {
|
||||||
|
const deleteIdentityRes = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v1/identities/${id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(deleteIdentityRes.statusCode).toBe(200);
|
||||||
|
return deleteIdentityRes.json().identity;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Identity v1", async () => {
|
||||||
|
test("Create identity", async () => {
|
||||||
|
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||||
|
expect(newIdentity.name).toBe("mac1");
|
||||||
|
expect(newIdentity.authMethod).toBeNull();
|
||||||
|
|
||||||
|
await deleteIdentity(newIdentity.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Update identity", async () => {
|
||||||
|
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||||
|
expect(newIdentity.name).toBe("mac1");
|
||||||
|
expect(newIdentity.authMethod).toBeNull();
|
||||||
|
|
||||||
|
const updatedIdentity = await testServer.inject({
|
||||||
|
method: "PATCH",
|
||||||
|
url: `/api/v1/identities/${newIdentity.id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
name: "updated-mac-1",
|
||||||
|
role: OrgMembershipRole.Member
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(updatedIdentity.statusCode).toBe(200);
|
||||||
|
expect(updatedIdentity.json().identity.name).toBe("updated-mac-1");
|
||||||
|
|
||||||
|
await deleteIdentity(newIdentity.id);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Delete Identity", async () => {
|
||||||
|
const newIdentity = await createIdentity("mac1", OrgMembershipRole.Admin);
|
||||||
|
|
||||||
|
const deletedIdentity = await deleteIdentity(newIdentity.id);
|
||||||
|
expect(deletedIdentity.name).toBe("mac1");
|
||||||
|
});
|
||||||
|
});
|
@ -1,6 +1,7 @@
|
|||||||
import { seedData1 } from "@app/db/seed-data";
|
|
||||||
import jsrp from "jsrp";
|
import jsrp from "jsrp";
|
||||||
|
|
||||||
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
|
||||||
describe("Login V1 Router", async () => {
|
describe("Login V1 Router", async () => {
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const client = new jsrp.client();
|
const client = new jsrp.client();
|
||||||
|
@ -1,6 +1,40 @@
|
|||||||
import { seedData1 } from "@app/db/seed-data";
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
import { DEFAULT_PROJECT_ENVS } from "@app/db/seeds/3-project";
|
import { DEFAULT_PROJECT_ENVS } from "@app/db/seeds/3-project";
|
||||||
|
|
||||||
|
const createProjectEnvironment = async (name: string, slug: string) => {
|
||||||
|
const res = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v1/workspace/${seedData1.project.id}/environments`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
name,
|
||||||
|
slug
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
const payload = JSON.parse(res.payload);
|
||||||
|
expect(payload).toHaveProperty("environment");
|
||||||
|
return payload.environment;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteProjectEnvironment = async (envId: string) => {
|
||||||
|
const res = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v1/workspace/${seedData1.project.id}/environments/${envId}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
const payload = JSON.parse(res.payload);
|
||||||
|
expect(payload).toHaveProperty("environment");
|
||||||
|
return payload.environment;
|
||||||
|
};
|
||||||
|
|
||||||
describe("Project Environment Router", async () => {
|
describe("Project Environment Router", async () => {
|
||||||
test("Get default environments", async () => {
|
test("Get default environments", async () => {
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
@ -31,24 +65,10 @@ describe("Project Environment Router", async () => {
|
|||||||
expect(payload.workspace.environments.length).toBe(3);
|
expect(payload.workspace.environments.length).toBe(3);
|
||||||
});
|
});
|
||||||
|
|
||||||
const mockProjectEnv = { name: "temp", slug: "temp", id: "" }; // id will be filled in create op
|
const mockProjectEnv = { name: "temp", slug: "temp" }; // id will be filled in create op
|
||||||
test("Create environment", async () => {
|
test("Create environment", async () => {
|
||||||
const res = await testServer.inject({
|
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
|
||||||
method: "POST",
|
expect(newEnvironment).toEqual(
|
||||||
url: `/api/v1/workspace/${seedData1.project.id}/environments`,
|
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
name: mockProjectEnv.name,
|
|
||||||
slug: mockProjectEnv.slug
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
|
||||||
const payload = JSON.parse(res.payload);
|
|
||||||
expect(payload).toHaveProperty("environment");
|
|
||||||
expect(payload.environment).toEqual(
|
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
name: mockProjectEnv.name,
|
name: mockProjectEnv.name,
|
||||||
@ -59,14 +79,15 @@ describe("Project Environment Router", async () => {
|
|||||||
updatedAt: expect.any(String)
|
updatedAt: expect.any(String)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
mockProjectEnv.id = payload.environment.id;
|
await deleteProjectEnvironment(newEnvironment.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Update environment", async () => {
|
test("Update environment", async () => {
|
||||||
|
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
|
||||||
const updatedName = { name: "temp#2", slug: "temp2" };
|
const updatedName = { name: "temp#2", slug: "temp2" };
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
url: `/api/v1/workspace/${seedData1.project.id}/environments/${mockProjectEnv.id}`,
|
url: `/api/v1/workspace/${seedData1.project.id}/environments/${newEnvironment.id}`,
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
},
|
},
|
||||||
@ -82,7 +103,7 @@ describe("Project Environment Router", async () => {
|
|||||||
expect(payload).toHaveProperty("environment");
|
expect(payload).toHaveProperty("environment");
|
||||||
expect(payload.environment).toEqual(
|
expect(payload.environment).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: newEnvironment.id,
|
||||||
name: updatedName.name,
|
name: updatedName.name,
|
||||||
slug: updatedName.slug,
|
slug: updatedName.slug,
|
||||||
projectId: seedData1.project.id,
|
projectId: seedData1.project.id,
|
||||||
@ -91,61 +112,21 @@ describe("Project Environment Router", async () => {
|
|||||||
updatedAt: expect.any(String)
|
updatedAt: expect.any(String)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
mockProjectEnv.name = updatedName.name;
|
await deleteProjectEnvironment(newEnvironment.id);
|
||||||
mockProjectEnv.slug = updatedName.slug;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Delete environment", async () => {
|
test("Delete environment", async () => {
|
||||||
const res = await testServer.inject({
|
const newEnvironment = await createProjectEnvironment(mockProjectEnv.name, mockProjectEnv.slug);
|
||||||
method: "DELETE",
|
const deletedProjectEnvironment = await deleteProjectEnvironment(newEnvironment.id);
|
||||||
url: `/api/v1/workspace/${seedData1.project.id}/environments/${mockProjectEnv.id}`,
|
expect(deletedProjectEnvironment).toEqual(
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
|
||||||
const payload = JSON.parse(res.payload);
|
|
||||||
expect(payload).toHaveProperty("environment");
|
|
||||||
expect(payload.environment).toEqual(
|
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: deletedProjectEnvironment.id,
|
||||||
name: mockProjectEnv.name,
|
name: mockProjectEnv.name,
|
||||||
slug: mockProjectEnv.slug,
|
slug: mockProjectEnv.slug,
|
||||||
position: 1,
|
position: 4,
|
||||||
createdAt: expect.any(String),
|
createdAt: expect.any(String),
|
||||||
updatedAt: expect.any(String)
|
updatedAt: expect.any(String)
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// after all these opreations the list of environment should be still same
|
|
||||||
test("Default list of environment", async () => {
|
|
||||||
const res = await testServer.inject({
|
|
||||||
method: "GET",
|
|
||||||
url: `/api/v1/workspace/${seedData1.project.id}`,
|
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
|
||||||
const payload = JSON.parse(res.payload);
|
|
||||||
expect(payload).toHaveProperty("workspace");
|
|
||||||
// check for default environments
|
|
||||||
expect(payload).toEqual({
|
|
||||||
workspace: expect.objectContaining({
|
|
||||||
name: seedData1.project.name,
|
|
||||||
id: seedData1.project.id,
|
|
||||||
slug: seedData1.project.slug,
|
|
||||||
environments: expect.arrayContaining([
|
|
||||||
expect.objectContaining(DEFAULT_PROJECT_ENVS[0]),
|
|
||||||
expect.objectContaining(DEFAULT_PROJECT_ENVS[1]),
|
|
||||||
expect.objectContaining(DEFAULT_PROJECT_ENVS[2])
|
|
||||||
])
|
|
||||||
})
|
|
||||||
});
|
|
||||||
// ensure only two default environments exist
|
|
||||||
expect(payload.workspace.environments.length).toBe(3);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@ -1,12 +1,6 @@
|
|||||||
import { seedData1 } from "@app/db/seed-data";
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
|
||||||
describe("Secret Folder Router", async () => {
|
const createFolder = async (dto: { path: string; name: string }) => {
|
||||||
test.each([
|
|
||||||
{ name: "folder1", path: "/" }, // one in root
|
|
||||||
{ name: "folder1", path: "/level1/level2" }, // then create a deep one creating intermediate ones
|
|
||||||
{ name: "folder2", path: "/" },
|
|
||||||
{ name: "folder1", path: "/level1/level2" } // this should not create folder return same thing
|
|
||||||
])("Create folder $name in $path", async ({ name, path }) => {
|
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: `/api/v1/folders`,
|
url: `/api/v1/folders`,
|
||||||
@ -16,21 +10,47 @@ describe("Secret Folder Router", async () => {
|
|||||||
body: {
|
body: {
|
||||||
workspaceId: seedData1.project.id,
|
workspaceId: seedData1.project.id,
|
||||||
environment: seedData1.environment.slug,
|
environment: seedData1.environment.slug,
|
||||||
name,
|
name: dto.name,
|
||||||
path
|
path: dto.path
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
expect(res.statusCode).toBe(200);
|
||||||
const payload = JSON.parse(res.payload);
|
return res.json().folder;
|
||||||
expect(payload).toHaveProperty("folder");
|
};
|
||||||
|
|
||||||
|
const deleteFolder = async (dto: { path: string; id: string }) => {
|
||||||
|
const res = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v1/folders/${dto.id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
path: dto.path
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
return res.json().folder;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Secret Folder Router", async () => {
|
||||||
|
test.each([
|
||||||
|
{ name: "folder1", path: "/" }, // one in root
|
||||||
|
{ name: "folder1", path: "/level1/level2" }, // then create a deep one creating intermediate ones
|
||||||
|
{ name: "folder2", path: "/" },
|
||||||
|
{ name: "folder1", path: "/level1/level2" } // this should not create folder return same thing
|
||||||
|
])("Create folder $name in $path", async ({ name, path }) => {
|
||||||
|
const createdFolder = await createFolder({ path, name });
|
||||||
// check for default environments
|
// check for default environments
|
||||||
expect(payload).toEqual({
|
expect(createdFolder).toEqual(
|
||||||
folder: expect.objectContaining({
|
expect.objectContaining({
|
||||||
name,
|
name,
|
||||||
id: expect.any(String)
|
id: expect.any(String)
|
||||||
})
|
})
|
||||||
});
|
);
|
||||||
|
await deleteFolder({ path, id: createdFolder.id });
|
||||||
});
|
});
|
||||||
|
|
||||||
test.each([
|
test.each([
|
||||||
@ -43,6 +63,8 @@ describe("Secret Folder Router", async () => {
|
|||||||
},
|
},
|
||||||
{ path: "/level1/level2", expected: { folders: [{ name: "folder1" }], length: 1 } }
|
{ path: "/level1/level2", expected: { folders: [{ name: "folder1" }], length: 1 } }
|
||||||
])("Get folders $path", async ({ path, expected }) => {
|
])("Get folders $path", async ({ path, expected }) => {
|
||||||
|
const newFolders = await Promise.all(expected.folders.map(({ name }) => createFolder({ name, path })));
|
||||||
|
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `/api/v1/folders`,
|
url: `/api/v1/folders`,
|
||||||
@ -59,36 +81,22 @@ describe("Secret Folder Router", async () => {
|
|||||||
expect(res.statusCode).toBe(200);
|
expect(res.statusCode).toBe(200);
|
||||||
const payload = JSON.parse(res.payload);
|
const payload = JSON.parse(res.payload);
|
||||||
expect(payload).toHaveProperty("folders");
|
expect(payload).toHaveProperty("folders");
|
||||||
expect(payload.folders.length).toBe(expected.length);
|
expect(payload.folders.length >= expected.folders.length).toBeTruthy();
|
||||||
expect(payload).toEqual({ folders: expected.folders.map((el) => expect.objectContaining(el)) });
|
expect(payload).toEqual({
|
||||||
|
folders: expect.arrayContaining(expected.folders.map((el) => expect.objectContaining(el)))
|
||||||
|
});
|
||||||
|
|
||||||
|
await Promise.all(newFolders.map(({ id }) => deleteFolder({ path, id })));
|
||||||
});
|
});
|
||||||
|
|
||||||
let toBeDeleteFolderId = "";
|
|
||||||
test("Update a deep folder", async () => {
|
test("Update a deep folder", async () => {
|
||||||
const res = await testServer.inject({
|
const newFolder = await createFolder({ name: "folder-updated", path: "/level1/level2" });
|
||||||
method: "PATCH",
|
expect(newFolder).toEqual(
|
||||||
url: `/api/v1/folders/folder1`,
|
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
workspaceId: seedData1.project.id,
|
|
||||||
environment: seedData1.environment.slug,
|
|
||||||
name: "folder-updated",
|
|
||||||
path: "/level1/level2"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
|
||||||
const payload = JSON.parse(res.payload);
|
|
||||||
expect(payload).toHaveProperty("folder");
|
|
||||||
expect(payload.folder).toEqual(
|
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
name: "folder-updated"
|
name: "folder-updated"
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
toBeDeleteFolderId = payload.folder.id;
|
|
||||||
|
|
||||||
const resUpdatedFolders = await testServer.inject({
|
const resUpdatedFolders = await testServer.inject({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@ -106,14 +114,16 @@ describe("Secret Folder Router", async () => {
|
|||||||
expect(resUpdatedFolders.statusCode).toBe(200);
|
expect(resUpdatedFolders.statusCode).toBe(200);
|
||||||
const updatedFolderList = JSON.parse(resUpdatedFolders.payload);
|
const updatedFolderList = JSON.parse(resUpdatedFolders.payload);
|
||||||
expect(updatedFolderList).toHaveProperty("folders");
|
expect(updatedFolderList).toHaveProperty("folders");
|
||||||
expect(updatedFolderList.folders.length).toEqual(1);
|
|
||||||
expect(updatedFolderList.folders[0].name).toEqual("folder-updated");
|
expect(updatedFolderList.folders[0].name).toEqual("folder-updated");
|
||||||
|
|
||||||
|
await deleteFolder({ path: "/level1/level2", id: newFolder.id });
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Delete a deep folder", async () => {
|
test("Delete a deep folder", async () => {
|
||||||
|
const newFolder = await createFolder({ name: "folder-updated", path: "/level1/level2" });
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "DELETE",
|
method: "DELETE",
|
||||||
url: `/api/v1/folders/${toBeDeleteFolderId}`,
|
url: `/api/v1/folders/${newFolder.id}`,
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
},
|
},
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
import { seedData1 } from "@app/db/seed-data";
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
|
||||||
describe("Secret Folder Router", async () => {
|
const createSecretImport = async (importPath: string, importEnv: string) => {
|
||||||
test.each([
|
|
||||||
{ importEnv: "dev", importPath: "/" }, // one in root
|
|
||||||
{ importEnv: "staging", importPath: "/" } // then create a deep one creating intermediate ones
|
|
||||||
])("Create secret import $importEnv with path $importPath", async ({ importPath, importEnv }) => {
|
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: `/api/v1/secret-imports`,
|
url: `/api/v1/secret-imports`,
|
||||||
@ -25,8 +21,37 @@ describe("Secret Folder Router", async () => {
|
|||||||
expect(res.statusCode).toBe(200);
|
expect(res.statusCode).toBe(200);
|
||||||
const payload = JSON.parse(res.payload);
|
const payload = JSON.parse(res.payload);
|
||||||
expect(payload).toHaveProperty("secretImport");
|
expect(payload).toHaveProperty("secretImport");
|
||||||
|
return payload.secretImport;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteSecretImport = async (id: string) => {
|
||||||
|
const res = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v1/secret-imports/${id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
path: "/"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.statusCode).toBe(200);
|
||||||
|
const payload = JSON.parse(res.payload);
|
||||||
|
expect(payload).toHaveProperty("secretImport");
|
||||||
|
return payload.secretImport;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Secret Import Router", async () => {
|
||||||
|
test.each([
|
||||||
|
{ importEnv: "dev", importPath: "/" }, // one in root
|
||||||
|
{ importEnv: "staging", importPath: "/" } // then create a deep one creating intermediate ones
|
||||||
|
])("Create secret import $importEnv with path $importPath", async ({ importPath, importEnv }) => {
|
||||||
// check for default environments
|
// check for default environments
|
||||||
expect(payload.secretImport).toEqual(
|
const payload = await createSecretImport(importPath, importEnv);
|
||||||
|
expect(payload).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
importPath: expect.any(String),
|
importPath: expect.any(String),
|
||||||
@ -37,10 +62,12 @@ describe("Secret Folder Router", async () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
await deleteSecretImport(payload.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
let testSecretImportId = "";
|
|
||||||
test("Get secret imports", async () => {
|
test("Get secret imports", async () => {
|
||||||
|
const createdImport1 = await createSecretImport("/", "dev");
|
||||||
|
const createdImport2 = await createSecretImport("/", "staging");
|
||||||
const res = await testServer.inject({
|
const res = await testServer.inject({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: `/api/v1/secret-imports`,
|
url: `/api/v1/secret-imports`,
|
||||||
@ -58,7 +85,6 @@ describe("Secret Folder Router", async () => {
|
|||||||
const payload = JSON.parse(res.payload);
|
const payload = JSON.parse(res.payload);
|
||||||
expect(payload).toHaveProperty("secretImports");
|
expect(payload).toHaveProperty("secretImports");
|
||||||
expect(payload.secretImports.length).toBe(2);
|
expect(payload.secretImports.length).toBe(2);
|
||||||
testSecretImportId = payload.secretImports[0].id;
|
|
||||||
expect(payload.secretImports).toEqual(
|
expect(payload.secretImports).toEqual(
|
||||||
expect.arrayContaining([
|
expect.arrayContaining([
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
@ -72,12 +98,20 @@ describe("Secret Folder Router", async () => {
|
|||||||
})
|
})
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
|
await deleteSecretImport(createdImport1.id);
|
||||||
|
await deleteSecretImport(createdImport2.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Update secret import position", async () => {
|
test("Update secret import position", async () => {
|
||||||
const res = await testServer.inject({
|
const devImportDetails = { path: "/", envSlug: "dev" };
|
||||||
|
const stagingImportDetails = { path: "/", envSlug: "staging" };
|
||||||
|
|
||||||
|
const createdImport1 = await createSecretImport(devImportDetails.path, devImportDetails.envSlug);
|
||||||
|
const createdImport2 = await createSecretImport(stagingImportDetails.path, stagingImportDetails.envSlug);
|
||||||
|
|
||||||
|
const updateImportRes = await testServer.inject({
|
||||||
method: "PATCH",
|
method: "PATCH",
|
||||||
url: `/api/v1/secret-imports/${testSecretImportId}`,
|
url: `/api/v1/secret-imports/${createdImport1.id}`,
|
||||||
headers: {
|
headers: {
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
},
|
},
|
||||||
@ -91,8 +125,8 @@ describe("Secret Folder Router", async () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
expect(updateImportRes.statusCode).toBe(200);
|
||||||
const payload = JSON.parse(res.payload);
|
const payload = JSON.parse(updateImportRes.payload);
|
||||||
expect(payload).toHaveProperty("secretImport");
|
expect(payload).toHaveProperty("secretImport");
|
||||||
// check for default environments
|
// check for default environments
|
||||||
expect(payload.secretImport).toEqual(
|
expect(payload.secretImport).toEqual(
|
||||||
@ -102,7 +136,7 @@ describe("Secret Folder Router", async () => {
|
|||||||
position: 2,
|
position: 2,
|
||||||
importEnv: expect.objectContaining({
|
importEnv: expect.objectContaining({
|
||||||
name: expect.any(String),
|
name: expect.any(String),
|
||||||
slug: expect.any(String),
|
slug: expect.stringMatching(devImportDetails.envSlug),
|
||||||
id: expect.any(String)
|
id: expect.any(String)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -124,28 +158,19 @@ describe("Secret Folder Router", async () => {
|
|||||||
expect(secretImportsListRes.statusCode).toBe(200);
|
expect(secretImportsListRes.statusCode).toBe(200);
|
||||||
const secretImportList = JSON.parse(secretImportsListRes.payload);
|
const secretImportList = JSON.parse(secretImportsListRes.payload);
|
||||||
expect(secretImportList).toHaveProperty("secretImports");
|
expect(secretImportList).toHaveProperty("secretImports");
|
||||||
expect(secretImportList.secretImports[1].id).toEqual(testSecretImportId);
|
expect(secretImportList.secretImports[1].id).toEqual(createdImport1.id);
|
||||||
|
expect(secretImportList.secretImports[0].id).toEqual(createdImport2.id);
|
||||||
|
|
||||||
|
await deleteSecretImport(createdImport1.id);
|
||||||
|
await deleteSecretImport(createdImport2.id);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Delete secret import position", async () => {
|
test("Delete secret import position", async () => {
|
||||||
const res = await testServer.inject({
|
const createdImport1 = await createSecretImport("/", "dev");
|
||||||
method: "DELETE",
|
const createdImport2 = await createSecretImport("/", "staging");
|
||||||
url: `/api/v1/secret-imports/${testSecretImportId}`,
|
const deletedImport = await deleteSecretImport(createdImport1.id);
|
||||||
headers: {
|
|
||||||
authorization: `Bearer ${jwtAuthToken}`
|
|
||||||
},
|
|
||||||
body: {
|
|
||||||
workspaceId: seedData1.project.id,
|
|
||||||
environment: seedData1.environment.slug,
|
|
||||||
path: "/"
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(res.statusCode).toBe(200);
|
|
||||||
const payload = JSON.parse(res.payload);
|
|
||||||
expect(payload).toHaveProperty("secretImport");
|
|
||||||
// check for default environments
|
// check for default environments
|
||||||
expect(payload.secretImport).toEqual(
|
expect(deletedImport).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
id: expect.any(String),
|
id: expect.any(String),
|
||||||
importPath: expect.any(String),
|
importPath: expect.any(String),
|
||||||
@ -175,5 +200,7 @@ describe("Secret Folder Router", async () => {
|
|||||||
expect(secretImportList).toHaveProperty("secretImports");
|
expect(secretImportList).toHaveProperty("secretImports");
|
||||||
expect(secretImportList.secretImports.length).toEqual(1);
|
expect(secretImportList.secretImports.length).toEqual(1);
|
||||||
expect(secretImportList.secretImports[0].position).toEqual(1);
|
expect(secretImportList.secretImports[0].position).toEqual(1);
|
||||||
|
|
||||||
|
await deleteSecretImport(createdImport2.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
579
backend/e2e-test/routes/v2/service-token.spec.ts
Normal file
579
backend/e2e-test/routes/v2/service-token.spec.ts
Normal file
@ -0,0 +1,579 @@
|
|||||||
|
import crypto from "node:crypto";
|
||||||
|
|
||||||
|
import { SecretType, TSecrets } from "@app/db/schemas";
|
||||||
|
import { decryptSecret, encryptSecret, getUserPrivateKey, seedData1 } from "@app/db/seed-data";
|
||||||
|
import { decryptAsymmetric, decryptSymmetric128BitHexKeyUTF8, encryptSymmetric128BitHexKeyUTF8 } from "@app/lib/crypto";
|
||||||
|
|
||||||
|
const createServiceToken = async (
|
||||||
|
scopes: { environment: string; secretPath: string }[],
|
||||||
|
permissions: ("read" | "write")[]
|
||||||
|
) => {
|
||||||
|
const projectKeyRes = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/v2/workspace/${seedData1.project.id}/encrypted-key`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const projectKeyEnc = JSON.parse(projectKeyRes.payload);
|
||||||
|
|
||||||
|
const userInfoRes = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: "/api/v2/users/me",
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const { user: userInfo } = JSON.parse(userInfoRes.payload);
|
||||||
|
const privateKey = await getUserPrivateKey(seedData1.password, userInfo);
|
||||||
|
const projectKey = decryptAsymmetric({
|
||||||
|
ciphertext: projectKeyEnc.encryptedKey,
|
||||||
|
nonce: projectKeyEnc.nonce,
|
||||||
|
publicKey: projectKeyEnc.sender.publicKey,
|
||||||
|
privateKey
|
||||||
|
});
|
||||||
|
|
||||||
|
const randomBytes = crypto.randomBytes(16).toString("hex");
|
||||||
|
const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8(projectKey, randomBytes);
|
||||||
|
const serviceTokenRes = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: "/api/v2/service-token",
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
name: "test-token",
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
scopes,
|
||||||
|
encryptedKey: ciphertext,
|
||||||
|
iv,
|
||||||
|
tag,
|
||||||
|
permissions,
|
||||||
|
expiresIn: null
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(serviceTokenRes.statusCode).toBe(200);
|
||||||
|
const serviceTokenInfo = serviceTokenRes.json();
|
||||||
|
expect(serviceTokenInfo).toHaveProperty("serviceToken");
|
||||||
|
expect(serviceTokenInfo).toHaveProperty("serviceTokenData");
|
||||||
|
return `${serviceTokenInfo.serviceToken}.${randomBytes}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteServiceToken = async () => {
|
||||||
|
const serviceTokenListRes = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/v1/workspace/${seedData1.project.id}/service-token-data`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(serviceTokenListRes.statusCode).toBe(200);
|
||||||
|
const serviceTokens = JSON.parse(serviceTokenListRes.payload).serviceTokenData as { name: string; id: string }[];
|
||||||
|
expect(serviceTokens.length).toBeGreaterThan(0);
|
||||||
|
const serviceTokenInfo = serviceTokens.find(({ name }) => name === "test-token");
|
||||||
|
expect(serviceTokenInfo).toBeDefined();
|
||||||
|
|
||||||
|
const deleteTokenRes = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v2/service-token/${serviceTokenInfo?.id}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(deleteTokenRes.statusCode).toBe(200);
|
||||||
|
};
|
||||||
|
|
||||||
|
const createSecret = async (dto: {
|
||||||
|
projectKey: string;
|
||||||
|
path: string;
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
comment: string;
|
||||||
|
type?: SecretType;
|
||||||
|
token: string;
|
||||||
|
}) => {
|
||||||
|
const createSecretReqBody = {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
type: dto.type || SecretType.Shared,
|
||||||
|
secretPath: dto.path,
|
||||||
|
...encryptSecret(dto.projectKey, dto.key, dto.value, dto.comment)
|
||||||
|
};
|
||||||
|
const createSecRes = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v3/secrets/${dto.key}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${dto.token}`
|
||||||
|
},
|
||||||
|
body: createSecretReqBody
|
||||||
|
});
|
||||||
|
expect(createSecRes.statusCode).toBe(200);
|
||||||
|
const createdSecretPayload = JSON.parse(createSecRes.payload);
|
||||||
|
expect(createdSecretPayload).toHaveProperty("secret");
|
||||||
|
return createdSecretPayload.secret;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteSecret = async (dto: { path: string; key: string; token: string }) => {
|
||||||
|
const deleteSecRes = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v3/secrets/${dto.key}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${dto.token}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: dto.path
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(deleteSecRes.statusCode).toBe(200);
|
||||||
|
const updatedSecretPayload = JSON.parse(deleteSecRes.payload);
|
||||||
|
expect(updatedSecretPayload).toHaveProperty("secret");
|
||||||
|
return updatedSecretPayload.secret;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe("Service token secret ops", async () => {
|
||||||
|
let serviceToken = "";
|
||||||
|
let projectKey = "";
|
||||||
|
let folderId = "";
|
||||||
|
beforeAll(async () => {
|
||||||
|
serviceToken = await createServiceToken(
|
||||||
|
[{ secretPath: "/**", environment: seedData1.environment.slug }],
|
||||||
|
["read", "write"]
|
||||||
|
);
|
||||||
|
|
||||||
|
// this is ensure cli service token decryptiong working fine
|
||||||
|
const serviceTokenInfoRes = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: "/api/v2/service-token",
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(serviceTokenInfoRes.statusCode).toBe(200);
|
||||||
|
const serviceTokenInfo = serviceTokenInfoRes.json();
|
||||||
|
const serviceTokenParts = serviceToken.split(".");
|
||||||
|
projectKey = decryptSymmetric128BitHexKeyUTF8({
|
||||||
|
key: serviceTokenParts[3],
|
||||||
|
tag: serviceTokenInfo.tag,
|
||||||
|
ciphertext: serviceTokenInfo.encryptedKey,
|
||||||
|
iv: serviceTokenInfo.iv
|
||||||
|
});
|
||||||
|
|
||||||
|
// create a deep folder
|
||||||
|
const folderCreate = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v1/folders`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
name: "folder",
|
||||||
|
path: "/nested1/nested2"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(folderCreate.statusCode).toBe(200);
|
||||||
|
folderId = folderCreate.json().folder.id;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterAll(async () => {
|
||||||
|
await deleteServiceToken();
|
||||||
|
|
||||||
|
// create a deep folder
|
||||||
|
const deleteFolder = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v1/folders/${folderId}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${jwtAuthToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
path: "/nested1/nested2"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(deleteFolder.statusCode).toBe(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
const testSecrets = [
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
secret: {
|
||||||
|
key: "ST-SEC",
|
||||||
|
value: "something-secret",
|
||||||
|
comment: "some comment"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: "/nested1/nested2/folder",
|
||||||
|
secret: {
|
||||||
|
key: "NESTED-ST-SEC",
|
||||||
|
value: "something-secret",
|
||||||
|
comment: "some comment"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
const getSecrets = async (environment: string, secretPath = "/") => {
|
||||||
|
const res = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/v3/secrets`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
secretPath,
|
||||||
|
environment,
|
||||||
|
workspaceId: seedData1.project.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const secrets: TSecrets[] = JSON.parse(res.payload).secrets || [];
|
||||||
|
return secrets.map((el) => ({ ...decryptSecret(projectKey, el), type: el.type }));
|
||||||
|
};
|
||||||
|
|
||||||
|
test.each(testSecrets)("Create secret in path $path", async ({ secret, path }) => {
|
||||||
|
const createdSecret = await createSecret({ projectKey, path, ...secret, token: serviceToken });
|
||||||
|
const decryptedSecret = decryptSecret(projectKey, createdSecret);
|
||||||
|
expect(decryptedSecret.key).toEqual(secret.key);
|
||||||
|
expect(decryptedSecret.value).toEqual(secret.value);
|
||||||
|
expect(decryptedSecret.comment).toEqual(secret.comment);
|
||||||
|
expect(decryptedSecret.version).toEqual(1);
|
||||||
|
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
key: secret.key,
|
||||||
|
value: secret.value,
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
])
|
||||||
|
);
|
||||||
|
await deleteSecret({ path, key: secret.key, token: serviceToken });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Get secret by name in path $path", async ({ secret, path }) => {
|
||||||
|
await createSecret({ projectKey, path, ...secret, token: serviceToken });
|
||||||
|
|
||||||
|
const getSecByNameRes = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: `/api/v3/secrets/${secret.key}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
secretPath: path,
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(getSecByNameRes.statusCode).toBe(200);
|
||||||
|
const getSecretByNamePayload = JSON.parse(getSecByNameRes.payload);
|
||||||
|
expect(getSecretByNamePayload).toHaveProperty("secret");
|
||||||
|
const decryptedSecret = decryptSecret(projectKey, getSecretByNamePayload.secret);
|
||||||
|
expect(decryptedSecret.key).toEqual(secret.key);
|
||||||
|
expect(decryptedSecret.value).toEqual(secret.value);
|
||||||
|
expect(decryptedSecret.comment).toEqual(secret.comment);
|
||||||
|
|
||||||
|
await deleteSecret({ path, key: secret.key, token: serviceToken });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Update secret in path $path", async ({ path, secret }) => {
|
||||||
|
await createSecret({ projectKey, path, ...secret, token: serviceToken });
|
||||||
|
const updateSecretReqBody = {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
type: SecretType.Shared,
|
||||||
|
secretPath: path,
|
||||||
|
...encryptSecret(projectKey, secret.key, "new-value", secret.comment)
|
||||||
|
};
|
||||||
|
const updateSecRes = await testServer.inject({
|
||||||
|
method: "PATCH",
|
||||||
|
url: `/api/v3/secrets/${secret.key}`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
body: updateSecretReqBody
|
||||||
|
});
|
||||||
|
expect(updateSecRes.statusCode).toBe(200);
|
||||||
|
const updatedSecretPayload = JSON.parse(updateSecRes.payload);
|
||||||
|
expect(updatedSecretPayload).toHaveProperty("secret");
|
||||||
|
const decryptedSecret = decryptSecret(projectKey, updatedSecretPayload.secret);
|
||||||
|
expect(decryptedSecret.key).toEqual(secret.key);
|
||||||
|
expect(decryptedSecret.value).toEqual("new-value");
|
||||||
|
expect(decryptedSecret.comment).toEqual(secret.comment);
|
||||||
|
|
||||||
|
// list secret should have updated value
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
key: secret.key,
|
||||||
|
value: "new-value",
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
await deleteSecret({ path, key: secret.key, token: serviceToken });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Delete secret in path $path", async ({ secret, path }) => {
|
||||||
|
await createSecret({ projectKey, path, ...secret, token: serviceToken });
|
||||||
|
const deletedSecret = await deleteSecret({ path, key: secret.key, token: serviceToken });
|
||||||
|
const decryptedSecret = decryptSecret(projectKey, deletedSecret);
|
||||||
|
expect(decryptedSecret.key).toEqual(secret.key);
|
||||||
|
|
||||||
|
// shared secret deletion should delete personal ones also
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.not.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
key: secret.key,
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Bulk create secrets in path $path", async ({ secret, path }) => {
|
||||||
|
const createSharedSecRes = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v3/secrets/batch`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: path,
|
||||||
|
secrets: Array.from(Array(5)).map((_e, i) => ({
|
||||||
|
secretName: `BULK-${secret.key}-${i + 1}`,
|
||||||
|
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, secret.value, secret.comment)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(createSharedSecRes.statusCode).toBe(200);
|
||||||
|
const createSharedSecPayload = JSON.parse(createSharedSecRes.payload);
|
||||||
|
expect(createSharedSecPayload).toHaveProperty("secrets");
|
||||||
|
|
||||||
|
// bulk ones should exist
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
expect.objectContaining({
|
||||||
|
key: `BULK-${secret.key}-${i + 1}`,
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
deleteSecret({ path, token: serviceToken, key: `BULK-${secret.key}-${i + 1}` })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Bulk create fail on existing secret in path $path", async ({ secret, path }) => {
|
||||||
|
await createSecret({ projectKey, ...secret, key: `BULK-${secret.key}-1`, path, token: serviceToken });
|
||||||
|
|
||||||
|
const createSharedSecRes = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v3/secrets/batch`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: path,
|
||||||
|
secrets: Array.from(Array(5)).map((_e, i) => ({
|
||||||
|
secretName: `BULK-${secret.key}-${i + 1}`,
|
||||||
|
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, secret.value, secret.comment)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(createSharedSecRes.statusCode).toBe(400);
|
||||||
|
|
||||||
|
await deleteSecret({ path, key: `BULK-${secret.key}-1`, token: serviceToken });
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Bulk update secrets in path $path", async ({ secret, path }) => {
|
||||||
|
await Promise.all(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
createSecret({ projectKey, token: serviceToken, ...secret, key: `BULK-${secret.key}-${i + 1}`, path })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const updateSharedSecRes = await testServer.inject({
|
||||||
|
method: "PATCH",
|
||||||
|
url: `/api/v3/secrets/batch`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: path,
|
||||||
|
secrets: Array.from(Array(5)).map((_e, i) => ({
|
||||||
|
secretName: `BULK-${secret.key}-${i + 1}`,
|
||||||
|
...encryptSecret(projectKey, `BULK-${secret.key}-${i + 1}`, "update-value", secret.comment)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(updateSharedSecRes.statusCode).toBe(200);
|
||||||
|
const updateSharedSecPayload = JSON.parse(updateSharedSecRes.payload);
|
||||||
|
expect(updateSharedSecPayload).toHaveProperty("secrets");
|
||||||
|
|
||||||
|
// bulk ones should exist
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.arrayContaining(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
expect.objectContaining({
|
||||||
|
key: `BULK-${secret.key}-${i + 1}`,
|
||||||
|
value: "update-value",
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
await Promise.all(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
deleteSecret({ path, key: `BULK-${secret.key}-${i + 1}`, token: serviceToken })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test.each(testSecrets)("Bulk delete secrets in path $path", async ({ secret, path }) => {
|
||||||
|
await Promise.all(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
createSecret({ projectKey, token: serviceToken, ...secret, key: `BULK-${secret.key}-${i + 1}`, path })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
const deletedSharedSecRes = await testServer.inject({
|
||||||
|
method: "DELETE",
|
||||||
|
url: `/api/v3/secrets/batch`,
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: path,
|
||||||
|
secrets: Array.from(Array(5)).map((_e, i) => ({
|
||||||
|
secretName: `BULK-${secret.key}-${i + 1}`
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(deletedSharedSecRes.statusCode).toBe(200);
|
||||||
|
const deletedSecretPayload = JSON.parse(deletedSharedSecRes.payload);
|
||||||
|
expect(deletedSecretPayload).toHaveProperty("secrets");
|
||||||
|
|
||||||
|
// bulk ones should exist
|
||||||
|
const secrets = await getSecrets(seedData1.environment.slug, path);
|
||||||
|
expect(secrets).toEqual(
|
||||||
|
expect.not.arrayContaining(
|
||||||
|
Array.from(Array(5)).map((_e, i) =>
|
||||||
|
expect.objectContaining({
|
||||||
|
key: `BULK-${secret.value}-${i + 1}`,
|
||||||
|
type: SecretType.Shared
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Service token fail cases", async () => {
|
||||||
|
test("Unauthorized secret path access", async () => {
|
||||||
|
const serviceToken = await createServiceToken(
|
||||||
|
[{ secretPath: "/", environment: seedData1.environment.slug }],
|
||||||
|
["read", "write"]
|
||||||
|
);
|
||||||
|
const fetchSecrets = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: "/api/v3/secrets",
|
||||||
|
query: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: "/nested/deep"
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(fetchSecrets.statusCode).toBe(401);
|
||||||
|
expect(fetchSecrets.json().error).toBe("PermissionDenied");
|
||||||
|
await deleteServiceToken();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Unauthorized secret environment access", async () => {
|
||||||
|
const serviceToken = await createServiceToken(
|
||||||
|
[{ secretPath: "/", environment: seedData1.environment.slug }],
|
||||||
|
["read", "write"]
|
||||||
|
);
|
||||||
|
const fetchSecrets = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: "/api/v3/secrets",
|
||||||
|
query: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: "prod",
|
||||||
|
secretPath: "/"
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(fetchSecrets.statusCode).toBe(401);
|
||||||
|
expect(fetchSecrets.json().error).toBe("PermissionDenied");
|
||||||
|
await deleteServiceToken();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Unauthorized write operation", async () => {
|
||||||
|
const serviceToken = await createServiceToken(
|
||||||
|
[{ secretPath: "/", environment: seedData1.environment.slug }],
|
||||||
|
["read"]
|
||||||
|
);
|
||||||
|
const writeSecrets = await testServer.inject({
|
||||||
|
method: "POST",
|
||||||
|
url: `/api/v3/secrets/NEW`,
|
||||||
|
body: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
type: SecretType.Shared,
|
||||||
|
secretPath: "/",
|
||||||
|
// doesn't matter project key because this will fail before that due to read only access
|
||||||
|
...encryptSecret(crypto.randomBytes(16).toString("hex"), "NEW", "value", "")
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(writeSecrets.statusCode).toBe(401);
|
||||||
|
expect(writeSecrets.json().error).toBe("PermissionDenied");
|
||||||
|
|
||||||
|
// but read access should still work fine
|
||||||
|
const fetchSecrets = await testServer.inject({
|
||||||
|
method: "GET",
|
||||||
|
url: "/api/v3/secrets",
|
||||||
|
query: {
|
||||||
|
workspaceId: seedData1.project.id,
|
||||||
|
environment: seedData1.environment.slug,
|
||||||
|
secretPath: "/"
|
||||||
|
},
|
||||||
|
headers: {
|
||||||
|
authorization: `Bearer ${serviceToken}`
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(fetchSecrets.statusCode).toBe(200);
|
||||||
|
await deleteServiceToken();
|
||||||
|
});
|
||||||
|
});
|
File diff suppressed because it is too large
Load Diff
@ -1,26 +1,31 @@
|
|||||||
// import { main } from "@app/server/app";
|
// eslint-disable-next-line
|
||||||
import { initEnvConfig } from "@app/lib/config/env";
|
import "ts-node/register";
|
||||||
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
|
import jwt from "jsonwebtoken";
|
||||||
import knex from "knex";
|
import knex from "knex";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { mockSmtpServer } from "./mocks/smtp";
|
|
||||||
import { initLogger } from "@app/lib/logger";
|
|
||||||
import jwt from "jsonwebtoken";
|
|
||||||
|
|
||||||
import "ts-node/register";
|
|
||||||
import { main } from "@app/server/app";
|
|
||||||
import { mockQueue } from "./mocks/queue";
|
|
||||||
import { AuthTokenType } from "@app/services/auth/auth-type";
|
|
||||||
import { seedData1 } from "@app/db/seed-data";
|
import { seedData1 } from "@app/db/seed-data";
|
||||||
|
import { initEnvConfig } from "@app/lib/config/env";
|
||||||
|
import { initLogger } from "@app/lib/logger";
|
||||||
|
import { main } from "@app/server/app";
|
||||||
|
import { AuthMethod, AuthTokenType } from "@app/services/auth/auth-type";
|
||||||
|
|
||||||
dotenv.config({ path: path.join(__dirname, "../.env.test") });
|
import { mockQueue } from "./mocks/queue";
|
||||||
|
import { mockSmtpServer } from "./mocks/smtp";
|
||||||
|
import { mockKeyStore } from "./mocks/keystore";
|
||||||
|
|
||||||
|
dotenv.config({ path: path.join(__dirname, "../../.env.test"), debug: true });
|
||||||
export default {
|
export default {
|
||||||
name: "knex-env",
|
name: "knex-env",
|
||||||
transformMode: "ssr",
|
transformMode: "ssr",
|
||||||
async setup() {
|
async setup() {
|
||||||
|
const logger = await initLogger();
|
||||||
|
const cfg = initEnvConfig(logger);
|
||||||
const db = knex({
|
const db = knex({
|
||||||
client: "pg",
|
client: "pg",
|
||||||
connection: process.env.DB_CONNECTION_URI,
|
connection: cfg.DB_CONNECTION_URI,
|
||||||
migrations: {
|
migrations: {
|
||||||
directory: path.join(__dirname, "../src/db/migrations"),
|
directory: path.join(__dirname, "../src/db/migrations"),
|
||||||
extension: "ts",
|
extension: "ts",
|
||||||
@ -37,9 +42,8 @@ export default {
|
|||||||
await db.seed.run();
|
await db.seed.run();
|
||||||
const smtp = mockSmtpServer();
|
const smtp = mockSmtpServer();
|
||||||
const queue = mockQueue();
|
const queue = mockQueue();
|
||||||
const logger = await initLogger();
|
const keyStore = mockKeyStore();
|
||||||
const cfg = initEnvConfig(logger);
|
const server = await main({ db, smtp, logger, queue, keyStore });
|
||||||
const server = await main({ db, smtp, logger, queue });
|
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
globalThis.testServer = server;
|
globalThis.testServer = server;
|
||||||
// @ts-expect-error type
|
// @ts-expect-error type
|
||||||
@ -48,12 +52,15 @@ export default {
|
|||||||
authTokenType: AuthTokenType.ACCESS_TOKEN,
|
authTokenType: AuthTokenType.ACCESS_TOKEN,
|
||||||
userId: seedData1.id,
|
userId: seedData1.id,
|
||||||
tokenVersionId: seedData1.token.id,
|
tokenVersionId: seedData1.token.id,
|
||||||
|
authMethod: AuthMethod.EMAIL,
|
||||||
|
organizationId: seedData1.organization.id,
|
||||||
accessVersion: 1
|
accessVersion: 1
|
||||||
},
|
},
|
||||||
cfg.AUTH_SECRET,
|
cfg.AUTH_SECRET,
|
||||||
{ expiresIn: cfg.JWT_AUTH_LIFETIME }
|
{ expiresIn: cfg.JWT_AUTH_LIFETIME }
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log("[TEST] Error setting up environment", error);
|
||||||
await db.destroy();
|
await db.destroy();
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
3390
backend/package-lock.json
generated
3390
backend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -24,8 +24,8 @@
|
|||||||
"migration:latest": "knex --knexfile ./src/db/knexfile.ts --client pg migrate:latest",
|
"migration:latest": "knex --knexfile ./src/db/knexfile.ts --client pg migrate:latest",
|
||||||
"migration:rollback": "knex --knexfile ./src/db/knexfile.ts migrate:rollback",
|
"migration:rollback": "knex --knexfile ./src/db/knexfile.ts migrate:rollback",
|
||||||
"seed:new": "tsx ./scripts/create-seed-file.ts",
|
"seed:new": "tsx ./scripts/create-seed-file.ts",
|
||||||
"seed:run": "knex --knexfile ./src/db/knexfile.ts --client pg seed:run",
|
"seed": "knex --knexfile ./src/db/knexfile.ts --client pg seed:run",
|
||||||
"db:reset": "npm run migration:rollback -- --all && npm run migration:latest && npm run seed:run"
|
"db:reset": "npm run migration:rollback -- --all && npm run migration:latest"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -67,21 +67,22 @@
|
|||||||
"tsx": "^4.4.0",
|
"tsx": "^4.4.0",
|
||||||
"typescript": "^5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"vite-tsconfig-paths": "^4.2.2",
|
"vite-tsconfig-paths": "^4.2.2",
|
||||||
"vitest": "^1.0.4"
|
"vitest": "^1.2.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-secrets-manager": "^3.485.0",
|
"@aws-sdk/client-iam": "^3.525.0",
|
||||||
|
"@aws-sdk/client-secrets-manager": "^3.504.0",
|
||||||
"@casl/ability": "^6.5.0",
|
"@casl/ability": "^6.5.0",
|
||||||
"@fastify/cookie": "^9.2.0",
|
"@fastify/cookie": "^9.3.1",
|
||||||
"@fastify/cors": "^8.4.1",
|
"@fastify/cors": "^8.5.0",
|
||||||
"@fastify/etag": "^5.1.0",
|
"@fastify/etag": "^5.1.0",
|
||||||
"@fastify/formbody": "^7.4.0",
|
"@fastify/formbody": "^7.4.0",
|
||||||
"@fastify/helmet": "^11.1.1",
|
"@fastify/helmet": "^11.1.1",
|
||||||
"@fastify/passport": "^2.4.0",
|
"@fastify/passport": "^2.4.0",
|
||||||
"@fastify/rate-limit": "^9.0.0",
|
"@fastify/rate-limit": "^9.0.0",
|
||||||
"@fastify/session": "^10.7.0",
|
"@fastify/session": "^10.7.0",
|
||||||
"@fastify/swagger": "^8.12.0",
|
"@fastify/swagger": "^8.14.0",
|
||||||
"@fastify/swagger-ui": "^1.10.1",
|
"@fastify/swagger-ui": "^2.1.0",
|
||||||
"@node-saml/passport-saml": "^4.0.4",
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
"@octokit/rest": "^20.0.2",
|
"@octokit/rest": "^20.0.2",
|
||||||
"@octokit/webhooks-types": "^7.3.1",
|
"@octokit/webhooks-types": "^7.3.1",
|
||||||
@ -90,13 +91,13 @@
|
|||||||
"@ucast/mongo2js": "^1.3.4",
|
"@ucast/mongo2js": "^1.3.4",
|
||||||
"ajv": "^8.12.0",
|
"ajv": "^8.12.0",
|
||||||
"argon2": "^0.31.2",
|
"argon2": "^0.31.2",
|
||||||
"aws-sdk": "^2.1532.0",
|
"aws-sdk": "^2.1553.0",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.7",
|
||||||
"axios-retry": "^4.0.0",
|
"axios-retry": "^4.0.0",
|
||||||
"bcrypt": "^5.1.1",
|
"bcrypt": "^5.1.1",
|
||||||
"bullmq": "^5.1.1",
|
"bullmq": "^5.3.3",
|
||||||
"dotenv": "^16.3.1",
|
"dotenv": "^16.4.1",
|
||||||
"fastify": "^4.24.3",
|
"fastify": "^4.26.0",
|
||||||
"fastify-plugin": "^4.5.1",
|
"fastify-plugin": "^4.5.1",
|
||||||
"handlebars": "^4.7.8",
|
"handlebars": "^4.7.8",
|
||||||
"ioredis": "^5.3.2",
|
"ioredis": "^5.3.2",
|
||||||
@ -106,23 +107,26 @@
|
|||||||
"knex": "^3.0.1",
|
"knex": "^3.0.1",
|
||||||
"libsodium-wrappers": "^0.7.13",
|
"libsodium-wrappers": "^0.7.13",
|
||||||
"lodash.isequal": "^4.5.0",
|
"lodash.isequal": "^4.5.0",
|
||||||
"mysql2": "^3.6.5",
|
"ms": "^2.1.3",
|
||||||
|
"mysql2": "^3.9.1",
|
||||||
"nanoid": "^5.0.4",
|
"nanoid": "^5.0.4",
|
||||||
"node-cache": "^5.1.2",
|
"nodemailer": "^6.9.9",
|
||||||
"nodemailer": "^6.9.7",
|
"ora": "^7.0.1",
|
||||||
"passport-github": "^1.1.0",
|
"passport-github": "^1.1.0",
|
||||||
"passport-gitlab2": "^5.0.0",
|
"passport-gitlab2": "^5.0.0",
|
||||||
"passport-google-oauth20": "^2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
|
"passport-ldapauth": "^3.0.1",
|
||||||
"pg": "^8.11.3",
|
"pg": "^8.11.3",
|
||||||
|
"pg-query-stream": "^4.5.3",
|
||||||
"picomatch": "^3.0.1",
|
"picomatch": "^3.0.1",
|
||||||
"pino": "^8.16.2",
|
"pino": "^8.16.2",
|
||||||
"posthog-node": "^3.6.0",
|
"posthog-node": "^3.6.2",
|
||||||
"probot": "^12.3.3",
|
"probot": "^13.0.0",
|
||||||
"smee-client": "^2.0.0",
|
"smee-client": "^2.0.0",
|
||||||
"tweetnacl": "^1.0.3",
|
"tweetnacl": "^1.0.3",
|
||||||
"tweetnacl-util": "^0.15.1",
|
"tweetnacl-util": "^0.15.1",
|
||||||
"uuid": "^9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"zod": "^3.22.4",
|
"zod": "^3.22.4",
|
||||||
"zod-to-json-schema": "^3.22.0"
|
"zod-to-json-schema": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,11 +7,10 @@ import promptSync from "prompt-sync";
|
|||||||
const prompt = promptSync({ sigint: true });
|
const prompt = promptSync({ sigint: true });
|
||||||
|
|
||||||
const migrationName = prompt("Enter name for seedfile: ");
|
const migrationName = prompt("Enter name for seedfile: ");
|
||||||
const fileCounter = readdirSync(path.join(__dirname, "../src/db/seed")).length || 1;
|
const fileCounter = readdirSync(path.join(__dirname, "../src/db/seeds")).length || 1;
|
||||||
execSync(
|
execSync(
|
||||||
`npx knex seed:make --knexfile ${path.join(
|
`npx knex seed:make --knexfile ${path.join(__dirname, "../src/db/knexfile.ts")} -x ts ${
|
||||||
__dirname,
|
fileCounter + 1
|
||||||
"../src/db/knexfile.ts"
|
}-${migrationName}`,
|
||||||
)} -x ts ${fileCounter}-${migrationName}`,
|
|
||||||
{ stdio: "inherit" }
|
{ stdio: "inherit" }
|
||||||
);
|
);
|
||||||
|
@ -44,7 +44,7 @@ const getZodDefaultValue = (type: unknown, value: string | number | boolean | Ob
|
|||||||
if (!value || value === "null") return;
|
if (!value || value === "null") return;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case "uuid":
|
case "uuid":
|
||||||
return;
|
return `.default("00000000-0000-0000-0000-000000000000")`;
|
||||||
case "character varying": {
|
case "character varying": {
|
||||||
if (value === "gen_random_uuid()") return;
|
if (value === "gen_random_uuid()") return;
|
||||||
if (typeof value === "string" && value.includes("::")) {
|
if (typeof value === "string" && value.includes("::")) {
|
||||||
@ -100,7 +100,8 @@ const main = async () => {
|
|||||||
const columnName = columnNames[colNum];
|
const columnName = columnNames[colNum];
|
||||||
const colInfo = columns[columnName];
|
const colInfo = columns[columnName];
|
||||||
let ztype = getZodPrimitiveType(colInfo.type);
|
let ztype = getZodPrimitiveType(colInfo.type);
|
||||||
if (colInfo.defaultValue) {
|
// don't put optional on id
|
||||||
|
if (colInfo.defaultValue && columnName !== "id") {
|
||||||
const { defaultValue } = colInfo;
|
const { defaultValue } = colInfo;
|
||||||
const zSchema = getZodDefaultValue(colInfo.type, defaultValue);
|
const zSchema = getZodDefaultValue(colInfo.type, defaultValue);
|
||||||
if (zSchema) {
|
if (zSchema) {
|
||||||
@ -120,6 +121,7 @@ const main = async () => {
|
|||||||
.split("_")
|
.split("_")
|
||||||
.reduce((prev, curr) => prev + `${curr.at(0)?.toUpperCase()}${curr.slice(1).toLowerCase()}`, "");
|
.reduce((prev, curr) => prev + `${curr.at(0)?.toUpperCase()}${curr.slice(1).toLowerCase()}`, "");
|
||||||
|
|
||||||
|
// the insert and update are changed to zod input type to use default cases
|
||||||
writeFileSync(
|
writeFileSync(
|
||||||
path.join(__dirname, "../src/db/schemas", `${dashcase}.ts`),
|
path.join(__dirname, "../src/db/schemas", `${dashcase}.ts`),
|
||||||
`// Code generated by automation script, DO NOT EDIT.
|
`// Code generated by automation script, DO NOT EDIT.
|
||||||
@ -134,8 +136,8 @@ import { TImmutableDBKeys } from "./models";
|
|||||||
export const ${pascalCase}Schema = z.object({${schema}});
|
export const ${pascalCase}Schema = z.object({${schema}});
|
||||||
|
|
||||||
export type T${pascalCase} = z.infer<typeof ${pascalCase}Schema>;
|
export type T${pascalCase} = z.infer<typeof ${pascalCase}Schema>;
|
||||||
export type T${pascalCase}Insert = Omit<T${pascalCase}, TImmutableDBKeys>;
|
export type T${pascalCase}Insert = Omit<z.input<typeof ${pascalCase}Schema>, TImmutableDBKeys>;
|
||||||
export type T${pascalCase}Update = Partial<Omit<T${pascalCase}, TImmutableDBKeys>>;
|
export type T${pascalCase}Update = Partial<Omit<z.input<typeof ${pascalCase}Schema>, TImmutableDBKeys>>;
|
||||||
`
|
`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
8
backend/src/@types/fastify.d.ts
vendored
8
backend/src/@types/fastify.d.ts
vendored
@ -3,9 +3,11 @@ import "fastify";
|
|||||||
import { TUsers } from "@app/db/schemas";
|
import { TUsers } from "@app/db/schemas";
|
||||||
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
import { TAuditLogServiceFactory } from "@app/ee/services/audit-log/audit-log-service";
|
||||||
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
import { TCreateAuditLogDTO } from "@app/ee/services/audit-log/audit-log-types";
|
||||||
|
import { TLdapConfigServiceFactory } from "@app/ee/services/ldap-config/ldap-config-service";
|
||||||
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
import { TLicenseServiceFactory } from "@app/ee/services/license/license-service";
|
||||||
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
import { TPermissionServiceFactory } from "@app/ee/services/permission/permission-service";
|
||||||
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
import { TSamlConfigServiceFactory } from "@app/ee/services/saml-config/saml-config-service";
|
||||||
|
import { TScimServiceFactory } from "@app/ee/services/scim/scim-service";
|
||||||
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
import { TSecretApprovalPolicyServiceFactory } from "@app/ee/services/secret-approval-policy/secret-approval-policy-service";
|
||||||
import { TSecretApprovalRequestServiceFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-service";
|
import { TSecretApprovalRequestServiceFactory } from "@app/ee/services/secret-approval-request/secret-approval-request-service";
|
||||||
import { TSecretRotationServiceFactory } from "@app/ee/services/secret-rotation/secret-rotation-service";
|
import { TSecretRotationServiceFactory } from "@app/ee/services/secret-rotation/secret-rotation-service";
|
||||||
@ -17,7 +19,7 @@ import { TApiKeyServiceFactory } from "@app/services/api-key/api-key-service";
|
|||||||
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
|
import { TAuthLoginFactory } from "@app/services/auth/auth-login-service";
|
||||||
import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
|
import { TAuthPasswordFactory } from "@app/services/auth/auth-password-service";
|
||||||
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
|
import { TAuthSignupFactory } from "@app/services/auth/auth-signup-service";
|
||||||
import { ActorType } from "@app/services/auth/auth-type";
|
import { ActorAuthMethod, ActorType } from "@app/services/auth/auth-type";
|
||||||
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
import { TAuthTokenServiceFactory } from "@app/services/auth-token/auth-token-service";
|
||||||
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
|
import { TIdentityServiceFactory } from "@app/services/identity/identity-service";
|
||||||
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
import { TIdentityAccessTokenServiceFactory } from "@app/services/identity-access-token/identity-access-token-service";
|
||||||
@ -57,6 +59,7 @@ declare module "fastify" {
|
|||||||
// identity injection. depending on which kinda of token the information is filled in auth
|
// identity injection. depending on which kinda of token the information is filled in auth
|
||||||
auth: TAuthMode;
|
auth: TAuthMode;
|
||||||
permission: {
|
permission: {
|
||||||
|
authMethod: ActorAuthMethod;
|
||||||
type: ActorType;
|
type: ActorType;
|
||||||
id: string;
|
id: string;
|
||||||
orgId?: string;
|
orgId?: string;
|
||||||
@ -68,6 +71,7 @@ declare module "fastify" {
|
|||||||
};
|
};
|
||||||
auditLogInfo: Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
|
auditLogInfo: Pick<TCreateAuditLogDTO, "userAgent" | "userAgentType" | "ipAddress" | "actor">;
|
||||||
ssoConfig: Awaited<ReturnType<TSamlConfigServiceFactory["getSaml"]>>;
|
ssoConfig: Awaited<ReturnType<TSamlConfigServiceFactory["getSaml"]>>;
|
||||||
|
ldapConfig: Awaited<ReturnType<TLdapConfigServiceFactory["getLdapCfg"]>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface FastifyInstance {
|
interface FastifyInstance {
|
||||||
@ -105,6 +109,8 @@ declare module "fastify" {
|
|||||||
secretRotation: TSecretRotationServiceFactory;
|
secretRotation: TSecretRotationServiceFactory;
|
||||||
snapshot: TSecretSnapshotServiceFactory;
|
snapshot: TSecretSnapshotServiceFactory;
|
||||||
saml: TSamlConfigServiceFactory;
|
saml: TSamlConfigServiceFactory;
|
||||||
|
scim: TScimServiceFactory;
|
||||||
|
ldap: TLdapConfigServiceFactory;
|
||||||
auditLog: TAuditLogServiceFactory;
|
auditLog: TAuditLogServiceFactory;
|
||||||
secretScanning: TSecretScanningServiceFactory;
|
secretScanning: TSecretScanningServiceFactory;
|
||||||
license: TLicenseServiceFactory;
|
license: TLicenseServiceFactory;
|
||||||
|
28
backend/src/@types/knex.d.ts
vendored
28
backend/src/@types/knex.d.ts
vendored
@ -32,6 +32,9 @@ import {
|
|||||||
TIdentityOrgMemberships,
|
TIdentityOrgMemberships,
|
||||||
TIdentityOrgMembershipsInsert,
|
TIdentityOrgMembershipsInsert,
|
||||||
TIdentityOrgMembershipsUpdate,
|
TIdentityOrgMembershipsUpdate,
|
||||||
|
TIdentityProjectMembershipRole,
|
||||||
|
TIdentityProjectMembershipRoleInsert,
|
||||||
|
TIdentityProjectMembershipRoleUpdate,
|
||||||
TIdentityProjectMemberships,
|
TIdentityProjectMemberships,
|
||||||
TIdentityProjectMembershipsInsert,
|
TIdentityProjectMembershipsInsert,
|
||||||
TIdentityProjectMembershipsUpdate,
|
TIdentityProjectMembershipsUpdate,
|
||||||
@ -50,6 +53,9 @@ import {
|
|||||||
TIntegrations,
|
TIntegrations,
|
||||||
TIntegrationsInsert,
|
TIntegrationsInsert,
|
||||||
TIntegrationsUpdate,
|
TIntegrationsUpdate,
|
||||||
|
TLdapConfigs,
|
||||||
|
TLdapConfigsInsert,
|
||||||
|
TLdapConfigsUpdate,
|
||||||
TOrganizations,
|
TOrganizations,
|
||||||
TOrganizationsInsert,
|
TOrganizationsInsert,
|
||||||
TOrganizationsUpdate,
|
TOrganizationsUpdate,
|
||||||
@ -80,9 +86,15 @@ import {
|
|||||||
TProjects,
|
TProjects,
|
||||||
TProjectsInsert,
|
TProjectsInsert,
|
||||||
TProjectsUpdate,
|
TProjectsUpdate,
|
||||||
|
TProjectUserMembershipRoles,
|
||||||
|
TProjectUserMembershipRolesInsert,
|
||||||
|
TProjectUserMembershipRolesUpdate,
|
||||||
TSamlConfigs,
|
TSamlConfigs,
|
||||||
TSamlConfigsInsert,
|
TSamlConfigsInsert,
|
||||||
TSamlConfigsUpdate,
|
TSamlConfigsUpdate,
|
||||||
|
TScimTokens,
|
||||||
|
TScimTokensInsert,
|
||||||
|
TScimTokensUpdate,
|
||||||
TSecretApprovalPolicies,
|
TSecretApprovalPolicies,
|
||||||
TSecretApprovalPoliciesApprovers,
|
TSecretApprovalPoliciesApprovers,
|
||||||
TSecretApprovalPoliciesApproversInsert,
|
TSecretApprovalPoliciesApproversInsert,
|
||||||
@ -158,6 +170,9 @@ import {
|
|||||||
TUserActions,
|
TUserActions,
|
||||||
TUserActionsInsert,
|
TUserActionsInsert,
|
||||||
TUserActionsUpdate,
|
TUserActionsUpdate,
|
||||||
|
TUserAliases,
|
||||||
|
TUserAliasesInsert,
|
||||||
|
TUserAliasesUpdate,
|
||||||
TUserEncryptionKeys,
|
TUserEncryptionKeys,
|
||||||
TUserEncryptionKeysInsert,
|
TUserEncryptionKeysInsert,
|
||||||
TUserEncryptionKeysUpdate,
|
TUserEncryptionKeysUpdate,
|
||||||
@ -172,6 +187,7 @@ import {
|
|||||||
declare module "knex/types/tables" {
|
declare module "knex/types/tables" {
|
||||||
interface Tables {
|
interface Tables {
|
||||||
[TableName.Users]: Knex.CompositeTableType<TUsers, TUsersInsert, TUsersUpdate>;
|
[TableName.Users]: Knex.CompositeTableType<TUsers, TUsersInsert, TUsersUpdate>;
|
||||||
|
[TableName.UserAliases]: Knex.CompositeTableType<TUserAliases, TUserAliasesInsert, TUserAliasesUpdate>;
|
||||||
[TableName.UserEncryptionKey]: Knex.CompositeTableType<
|
[TableName.UserEncryptionKey]: Knex.CompositeTableType<
|
||||||
TUserEncryptionKeys,
|
TUserEncryptionKeys,
|
||||||
TUserEncryptionKeysInsert,
|
TUserEncryptionKeysInsert,
|
||||||
@ -211,6 +227,11 @@ declare module "knex/types/tables" {
|
|||||||
TProjectEnvironmentsUpdate
|
TProjectEnvironmentsUpdate
|
||||||
>;
|
>;
|
||||||
[TableName.ProjectBot]: Knex.CompositeTableType<TProjectBots, TProjectBotsInsert, TProjectBotsUpdate>;
|
[TableName.ProjectBot]: Knex.CompositeTableType<TProjectBots, TProjectBotsInsert, TProjectBotsUpdate>;
|
||||||
|
[TableName.ProjectUserMembershipRole]: Knex.CompositeTableType<
|
||||||
|
TProjectUserMembershipRoles,
|
||||||
|
TProjectUserMembershipRolesInsert,
|
||||||
|
TProjectUserMembershipRolesUpdate
|
||||||
|
>;
|
||||||
[TableName.ProjectRoles]: Knex.CompositeTableType<TProjectRoles, TProjectRolesInsert, TProjectRolesUpdate>;
|
[TableName.ProjectRoles]: Knex.CompositeTableType<TProjectRoles, TProjectRolesInsert, TProjectRolesUpdate>;
|
||||||
[TableName.ProjectKeys]: Knex.CompositeTableType<TProjectKeys, TProjectKeysInsert, TProjectKeysUpdate>;
|
[TableName.ProjectKeys]: Knex.CompositeTableType<TProjectKeys, TProjectKeysInsert, TProjectKeysUpdate>;
|
||||||
[TableName.Secret]: Knex.CompositeTableType<TSecrets, TSecretsInsert, TSecretsUpdate>;
|
[TableName.Secret]: Knex.CompositeTableType<TSecrets, TSecretsInsert, TSecretsUpdate>;
|
||||||
@ -262,6 +283,12 @@ declare module "knex/types/tables" {
|
|||||||
TIdentityProjectMembershipsInsert,
|
TIdentityProjectMembershipsInsert,
|
||||||
TIdentityProjectMembershipsUpdate
|
TIdentityProjectMembershipsUpdate
|
||||||
>;
|
>;
|
||||||
|
[TableName.IdentityProjectMembershipRole]: Knex.CompositeTableType<
|
||||||
|
TIdentityProjectMembershipRole,
|
||||||
|
TIdentityProjectMembershipRoleInsert,
|
||||||
|
TIdentityProjectMembershipRoleUpdate
|
||||||
|
>;
|
||||||
|
[TableName.ScimToken]: Knex.CompositeTableType<TScimTokens, TScimTokensInsert, TScimTokensUpdate>;
|
||||||
[TableName.SecretApprovalPolicy]: Knex.CompositeTableType<
|
[TableName.SecretApprovalPolicy]: Knex.CompositeTableType<
|
||||||
TSecretApprovalPolicies,
|
TSecretApprovalPolicies,
|
||||||
TSecretApprovalPoliciesInsert,
|
TSecretApprovalPoliciesInsert,
|
||||||
@ -314,6 +341,7 @@ declare module "knex/types/tables" {
|
|||||||
TSecretSnapshotFoldersUpdate
|
TSecretSnapshotFoldersUpdate
|
||||||
>;
|
>;
|
||||||
[TableName.SamlConfig]: Knex.CompositeTableType<TSamlConfigs, TSamlConfigsInsert, TSamlConfigsUpdate>;
|
[TableName.SamlConfig]: Knex.CompositeTableType<TSamlConfigs, TSamlConfigsInsert, TSamlConfigsUpdate>;
|
||||||
|
[TableName.LdapConfig]: Knex.CompositeTableType<TLdapConfigs, TLdapConfigsInsert, TLdapConfigsUpdate>;
|
||||||
[TableName.OrgBot]: Knex.CompositeTableType<TOrgBots, TOrgBotsInsert, TOrgBotsUpdate>;
|
[TableName.OrgBot]: Knex.CompositeTableType<TOrgBots, TOrgBotsInsert, TOrgBotsUpdate>;
|
||||||
[TableName.AuditLog]: Knex.CompositeTableType<TAuditLogs, TAuditLogsInsert, TAuditLogsUpdate>;
|
[TableName.AuditLog]: Knex.CompositeTableType<TAuditLogs, TAuditLogsInsert, TAuditLogsUpdate>;
|
||||||
[TableName.GitAppInstallSession]: Knex.CompositeTableType<
|
[TableName.GitAppInstallSession]: Knex.CompositeTableType<
|
||||||
|
6
backend/src/cache/redis.ts
vendored
6
backend/src/cache/redis.ts
vendored
@ -1,6 +0,0 @@
|
|||||||
import Redis from "ioredis";
|
|
||||||
|
|
||||||
export const initRedisConnection = (redisUrl: string) => {
|
|
||||||
const redis = new Redis(redisUrl);
|
|
||||||
return redis;
|
|
||||||
};
|
|
@ -6,6 +6,13 @@ export const initDbConnection = ({ dbConnectionUri, dbRootCert }: { dbConnection
|
|||||||
client: "pg",
|
client: "pg",
|
||||||
connection: {
|
connection: {
|
||||||
connectionString: dbConnectionUri,
|
connectionString: dbConnectionUri,
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
// @ts-expect-error I have no clue why only for the port there is a type error
|
||||||
|
// eslint-disable-next-line
|
||||||
|
port: process.env.DB_PORT,
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
password: process.env.DB_PASSWORD,
|
||||||
ssl: dbRootCert
|
ssl: dbRootCert
|
||||||
? {
|
? {
|
||||||
rejectUnauthorized: true,
|
rejectUnauthorized: true,
|
||||||
|
@ -7,13 +7,29 @@ import path from "path";
|
|||||||
|
|
||||||
// Update with your config settings. .
|
// Update with your config settings. .
|
||||||
dotenv.config({
|
dotenv.config({
|
||||||
path: path.join(__dirname, "../../../.env.migration"),
|
path: path.join(__dirname, "../../../.env.migration")
|
||||||
debug: true
|
|
||||||
});
|
});
|
||||||
|
dotenv.config({
|
||||||
|
path: path.join(__dirname, "../../../.env")
|
||||||
|
});
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
development: {
|
development: {
|
||||||
client: "postgres",
|
client: "postgres",
|
||||||
connection: process.env.DB_CONNECTION_URI,
|
connection: {
|
||||||
|
connectionString: process.env.DB_CONNECTION_URI,
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
port: process.env.DB_PORT,
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
password: process.env.DB_PASSWORD,
|
||||||
|
ssl: process.env.DB_ROOT_CERT
|
||||||
|
? {
|
||||||
|
rejectUnauthorized: true,
|
||||||
|
ca: Buffer.from(process.env.DB_ROOT_CERT, "base64").toString("ascii")
|
||||||
|
}
|
||||||
|
: false
|
||||||
|
},
|
||||||
pool: {
|
pool: {
|
||||||
min: 2,
|
min: 2,
|
||||||
max: 10
|
max: 10
|
||||||
@ -27,7 +43,20 @@ export default {
|
|||||||
},
|
},
|
||||||
production: {
|
production: {
|
||||||
client: "postgres",
|
client: "postgres",
|
||||||
connection: process.env.DB_CONNECTION_URI,
|
connection: {
|
||||||
|
connectionString: process.env.DB_CONNECTION_URI,
|
||||||
|
host: process.env.DB_HOST,
|
||||||
|
port: process.env.DB_PORT,
|
||||||
|
user: process.env.DB_USER,
|
||||||
|
database: process.env.DB_NAME,
|
||||||
|
password: process.env.DB_PASSWORD,
|
||||||
|
ssl: process.env.DB_ROOT_CERT
|
||||||
|
? {
|
||||||
|
rejectUnauthorized: true,
|
||||||
|
ca: Buffer.from(process.env.DB_ROOT_CERT, "base64").toString("ascii")
|
||||||
|
}
|
||||||
|
: false
|
||||||
|
},
|
||||||
pool: {
|
pool: {
|
||||||
min: 2,
|
min: 2,
|
||||||
max: 10
|
max: 10
|
||||||
|
31
backend/src/db/migrations/20240208234120_scim-token.ts
Normal file
31
backend/src/db/migrations/20240208234120_scim-token.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.ScimToken))) {
|
||||||
|
await knex.schema.createTable(TableName.ScimToken, (t) => {
|
||||||
|
t.string("id", 36).primary().defaultTo(knex.fn.uuid());
|
||||||
|
t.bigInteger("ttlDays").defaultTo(365).notNullable();
|
||||||
|
t.string("description").notNullable();
|
||||||
|
t.uuid("orgId").notNullable();
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (t) => {
|
||||||
|
t.boolean("scimEnabled").defaultTo(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.ScimToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.ScimToken);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.ScimToken);
|
||||||
|
await knex.schema.alterTable(TableName.Organization, (t) => {
|
||||||
|
t.dropColumn("scimEnabled");
|
||||||
|
});
|
||||||
|
}
|
39
backend/src/db/migrations/20240216154123_ghost_users.ts
Normal file
39
backend/src/db/migrations/20240216154123_ghost_users.ts
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { ProjectVersion, TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "isGhost");
|
||||||
|
const hasProjectVersionColumn = await knex.schema.hasColumn(TableName.Project, "version");
|
||||||
|
|
||||||
|
if (!hasGhostUserColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
t.boolean("isGhost").defaultTo(false).notNullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!hasProjectVersionColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.integer("version").defaultTo(ProjectVersion.V1).notNullable();
|
||||||
|
t.string("upgradeStatus").nullable();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
const hasGhostUserColumn = await knex.schema.hasColumn(TableName.Users, "isGhost");
|
||||||
|
const hasProjectVersionColumn = await knex.schema.hasColumn(TableName.Project, "version");
|
||||||
|
|
||||||
|
if (hasGhostUserColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
t.dropColumn("isGhost");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasProjectVersionColumn) {
|
||||||
|
await knex.schema.alterTable(TableName.Project, (t) => {
|
||||||
|
t.dropColumn("version");
|
||||||
|
t.dropColumn("upgradeStatus");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const isTablePresent = await knex.schema.hasTable(TableName.SuperAdmin);
|
||||||
|
if (isTablePresent) {
|
||||||
|
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||||
|
t.string("allowedSignUpDomain");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
if (await knex.schema.hasColumn(TableName.SuperAdmin, "allowedSignUpDomain")) {
|
||||||
|
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||||
|
t.dropColumn("allowedSignUpDomain");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
25
backend/src/db/migrations/20240226094411_instance-id.ts
Normal file
25
backend/src/db/migrations/20240226094411_instance-id.ts
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-nocheck
|
||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
const ADMIN_CONFIG_UUID = "00000000-0000-0000-0000-000000000000";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||||
|
t.uuid("instanceId").notNullable().defaultTo(knex.fn.uuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
const superUserConfigExists = await knex(TableName.SuperAdmin).where("id", ADMIN_CONFIG_UUID).first();
|
||||||
|
if (!superUserConfigExists) {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
await knex(TableName.SuperAdmin).update({ id: ADMIN_CONFIG_UUID }).whereNotNull("id").limit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.SuperAdmin, (t) => {
|
||||||
|
t.dropColumn("instanceId");
|
||||||
|
});
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.Integration, (t) => {
|
||||||
|
t.datetime("lastUsed");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.alterTable(TableName.Integration, (t) => {
|
||||||
|
t.dropColumn("lastUsed");
|
||||||
|
});
|
||||||
|
}
|
68
backend/src/db/migrations/20240311210135_ldap-config.ts
Normal file
68
backend/src/db/migrations/20240311210135_ldap-config.ts
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
if (!(await knex.schema.hasTable(TableName.LdapConfig))) {
|
||||||
|
await knex.schema.createTable(TableName.LdapConfig, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.uuid("orgId").notNullable().unique();
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.boolean("isActive").notNullable();
|
||||||
|
t.string("url").notNullable();
|
||||||
|
t.string("encryptedBindDN").notNullable();
|
||||||
|
t.string("bindDNIV").notNullable();
|
||||||
|
t.string("bindDNTag").notNullable();
|
||||||
|
t.string("encryptedBindPass").notNullable();
|
||||||
|
t.string("bindPassIV").notNullable();
|
||||||
|
t.string("bindPassTag").notNullable();
|
||||||
|
t.string("searchBase").notNullable();
|
||||||
|
t.text("encryptedCACert").notNullable();
|
||||||
|
t.string("caCertIV").notNullable();
|
||||||
|
t.string("caCertTag").notNullable();
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.LdapConfig);
|
||||||
|
|
||||||
|
if (!(await knex.schema.hasTable(TableName.UserAliases))) {
|
||||||
|
await knex.schema.createTable(TableName.UserAliases, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.uuid("userId").notNullable();
|
||||||
|
t.foreign("userId").references("id").inTable(TableName.Users).onDelete("CASCADE");
|
||||||
|
t.string("username").notNullable();
|
||||||
|
t.string("aliasType").notNullable();
|
||||||
|
t.string("externalId").notNullable();
|
||||||
|
t.specificType("emails", "text[]");
|
||||||
|
t.uuid("orgId").nullable();
|
||||||
|
t.foreign("orgId").references("id").inTable(TableName.Organization).onDelete("CASCADE");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.UserAliases);
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
t.string("username").unique();
|
||||||
|
t.string("email").nullable().alter();
|
||||||
|
t.dropUnique(["email"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
await knex(TableName.Users).update("username", knex.ref("email"));
|
||||||
|
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
t.string("username").notNullable().alter();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.LdapConfig);
|
||||||
|
await knex.schema.dropTableIfExists(TableName.UserAliases);
|
||||||
|
await knex.schema.alterTable(TableName.Users, (t) => {
|
||||||
|
t.dropColumn("username");
|
||||||
|
// t.string("email").notNullable().alter();
|
||||||
|
});
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.LdapConfig);
|
||||||
|
}
|
50
backend/src/db/migrations/20240312162549_temp-roles.ts
Normal file
50
backend/src/db/migrations/20240312162549_temp-roles.ts
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const doesTableExist = await knex.schema.hasTable(TableName.ProjectUserMembershipRole);
|
||||||
|
if (!doesTableExist) {
|
||||||
|
await knex.schema.createTable(TableName.ProjectUserMembershipRole, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("role").notNullable();
|
||||||
|
t.uuid("projectMembershipId").notNullable();
|
||||||
|
t.foreign("projectMembershipId").references("id").inTable(TableName.ProjectMembership).onDelete("CASCADE");
|
||||||
|
// until role is changed/removed the role should not deleted
|
||||||
|
t.uuid("customRoleId");
|
||||||
|
t.foreign("customRoleId").references("id").inTable(TableName.ProjectRoles);
|
||||||
|
t.boolean("isTemporary").notNullable().defaultTo(false);
|
||||||
|
t.string("temporaryMode");
|
||||||
|
t.string("temporaryRange"); // could be cron or relative time like 1H or 1minute etc
|
||||||
|
t.datetime("temporaryAccessStartTime");
|
||||||
|
t.datetime("temporaryAccessEndTime");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.ProjectUserMembershipRole);
|
||||||
|
|
||||||
|
const projectMemberships = await knex(TableName.ProjectMembership).select(
|
||||||
|
"id",
|
||||||
|
"role",
|
||||||
|
"createdAt",
|
||||||
|
"updatedAt",
|
||||||
|
knex.ref("roleId").withSchema(TableName.ProjectMembership).as("customRoleId")
|
||||||
|
);
|
||||||
|
if (projectMemberships.length)
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.ProjectUserMembershipRole,
|
||||||
|
projectMemberships.map((data) => ({ ...data, projectMembershipId: data.id }))
|
||||||
|
);
|
||||||
|
// will be dropped later
|
||||||
|
// await knex.schema.alterTable(TableName.ProjectMembership, (t) => {
|
||||||
|
// t.dropColumn("roleId");
|
||||||
|
// t.dropColumn("role");
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.ProjectUserMembershipRole);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.ProjectUserMembershipRole);
|
||||||
|
}
|
@ -0,0 +1,52 @@
|
|||||||
|
import { Knex } from "knex";
|
||||||
|
|
||||||
|
import { TableName } from "../schemas";
|
||||||
|
import { createOnUpdateTrigger, dropOnUpdateTrigger } from "../utils";
|
||||||
|
|
||||||
|
export async function up(knex: Knex): Promise<void> {
|
||||||
|
const doesTableExist = await knex.schema.hasTable(TableName.IdentityProjectMembershipRole);
|
||||||
|
if (!doesTableExist) {
|
||||||
|
await knex.schema.createTable(TableName.IdentityProjectMembershipRole, (t) => {
|
||||||
|
t.uuid("id", { primaryKey: true }).defaultTo(knex.fn.uuid());
|
||||||
|
t.string("role").notNullable();
|
||||||
|
t.uuid("projectMembershipId").notNullable();
|
||||||
|
t.foreign("projectMembershipId")
|
||||||
|
.references("id")
|
||||||
|
.inTable(TableName.IdentityProjectMembership)
|
||||||
|
.onDelete("CASCADE");
|
||||||
|
// until role is changed/removed the role should not deleted
|
||||||
|
t.uuid("customRoleId");
|
||||||
|
t.foreign("customRoleId").references("id").inTable(TableName.ProjectRoles);
|
||||||
|
t.boolean("isTemporary").notNullable().defaultTo(false);
|
||||||
|
t.string("temporaryMode");
|
||||||
|
t.string("temporaryRange"); // could be cron or relative time like 1H or 1minute etc
|
||||||
|
t.datetime("temporaryAccessStartTime");
|
||||||
|
t.datetime("temporaryAccessEndTime");
|
||||||
|
t.timestamps(true, true, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
await createOnUpdateTrigger(knex, TableName.IdentityProjectMembershipRole);
|
||||||
|
|
||||||
|
const identityMemberships = await knex(TableName.IdentityProjectMembership).select(
|
||||||
|
"id",
|
||||||
|
"role",
|
||||||
|
"createdAt",
|
||||||
|
"updatedAt",
|
||||||
|
knex.ref("roleId").withSchema(TableName.IdentityProjectMembership).as("customRoleId")
|
||||||
|
);
|
||||||
|
if (identityMemberships.length)
|
||||||
|
await knex.batchInsert(
|
||||||
|
TableName.IdentityProjectMembershipRole,
|
||||||
|
identityMemberships.map((data) => ({ ...data, projectMembershipId: data.id }))
|
||||||
|
);
|
||||||
|
// await knex.schema.alterTable(TableName.IdentityProjectMembership, (t) => {
|
||||||
|
// t.dropColumn("roleId");
|
||||||
|
// t.dropColumn("role");
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function down(knex: Knex): Promise<void> {
|
||||||
|
await knex.schema.dropTableIfExists(TableName.IdentityProjectMembershipRole);
|
||||||
|
await dropOnUpdateTrigger(knex, TableName.IdentityProjectMembershipRole);
|
||||||
|
}
|
@ -19,5 +19,5 @@ export const ApiKeysSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TApiKeys = z.infer<typeof ApiKeysSchema>;
|
export type TApiKeys = z.infer<typeof ApiKeysSchema>;
|
||||||
export type TApiKeysInsert = Omit<TApiKeys, TImmutableDBKeys>;
|
export type TApiKeysInsert = Omit<z.input<typeof ApiKeysSchema>, TImmutableDBKeys>;
|
||||||
export type TApiKeysUpdate = Partial<Omit<TApiKeys, TImmutableDBKeys>>;
|
export type TApiKeysUpdate = Partial<Omit<z.input<typeof ApiKeysSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -24,5 +24,5 @@ export const AuditLogsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
|
export type TAuditLogs = z.infer<typeof AuditLogsSchema>;
|
||||||
export type TAuditLogsInsert = Omit<TAuditLogs, TImmutableDBKeys>;
|
export type TAuditLogsInsert = Omit<z.input<typeof AuditLogsSchema>, TImmutableDBKeys>;
|
||||||
export type TAuditLogsUpdate = Partial<Omit<TAuditLogs, TImmutableDBKeys>>;
|
export type TAuditLogsUpdate = Partial<Omit<z.input<typeof AuditLogsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -20,5 +20,5 @@ export const AuthTokenSessionsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
|
export type TAuthTokenSessions = z.infer<typeof AuthTokenSessionsSchema>;
|
||||||
export type TAuthTokenSessionsInsert = Omit<TAuthTokenSessions, TImmutableDBKeys>;
|
export type TAuthTokenSessionsInsert = Omit<z.input<typeof AuthTokenSessionsSchema>, TImmutableDBKeys>;
|
||||||
export type TAuthTokenSessionsUpdate = Partial<Omit<TAuthTokenSessions, TImmutableDBKeys>>;
|
export type TAuthTokenSessionsUpdate = Partial<Omit<z.input<typeof AuthTokenSessionsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -21,5 +21,5 @@ export const AuthTokensSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TAuthTokens = z.infer<typeof AuthTokensSchema>;
|
export type TAuthTokens = z.infer<typeof AuthTokensSchema>;
|
||||||
export type TAuthTokensInsert = Omit<TAuthTokens, TImmutableDBKeys>;
|
export type TAuthTokensInsert = Omit<z.input<typeof AuthTokensSchema>, TImmutableDBKeys>;
|
||||||
export type TAuthTokensUpdate = Partial<Omit<TAuthTokens, TImmutableDBKeys>>;
|
export type TAuthTokensUpdate = Partial<Omit<z.input<typeof AuthTokensSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -22,5 +22,5 @@ export const BackupPrivateKeySchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>;
|
export type TBackupPrivateKey = z.infer<typeof BackupPrivateKeySchema>;
|
||||||
export type TBackupPrivateKeyInsert = Omit<TBackupPrivateKey, TImmutableDBKeys>;
|
export type TBackupPrivateKeyInsert = Omit<z.input<typeof BackupPrivateKeySchema>, TImmutableDBKeys>;
|
||||||
export type TBackupPrivateKeyUpdate = Partial<Omit<TBackupPrivateKey, TImmutableDBKeys>>;
|
export type TBackupPrivateKeyUpdate = Partial<Omit<z.input<typeof BackupPrivateKeySchema>, TImmutableDBKeys>>;
|
||||||
|
@ -17,5 +17,5 @@ export const GitAppInstallSessionsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>;
|
export type TGitAppInstallSessions = z.infer<typeof GitAppInstallSessionsSchema>;
|
||||||
export type TGitAppInstallSessionsInsert = Omit<TGitAppInstallSessions, TImmutableDBKeys>;
|
export type TGitAppInstallSessionsInsert = Omit<z.input<typeof GitAppInstallSessionsSchema>, TImmutableDBKeys>;
|
||||||
export type TGitAppInstallSessionsUpdate = Partial<Omit<TGitAppInstallSessions, TImmutableDBKeys>>;
|
export type TGitAppInstallSessionsUpdate = Partial<Omit<z.input<typeof GitAppInstallSessionsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -17,5 +17,5 @@ export const GitAppOrgSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>;
|
export type TGitAppOrg = z.infer<typeof GitAppOrgSchema>;
|
||||||
export type TGitAppOrgInsert = Omit<TGitAppOrg, TImmutableDBKeys>;
|
export type TGitAppOrgInsert = Omit<z.input<typeof GitAppOrgSchema>, TImmutableDBKeys>;
|
||||||
export type TGitAppOrgUpdate = Partial<Omit<TGitAppOrg, TImmutableDBKeys>>;
|
export type TGitAppOrgUpdate = Partial<Omit<z.input<typeof GitAppOrgSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -16,5 +16,5 @@ export const IdentitiesSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentities = z.infer<typeof IdentitiesSchema>;
|
export type TIdentities = z.infer<typeof IdentitiesSchema>;
|
||||||
export type TIdentitiesInsert = Omit<TIdentities, TImmutableDBKeys>;
|
export type TIdentitiesInsert = Omit<z.input<typeof IdentitiesSchema>, TImmutableDBKeys>;
|
||||||
export type TIdentitiesUpdate = Partial<Omit<TIdentities, TImmutableDBKeys>>;
|
export type TIdentitiesUpdate = Partial<Omit<z.input<typeof IdentitiesSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -23,5 +23,5 @@ export const IdentityAccessTokensSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
export type TIdentityAccessTokens = z.infer<typeof IdentityAccessTokensSchema>;
|
||||||
export type TIdentityAccessTokensInsert = Omit<TIdentityAccessTokens, TImmutableDBKeys>;
|
export type TIdentityAccessTokensInsert = Omit<z.input<typeof IdentityAccessTokensSchema>, TImmutableDBKeys>;
|
||||||
export type TIdentityAccessTokensUpdate = Partial<Omit<TIdentityAccessTokens, TImmutableDBKeys>>;
|
export type TIdentityAccessTokensUpdate = Partial<Omit<z.input<typeof IdentityAccessTokensSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -18,5 +18,7 @@ export const IdentityOrgMembershipsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
|
export type TIdentityOrgMemberships = z.infer<typeof IdentityOrgMembershipsSchema>;
|
||||||
export type TIdentityOrgMembershipsInsert = Omit<TIdentityOrgMemberships, TImmutableDBKeys>;
|
export type TIdentityOrgMembershipsInsert = Omit<z.input<typeof IdentityOrgMembershipsSchema>, TImmutableDBKeys>;
|
||||||
export type TIdentityOrgMembershipsUpdate = Partial<Omit<TIdentityOrgMemberships, TImmutableDBKeys>>;
|
export type TIdentityOrgMembershipsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof IdentityOrgMembershipsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
31
backend/src/db/schemas/identity-project-membership-role.ts
Normal file
31
backend/src/db/schemas/identity-project-membership-role.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const IdentityProjectMembershipRoleSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
role: z.string(),
|
||||||
|
projectMembershipId: z.string().uuid(),
|
||||||
|
customRoleId: z.string().uuid().nullable().optional(),
|
||||||
|
isTemporary: z.boolean().default(false),
|
||||||
|
temporaryMode: z.string().nullable().optional(),
|
||||||
|
temporaryRange: z.string().nullable().optional(),
|
||||||
|
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||||
|
temporaryAccessEndTime: z.date().nullable().optional(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TIdentityProjectMembershipRole = z.infer<typeof IdentityProjectMembershipRoleSchema>;
|
||||||
|
export type TIdentityProjectMembershipRoleInsert = Omit<
|
||||||
|
z.input<typeof IdentityProjectMembershipRoleSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TIdentityProjectMembershipRoleUpdate = Partial<
|
||||||
|
Omit<z.input<typeof IdentityProjectMembershipRoleSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
@ -18,5 +18,10 @@ export const IdentityProjectMembershipsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
|
export type TIdentityProjectMemberships = z.infer<typeof IdentityProjectMembershipsSchema>;
|
||||||
export type TIdentityProjectMembershipsInsert = Omit<TIdentityProjectMemberships, TImmutableDBKeys>;
|
export type TIdentityProjectMembershipsInsert = Omit<
|
||||||
export type TIdentityProjectMembershipsUpdate = Partial<Omit<TIdentityProjectMemberships, TImmutableDBKeys>>;
|
z.input<typeof IdentityProjectMembershipsSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TIdentityProjectMembershipsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof IdentityProjectMembershipsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -23,5 +23,7 @@ export const IdentityUaClientSecretsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
|
export type TIdentityUaClientSecrets = z.infer<typeof IdentityUaClientSecretsSchema>;
|
||||||
export type TIdentityUaClientSecretsInsert = Omit<TIdentityUaClientSecrets, TImmutableDBKeys>;
|
export type TIdentityUaClientSecretsInsert = Omit<z.input<typeof IdentityUaClientSecretsSchema>, TImmutableDBKeys>;
|
||||||
export type TIdentityUaClientSecretsUpdate = Partial<Omit<TIdentityUaClientSecrets, TImmutableDBKeys>>;
|
export type TIdentityUaClientSecretsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof IdentityUaClientSecretsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -21,5 +21,7 @@ export const IdentityUniversalAuthsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
|
export type TIdentityUniversalAuths = z.infer<typeof IdentityUniversalAuthsSchema>;
|
||||||
export type TIdentityUniversalAuthsInsert = Omit<TIdentityUniversalAuths, TImmutableDBKeys>;
|
export type TIdentityUniversalAuthsInsert = Omit<z.input<typeof IdentityUniversalAuthsSchema>, TImmutableDBKeys>;
|
||||||
export type TIdentityUniversalAuthsUpdate = Partial<Omit<TIdentityUniversalAuths, TImmutableDBKeys>>;
|
export type TIdentityUniversalAuthsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof IdentityUniversalAuthsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -16,5 +16,5 @@ export const IncidentContactsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>;
|
export type TIncidentContacts = z.infer<typeof IncidentContactsSchema>;
|
||||||
export type TIncidentContactsInsert = Omit<TIncidentContacts, TImmutableDBKeys>;
|
export type TIncidentContactsInsert = Omit<z.input<typeof IncidentContactsSchema>, TImmutableDBKeys>;
|
||||||
export type TIncidentContactsUpdate = Partial<Omit<TIncidentContacts, TImmutableDBKeys>>;
|
export type TIncidentContactsUpdate = Partial<Omit<z.input<typeof IncidentContactsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -8,12 +8,14 @@ export * from "./git-app-org";
|
|||||||
export * from "./identities";
|
export * from "./identities";
|
||||||
export * from "./identity-access-tokens";
|
export * from "./identity-access-tokens";
|
||||||
export * from "./identity-org-memberships";
|
export * from "./identity-org-memberships";
|
||||||
|
export * from "./identity-project-membership-role";
|
||||||
export * from "./identity-project-memberships";
|
export * from "./identity-project-memberships";
|
||||||
export * from "./identity-ua-client-secrets";
|
export * from "./identity-ua-client-secrets";
|
||||||
export * from "./identity-universal-auths";
|
export * from "./identity-universal-auths";
|
||||||
export * from "./incident-contacts";
|
export * from "./incident-contacts";
|
||||||
export * from "./integration-auths";
|
export * from "./integration-auths";
|
||||||
export * from "./integrations";
|
export * from "./integrations";
|
||||||
|
export * from "./ldap-configs";
|
||||||
export * from "./models";
|
export * from "./models";
|
||||||
export * from "./org-bots";
|
export * from "./org-bots";
|
||||||
export * from "./org-memberships";
|
export * from "./org-memberships";
|
||||||
@ -24,8 +26,10 @@ export * from "./project-environments";
|
|||||||
export * from "./project-keys";
|
export * from "./project-keys";
|
||||||
export * from "./project-memberships";
|
export * from "./project-memberships";
|
||||||
export * from "./project-roles";
|
export * from "./project-roles";
|
||||||
|
export * from "./project-user-membership-roles";
|
||||||
export * from "./projects";
|
export * from "./projects";
|
||||||
export * from "./saml-configs";
|
export * from "./saml-configs";
|
||||||
|
export * from "./scim-tokens";
|
||||||
export * from "./secret-approval-policies";
|
export * from "./secret-approval-policies";
|
||||||
export * from "./secret-approval-policies-approvers";
|
export * from "./secret-approval-policies-approvers";
|
||||||
export * from "./secret-approval-request-secret-tags";
|
export * from "./secret-approval-request-secret-tags";
|
||||||
@ -51,6 +55,7 @@ export * from "./service-tokens";
|
|||||||
export * from "./super-admin";
|
export * from "./super-admin";
|
||||||
export * from "./trusted-ips";
|
export * from "./trusted-ips";
|
||||||
export * from "./user-actions";
|
export * from "./user-actions";
|
||||||
|
export * from "./user-aliases";
|
||||||
export * from "./user-encryption-keys";
|
export * from "./user-encryption-keys";
|
||||||
export * from "./users";
|
export * from "./users";
|
||||||
export * from "./webhooks";
|
export * from "./webhooks";
|
||||||
|
@ -33,5 +33,5 @@ export const IntegrationAuthsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>;
|
export type TIntegrationAuths = z.infer<typeof IntegrationAuthsSchema>;
|
||||||
export type TIntegrationAuthsInsert = Omit<TIntegrationAuths, TImmutableDBKeys>;
|
export type TIntegrationAuthsInsert = Omit<z.input<typeof IntegrationAuthsSchema>, TImmutableDBKeys>;
|
||||||
export type TIntegrationAuthsUpdate = Partial<Omit<TIntegrationAuths, TImmutableDBKeys>>;
|
export type TIntegrationAuthsUpdate = Partial<Omit<z.input<typeof IntegrationAuthsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -27,9 +27,10 @@ export const IntegrationsSchema = z.object({
|
|||||||
envId: z.string().uuid(),
|
envId: z.string().uuid(),
|
||||||
secretPath: z.string().default("/"),
|
secretPath: z.string().default("/"),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
lastUsed: z.date().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TIntegrations = z.infer<typeof IntegrationsSchema>;
|
export type TIntegrations = z.infer<typeof IntegrationsSchema>;
|
||||||
export type TIntegrationsInsert = Omit<TIntegrations, TImmutableDBKeys>;
|
export type TIntegrationsInsert = Omit<z.input<typeof IntegrationsSchema>, TImmutableDBKeys>;
|
||||||
export type TIntegrationsUpdate = Partial<Omit<TIntegrations, TImmutableDBKeys>>;
|
export type TIntegrationsUpdate = Partial<Omit<z.input<typeof IntegrationsSchema>, TImmutableDBKeys>>;
|
||||||
|
31
backend/src/db/schemas/ldap-configs.ts
Normal file
31
backend/src/db/schemas/ldap-configs.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const LdapConfigsSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
isActive: z.boolean(),
|
||||||
|
url: z.string(),
|
||||||
|
encryptedBindDN: z.string(),
|
||||||
|
bindDNIV: z.string(),
|
||||||
|
bindDNTag: z.string(),
|
||||||
|
encryptedBindPass: z.string(),
|
||||||
|
bindPassIV: z.string(),
|
||||||
|
bindPassTag: z.string(),
|
||||||
|
searchBase: z.string(),
|
||||||
|
encryptedCACert: z.string(),
|
||||||
|
caCertIV: z.string(),
|
||||||
|
caCertTag: z.string(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TLdapConfigs = z.infer<typeof LdapConfigsSchema>;
|
||||||
|
export type TLdapConfigsInsert = Omit<z.input<typeof LdapConfigsSchema>, TImmutableDBKeys>;
|
||||||
|
export type TLdapConfigsUpdate = Partial<Omit<z.input<typeof LdapConfigsSchema>, TImmutableDBKeys>>;
|
@ -2,6 +2,7 @@ import { z } from "zod";
|
|||||||
|
|
||||||
export enum TableName {
|
export enum TableName {
|
||||||
Users = "users",
|
Users = "users",
|
||||||
|
UserAliases = "user_aliases",
|
||||||
UserEncryptionKey = "user_encryption_keys",
|
UserEncryptionKey = "user_encryption_keys",
|
||||||
AuthTokens = "auth_tokens",
|
AuthTokens = "auth_tokens",
|
||||||
AuthTokenSession = "auth_token_sessions",
|
AuthTokenSession = "auth_token_sessions",
|
||||||
@ -19,6 +20,7 @@ export enum TableName {
|
|||||||
Environment = "project_environments",
|
Environment = "project_environments",
|
||||||
ProjectMembership = "project_memberships",
|
ProjectMembership = "project_memberships",
|
||||||
ProjectRoles = "project_roles",
|
ProjectRoles = "project_roles",
|
||||||
|
ProjectUserMembershipRole = "project_user_membership_roles",
|
||||||
ProjectKeys = "project_keys",
|
ProjectKeys = "project_keys",
|
||||||
Secret = "secrets",
|
Secret = "secrets",
|
||||||
SecretBlindIndex = "secret_blind_indexes",
|
SecretBlindIndex = "secret_blind_indexes",
|
||||||
@ -40,6 +42,8 @@ export enum TableName {
|
|||||||
IdentityUaClientSecret = "identity_ua_client_secrets",
|
IdentityUaClientSecret = "identity_ua_client_secrets",
|
||||||
IdentityOrgMembership = "identity_org_memberships",
|
IdentityOrgMembership = "identity_org_memberships",
|
||||||
IdentityProjectMembership = "identity_project_memberships",
|
IdentityProjectMembership = "identity_project_memberships",
|
||||||
|
IdentityProjectMembershipRole = "identity_project_membership_role",
|
||||||
|
ScimToken = "scim_tokens",
|
||||||
SecretApprovalPolicy = "secret_approval_policies",
|
SecretApprovalPolicy = "secret_approval_policies",
|
||||||
SecretApprovalPolicyApprover = "secret_approval_policies_approvers",
|
SecretApprovalPolicyApprover = "secret_approval_policies_approvers",
|
||||||
SecretApprovalRequest = "secret_approval_requests",
|
SecretApprovalRequest = "secret_approval_requests",
|
||||||
@ -49,6 +53,7 @@ export enum TableName {
|
|||||||
SecretRotation = "secret_rotations",
|
SecretRotation = "secret_rotations",
|
||||||
SecretRotationOutput = "secret_rotation_outputs",
|
SecretRotationOutput = "secret_rotation_outputs",
|
||||||
SamlConfig = "saml_configs",
|
SamlConfig = "saml_configs",
|
||||||
|
LdapConfig = "ldap_configs",
|
||||||
AuditLog = "audit_logs",
|
AuditLog = "audit_logs",
|
||||||
GitAppInstallSession = "git_app_install_sessions",
|
GitAppInstallSession = "git_app_install_sessions",
|
||||||
GitAppOrg = "git_app_org",
|
GitAppOrg = "git_app_org",
|
||||||
@ -111,6 +116,17 @@ export enum SecretType {
|
|||||||
Personal = "personal"
|
Personal = "personal"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum ProjectVersion {
|
||||||
|
V1 = 1,
|
||||||
|
V2 = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ProjectUpgradeStatus {
|
||||||
|
InProgress = "IN_PROGRESS",
|
||||||
|
// Completed -> Will be null if completed. So a completed status is not needed
|
||||||
|
Failed = "FAILED"
|
||||||
|
}
|
||||||
|
|
||||||
export enum IdentityAuthMethod {
|
export enum IdentityAuthMethod {
|
||||||
Univeral = "universal-auth"
|
Univeral = "universal-auth"
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,5 @@ export const OrgBotsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TOrgBots = z.infer<typeof OrgBotsSchema>;
|
export type TOrgBots = z.infer<typeof OrgBotsSchema>;
|
||||||
export type TOrgBotsInsert = Omit<TOrgBots, TImmutableDBKeys>;
|
export type TOrgBotsInsert = Omit<z.input<typeof OrgBotsSchema>, TImmutableDBKeys>;
|
||||||
export type TOrgBotsUpdate = Partial<Omit<TOrgBots, TImmutableDBKeys>>;
|
export type TOrgBotsUpdate = Partial<Omit<z.input<typeof OrgBotsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -20,5 +20,5 @@ export const OrgMembershipsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>;
|
export type TOrgMemberships = z.infer<typeof OrgMembershipsSchema>;
|
||||||
export type TOrgMembershipsInsert = Omit<TOrgMemberships, TImmutableDBKeys>;
|
export type TOrgMembershipsInsert = Omit<z.input<typeof OrgMembershipsSchema>, TImmutableDBKeys>;
|
||||||
export type TOrgMembershipsUpdate = Partial<Omit<TOrgMemberships, TImmutableDBKeys>>;
|
export type TOrgMembershipsUpdate = Partial<Omit<z.input<typeof OrgMembershipsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -19,5 +19,5 @@ export const OrgRolesSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TOrgRoles = z.infer<typeof OrgRolesSchema>;
|
export type TOrgRoles = z.infer<typeof OrgRolesSchema>;
|
||||||
export type TOrgRolesInsert = Omit<TOrgRoles, TImmutableDBKeys>;
|
export type TOrgRolesInsert = Omit<z.input<typeof OrgRolesSchema>, TImmutableDBKeys>;
|
||||||
export type TOrgRolesUpdate = Partial<Omit<TOrgRoles, TImmutableDBKeys>>;
|
export type TOrgRolesUpdate = Partial<Omit<z.input<typeof OrgRolesSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -14,9 +14,10 @@ export const OrganizationsSchema = z.object({
|
|||||||
slug: z.string(),
|
slug: z.string(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date(),
|
updatedAt: z.date(),
|
||||||
authEnforced: z.boolean().default(false).nullable().optional()
|
authEnforced: z.boolean().default(false).nullable().optional(),
|
||||||
|
scimEnabled: z.boolean().default(false).nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
export type TOrganizations = z.infer<typeof OrganizationsSchema>;
|
||||||
export type TOrganizationsInsert = Omit<TOrganizations, TImmutableDBKeys>;
|
export type TOrganizationsInsert = Omit<z.input<typeof OrganizationsSchema>, TImmutableDBKeys>;
|
||||||
export type TOrganizationsUpdate = Partial<Omit<TOrganizations, TImmutableDBKeys>>;
|
export type TOrganizationsUpdate = Partial<Omit<z.input<typeof OrganizationsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -26,5 +26,5 @@ export const ProjectBotsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectBots = z.infer<typeof ProjectBotsSchema>;
|
export type TProjectBots = z.infer<typeof ProjectBotsSchema>;
|
||||||
export type TProjectBotsInsert = Omit<TProjectBots, TImmutableDBKeys>;
|
export type TProjectBotsInsert = Omit<z.input<typeof ProjectBotsSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectBotsUpdate = Partial<Omit<TProjectBots, TImmutableDBKeys>>;
|
export type TProjectBotsUpdate = Partial<Omit<z.input<typeof ProjectBotsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -18,5 +18,5 @@ export const ProjectEnvironmentsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>;
|
export type TProjectEnvironments = z.infer<typeof ProjectEnvironmentsSchema>;
|
||||||
export type TProjectEnvironmentsInsert = Omit<TProjectEnvironments, TImmutableDBKeys>;
|
export type TProjectEnvironmentsInsert = Omit<z.input<typeof ProjectEnvironmentsSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectEnvironmentsUpdate = Partial<Omit<TProjectEnvironments, TImmutableDBKeys>>;
|
export type TProjectEnvironmentsUpdate = Partial<Omit<z.input<typeof ProjectEnvironmentsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -19,5 +19,5 @@ export const ProjectKeysSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectKeys = z.infer<typeof ProjectKeysSchema>;
|
export type TProjectKeys = z.infer<typeof ProjectKeysSchema>;
|
||||||
export type TProjectKeysInsert = Omit<TProjectKeys, TImmutableDBKeys>;
|
export type TProjectKeysInsert = Omit<z.input<typeof ProjectKeysSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectKeysUpdate = Partial<Omit<TProjectKeys, TImmutableDBKeys>>;
|
export type TProjectKeysUpdate = Partial<Omit<z.input<typeof ProjectKeysSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -18,5 +18,5 @@ export const ProjectMembershipsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
|
export type TProjectMemberships = z.infer<typeof ProjectMembershipsSchema>;
|
||||||
export type TProjectMembershipsInsert = Omit<TProjectMemberships, TImmutableDBKeys>;
|
export type TProjectMembershipsInsert = Omit<z.input<typeof ProjectMembershipsSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectMembershipsUpdate = Partial<Omit<TProjectMemberships, TImmutableDBKeys>>;
|
export type TProjectMembershipsUpdate = Partial<Omit<z.input<typeof ProjectMembershipsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -19,5 +19,5 @@ export const ProjectRolesSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
|
export type TProjectRoles = z.infer<typeof ProjectRolesSchema>;
|
||||||
export type TProjectRolesInsert = Omit<TProjectRoles, TImmutableDBKeys>;
|
export type TProjectRolesInsert = Omit<z.input<typeof ProjectRolesSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectRolesUpdate = Partial<Omit<TProjectRoles, TImmutableDBKeys>>;
|
export type TProjectRolesUpdate = Partial<Omit<z.input<typeof ProjectRolesSchema>, TImmutableDBKeys>>;
|
||||||
|
31
backend/src/db/schemas/project-user-membership-roles.ts
Normal file
31
backend/src/db/schemas/project-user-membership-roles.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const ProjectUserMembershipRolesSchema = z.object({
|
||||||
|
id: z.string().uuid(),
|
||||||
|
role: z.string(),
|
||||||
|
projectMembershipId: z.string().uuid(),
|
||||||
|
customRoleId: z.string().uuid().nullable().optional(),
|
||||||
|
isTemporary: z.boolean().default(false),
|
||||||
|
temporaryMode: z.string().nullable().optional(),
|
||||||
|
temporaryRange: z.string().nullable().optional(),
|
||||||
|
temporaryAccessStartTime: z.date().nullable().optional(),
|
||||||
|
temporaryAccessEndTime: z.date().nullable().optional(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TProjectUserMembershipRoles = z.infer<typeof ProjectUserMembershipRolesSchema>;
|
||||||
|
export type TProjectUserMembershipRolesInsert = Omit<
|
||||||
|
z.input<typeof ProjectUserMembershipRolesSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TProjectUserMembershipRolesUpdate = Partial<
|
||||||
|
Omit<z.input<typeof ProjectUserMembershipRolesSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
@ -14,9 +14,11 @@ export const ProjectsSchema = z.object({
|
|||||||
autoCapitalization: z.boolean().default(true).nullable().optional(),
|
autoCapitalization: z.boolean().default(true).nullable().optional(),
|
||||||
orgId: z.string().uuid(),
|
orgId: z.string().uuid(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
version: z.number().default(1),
|
||||||
|
upgradeStatus: z.string().nullable().optional()
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TProjects = z.infer<typeof ProjectsSchema>;
|
export type TProjects = z.infer<typeof ProjectsSchema>;
|
||||||
export type TProjectsInsert = Omit<TProjects, TImmutableDBKeys>;
|
export type TProjectsInsert = Omit<z.input<typeof ProjectsSchema>, TImmutableDBKeys>;
|
||||||
export type TProjectsUpdate = Partial<Omit<TProjects, TImmutableDBKeys>>;
|
export type TProjectsUpdate = Partial<Omit<z.input<typeof ProjectsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -27,5 +27,5 @@ export const SamlConfigsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;
|
export type TSamlConfigs = z.infer<typeof SamlConfigsSchema>;
|
||||||
export type TSamlConfigsInsert = Omit<TSamlConfigs, TImmutableDBKeys>;
|
export type TSamlConfigsInsert = Omit<z.input<typeof SamlConfigsSchema>, TImmutableDBKeys>;
|
||||||
export type TSamlConfigsUpdate = Partial<Omit<TSamlConfigs, TImmutableDBKeys>>;
|
export type TSamlConfigsUpdate = Partial<Omit<z.input<typeof SamlConfigsSchema>, TImmutableDBKeys>>;
|
||||||
|
21
backend/src/db/schemas/scim-tokens.ts
Normal file
21
backend/src/db/schemas/scim-tokens.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
// Code generated by automation script, DO NOT EDIT.
|
||||||
|
// Automated by pulling database and generating zod schema
|
||||||
|
// To update. Just run npm run generate:schema
|
||||||
|
// Written by akhilmhdh.
|
||||||
|
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
import { TImmutableDBKeys } from "./models";
|
||||||
|
|
||||||
|
export const ScimTokensSchema = z.object({
|
||||||
|
id: z.string(),
|
||||||
|
ttlDays: z.coerce.number().default(365),
|
||||||
|
description: z.string(),
|
||||||
|
orgId: z.string().uuid(),
|
||||||
|
createdAt: z.date(),
|
||||||
|
updatedAt: z.date()
|
||||||
|
});
|
||||||
|
|
||||||
|
export type TScimTokens = z.infer<typeof ScimTokensSchema>;
|
||||||
|
export type TScimTokensInsert = Omit<z.input<typeof ScimTokensSchema>, TImmutableDBKeys>;
|
||||||
|
export type TScimTokensUpdate = Partial<Omit<z.input<typeof ScimTokensSchema>, TImmutableDBKeys>>;
|
@ -16,5 +16,10 @@ export const SecretApprovalPoliciesApproversSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
|
export type TSecretApprovalPoliciesApprovers = z.infer<typeof SecretApprovalPoliciesApproversSchema>;
|
||||||
export type TSecretApprovalPoliciesApproversInsert = Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>;
|
export type TSecretApprovalPoliciesApproversInsert = Omit<
|
||||||
export type TSecretApprovalPoliciesApproversUpdate = Partial<Omit<TSecretApprovalPoliciesApprovers, TImmutableDBKeys>>;
|
z.input<typeof SecretApprovalPoliciesApproversSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TSecretApprovalPoliciesApproversUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalPoliciesApproversSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -18,5 +18,7 @@ export const SecretApprovalPoliciesSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
|
export type TSecretApprovalPolicies = z.infer<typeof SecretApprovalPoliciesSchema>;
|
||||||
export type TSecretApprovalPoliciesInsert = Omit<TSecretApprovalPolicies, TImmutableDBKeys>;
|
export type TSecretApprovalPoliciesInsert = Omit<z.input<typeof SecretApprovalPoliciesSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretApprovalPoliciesUpdate = Partial<Omit<TSecretApprovalPolicies, TImmutableDBKeys>>;
|
export type TSecretApprovalPoliciesUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalPoliciesSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -16,5 +16,10 @@ export const SecretApprovalRequestSecretTagsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
|
export type TSecretApprovalRequestSecretTags = z.infer<typeof SecretApprovalRequestSecretTagsSchema>;
|
||||||
export type TSecretApprovalRequestSecretTagsInsert = Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>;
|
export type TSecretApprovalRequestSecretTagsInsert = Omit<
|
||||||
export type TSecretApprovalRequestSecretTagsUpdate = Partial<Omit<TSecretApprovalRequestSecretTags, TImmutableDBKeys>>;
|
z.input<typeof SecretApprovalRequestSecretTagsSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TSecretApprovalRequestSecretTagsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalRequestSecretTagsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -17,5 +17,10 @@ export const SecretApprovalRequestsReviewersSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
|
export type TSecretApprovalRequestsReviewers = z.infer<typeof SecretApprovalRequestsReviewersSchema>;
|
||||||
export type TSecretApprovalRequestsReviewersInsert = Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>;
|
export type TSecretApprovalRequestsReviewersInsert = Omit<
|
||||||
export type TSecretApprovalRequestsReviewersUpdate = Partial<Omit<TSecretApprovalRequestsReviewers, TImmutableDBKeys>>;
|
z.input<typeof SecretApprovalRequestsReviewersSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TSecretApprovalRequestsReviewersUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalRequestsReviewersSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -35,5 +35,10 @@ export const SecretApprovalRequestsSecretsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
|
export type TSecretApprovalRequestsSecrets = z.infer<typeof SecretApprovalRequestsSecretsSchema>;
|
||||||
export type TSecretApprovalRequestsSecretsInsert = Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>;
|
export type TSecretApprovalRequestsSecretsInsert = Omit<
|
||||||
export type TSecretApprovalRequestsSecretsUpdate = Partial<Omit<TSecretApprovalRequestsSecrets, TImmutableDBKeys>>;
|
z.input<typeof SecretApprovalRequestsSecretsSchema>,
|
||||||
|
TImmutableDBKeys
|
||||||
|
>;
|
||||||
|
export type TSecretApprovalRequestsSecretsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalRequestsSecretsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -22,5 +22,7 @@ export const SecretApprovalRequestsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
|
export type TSecretApprovalRequests = z.infer<typeof SecretApprovalRequestsSchema>;
|
||||||
export type TSecretApprovalRequestsInsert = Omit<TSecretApprovalRequests, TImmutableDBKeys>;
|
export type TSecretApprovalRequestsInsert = Omit<z.input<typeof SecretApprovalRequestsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretApprovalRequestsUpdate = Partial<Omit<TSecretApprovalRequests, TImmutableDBKeys>>;
|
export type TSecretApprovalRequestsUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretApprovalRequestsSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -20,5 +20,5 @@ export const SecretBlindIndexesSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>;
|
export type TSecretBlindIndexes = z.infer<typeof SecretBlindIndexesSchema>;
|
||||||
export type TSecretBlindIndexesInsert = Omit<TSecretBlindIndexes, TImmutableDBKeys>;
|
export type TSecretBlindIndexesInsert = Omit<z.input<typeof SecretBlindIndexesSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretBlindIndexesUpdate = Partial<Omit<TSecretBlindIndexes, TImmutableDBKeys>>;
|
export type TSecretBlindIndexesUpdate = Partial<Omit<z.input<typeof SecretBlindIndexesSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -18,5 +18,5 @@ export const SecretFolderVersionsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>;
|
export type TSecretFolderVersions = z.infer<typeof SecretFolderVersionsSchema>;
|
||||||
export type TSecretFolderVersionsInsert = Omit<TSecretFolderVersions, TImmutableDBKeys>;
|
export type TSecretFolderVersionsInsert = Omit<z.input<typeof SecretFolderVersionsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretFolderVersionsUpdate = Partial<Omit<TSecretFolderVersions, TImmutableDBKeys>>;
|
export type TSecretFolderVersionsUpdate = Partial<Omit<z.input<typeof SecretFolderVersionsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -18,5 +18,5 @@ export const SecretFoldersSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretFolders = z.infer<typeof SecretFoldersSchema>;
|
export type TSecretFolders = z.infer<typeof SecretFoldersSchema>;
|
||||||
export type TSecretFoldersInsert = Omit<TSecretFolders, TImmutableDBKeys>;
|
export type TSecretFoldersInsert = Omit<z.input<typeof SecretFoldersSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretFoldersUpdate = Partial<Omit<TSecretFolders, TImmutableDBKeys>>;
|
export type TSecretFoldersUpdate = Partial<Omit<z.input<typeof SecretFoldersSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -19,5 +19,5 @@ export const SecretImportsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretImports = z.infer<typeof SecretImportsSchema>;
|
export type TSecretImports = z.infer<typeof SecretImportsSchema>;
|
||||||
export type TSecretImportsInsert = Omit<TSecretImports, TImmutableDBKeys>;
|
export type TSecretImportsInsert = Omit<z.input<typeof SecretImportsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretImportsUpdate = Partial<Omit<TSecretImports, TImmutableDBKeys>>;
|
export type TSecretImportsUpdate = Partial<Omit<z.input<typeof SecretImportsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -15,5 +15,5 @@ export const SecretRotationOutputsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>;
|
export type TSecretRotationOutputs = z.infer<typeof SecretRotationOutputsSchema>;
|
||||||
export type TSecretRotationOutputsInsert = Omit<TSecretRotationOutputs, TImmutableDBKeys>;
|
export type TSecretRotationOutputsInsert = Omit<z.input<typeof SecretRotationOutputsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretRotationOutputsUpdate = Partial<Omit<TSecretRotationOutputs, TImmutableDBKeys>>;
|
export type TSecretRotationOutputsUpdate = Partial<Omit<z.input<typeof SecretRotationOutputsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -26,5 +26,5 @@ export const SecretRotationsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretRotations = z.infer<typeof SecretRotationsSchema>;
|
export type TSecretRotations = z.infer<typeof SecretRotationsSchema>;
|
||||||
export type TSecretRotationsInsert = Omit<TSecretRotations, TImmutableDBKeys>;
|
export type TSecretRotationsInsert = Omit<z.input<typeof SecretRotationsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretRotationsUpdate = Partial<Omit<TSecretRotations, TImmutableDBKeys>>;
|
export type TSecretRotationsUpdate = Partial<Omit<z.input<typeof SecretRotationsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -42,5 +42,7 @@ export const SecretScanningGitRisksSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
|
export type TSecretScanningGitRisks = z.infer<typeof SecretScanningGitRisksSchema>;
|
||||||
export type TSecretScanningGitRisksInsert = Omit<TSecretScanningGitRisks, TImmutableDBKeys>;
|
export type TSecretScanningGitRisksInsert = Omit<z.input<typeof SecretScanningGitRisksSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretScanningGitRisksUpdate = Partial<Omit<TSecretScanningGitRisks, TImmutableDBKeys>>;
|
export type TSecretScanningGitRisksUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretScanningGitRisksSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotFoldersSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>;
|
export type TSecretSnapshotFolders = z.infer<typeof SecretSnapshotFoldersSchema>;
|
||||||
export type TSecretSnapshotFoldersInsert = Omit<TSecretSnapshotFolders, TImmutableDBKeys>;
|
export type TSecretSnapshotFoldersInsert = Omit<z.input<typeof SecretSnapshotFoldersSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretSnapshotFoldersUpdate = Partial<Omit<TSecretSnapshotFolders, TImmutableDBKeys>>;
|
export type TSecretSnapshotFoldersUpdate = Partial<Omit<z.input<typeof SecretSnapshotFoldersSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotSecretsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>;
|
export type TSecretSnapshotSecrets = z.infer<typeof SecretSnapshotSecretsSchema>;
|
||||||
export type TSecretSnapshotSecretsInsert = Omit<TSecretSnapshotSecrets, TImmutableDBKeys>;
|
export type TSecretSnapshotSecretsInsert = Omit<z.input<typeof SecretSnapshotSecretsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretSnapshotSecretsUpdate = Partial<Omit<TSecretSnapshotSecrets, TImmutableDBKeys>>;
|
export type TSecretSnapshotSecretsUpdate = Partial<Omit<z.input<typeof SecretSnapshotSecretsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -17,5 +17,5 @@ export const SecretSnapshotsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>;
|
export type TSecretSnapshots = z.infer<typeof SecretSnapshotsSchema>;
|
||||||
export type TSecretSnapshotsInsert = Omit<TSecretSnapshots, TImmutableDBKeys>;
|
export type TSecretSnapshotsInsert = Omit<z.input<typeof SecretSnapshotsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretSnapshotsUpdate = Partial<Omit<TSecretSnapshots, TImmutableDBKeys>>;
|
export type TSecretSnapshotsUpdate = Partial<Omit<z.input<typeof SecretSnapshotsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -14,5 +14,5 @@ export const SecretTagJunctionSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>;
|
export type TSecretTagJunction = z.infer<typeof SecretTagJunctionSchema>;
|
||||||
export type TSecretTagJunctionInsert = Omit<TSecretTagJunction, TImmutableDBKeys>;
|
export type TSecretTagJunctionInsert = Omit<z.input<typeof SecretTagJunctionSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretTagJunctionUpdate = Partial<Omit<TSecretTagJunction, TImmutableDBKeys>>;
|
export type TSecretTagJunctionUpdate = Partial<Omit<z.input<typeof SecretTagJunctionSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -19,5 +19,5 @@ export const SecretTagsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretTags = z.infer<typeof SecretTagsSchema>;
|
export type TSecretTags = z.infer<typeof SecretTagsSchema>;
|
||||||
export type TSecretTagsInsert = Omit<TSecretTags, TImmutableDBKeys>;
|
export type TSecretTagsInsert = Omit<z.input<typeof SecretTagsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretTagsUpdate = Partial<Omit<TSecretTags, TImmutableDBKeys>>;
|
export type TSecretTagsUpdate = Partial<Omit<z.input<typeof SecretTagsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -14,5 +14,7 @@ export const SecretVersionTagJunctionSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
|
export type TSecretVersionTagJunction = z.infer<typeof SecretVersionTagJunctionSchema>;
|
||||||
export type TSecretVersionTagJunctionInsert = Omit<TSecretVersionTagJunction, TImmutableDBKeys>;
|
export type TSecretVersionTagJunctionInsert = Omit<z.input<typeof SecretVersionTagJunctionSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretVersionTagJunctionUpdate = Partial<Omit<TSecretVersionTagJunction, TImmutableDBKeys>>;
|
export type TSecretVersionTagJunctionUpdate = Partial<
|
||||||
|
Omit<z.input<typeof SecretVersionTagJunctionSchema>, TImmutableDBKeys>
|
||||||
|
>;
|
||||||
|
@ -36,5 +36,5 @@ export const SecretVersionsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
export type TSecretVersions = z.infer<typeof SecretVersionsSchema>;
|
||||||
export type TSecretVersionsInsert = Omit<TSecretVersions, TImmutableDBKeys>;
|
export type TSecretVersionsInsert = Omit<z.input<typeof SecretVersionsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretVersionsUpdate = Partial<Omit<TSecretVersions, TImmutableDBKeys>>;
|
export type TSecretVersionsUpdate = Partial<Omit<z.input<typeof SecretVersionsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -34,5 +34,5 @@ export const SecretsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TSecrets = z.infer<typeof SecretsSchema>;
|
export type TSecrets = z.infer<typeof SecretsSchema>;
|
||||||
export type TSecretsInsert = Omit<TSecrets, TImmutableDBKeys>;
|
export type TSecretsInsert = Omit<z.input<typeof SecretsSchema>, TImmutableDBKeys>;
|
||||||
export type TSecretsUpdate = Partial<Omit<TSecrets, TImmutableDBKeys>>;
|
export type TSecretsUpdate = Partial<Omit<z.input<typeof SecretsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -25,5 +25,5 @@ export const ServiceTokensSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TServiceTokens = z.infer<typeof ServiceTokensSchema>;
|
export type TServiceTokens = z.infer<typeof ServiceTokensSchema>;
|
||||||
export type TServiceTokensInsert = Omit<TServiceTokens, TImmutableDBKeys>;
|
export type TServiceTokensInsert = Omit<z.input<typeof ServiceTokensSchema>, TImmutableDBKeys>;
|
||||||
export type TServiceTokensUpdate = Partial<Omit<TServiceTokens, TImmutableDBKeys>>;
|
export type TServiceTokensUpdate = Partial<Omit<z.input<typeof ServiceTokensSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -12,9 +12,11 @@ export const SuperAdminSchema = z.object({
|
|||||||
initialized: z.boolean().default(false).nullable().optional(),
|
initialized: z.boolean().default(false).nullable().optional(),
|
||||||
allowSignUp: z.boolean().default(true).nullable().optional(),
|
allowSignUp: z.boolean().default(true).nullable().optional(),
|
||||||
createdAt: z.date(),
|
createdAt: z.date(),
|
||||||
updatedAt: z.date()
|
updatedAt: z.date(),
|
||||||
|
allowedSignUpDomain: z.string().nullable().optional(),
|
||||||
|
instanceId: z.string().uuid().default("00000000-0000-0000-0000-000000000000")
|
||||||
});
|
});
|
||||||
|
|
||||||
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;
|
export type TSuperAdmin = z.infer<typeof SuperAdminSchema>;
|
||||||
export type TSuperAdminInsert = Omit<TSuperAdmin, TImmutableDBKeys>;
|
export type TSuperAdminInsert = Omit<z.input<typeof SuperAdminSchema>, TImmutableDBKeys>;
|
||||||
export type TSuperAdminUpdate = Partial<Omit<TSuperAdmin, TImmutableDBKeys>>;
|
export type TSuperAdminUpdate = Partial<Omit<z.input<typeof SuperAdminSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -20,5 +20,5 @@ export const TrustedIpsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TTrustedIps = z.infer<typeof TrustedIpsSchema>;
|
export type TTrustedIps = z.infer<typeof TrustedIpsSchema>;
|
||||||
export type TTrustedIpsInsert = Omit<TTrustedIps, TImmutableDBKeys>;
|
export type TTrustedIpsInsert = Omit<z.input<typeof TrustedIpsSchema>, TImmutableDBKeys>;
|
||||||
export type TTrustedIpsUpdate = Partial<Omit<TTrustedIps, TImmutableDBKeys>>;
|
export type TTrustedIpsUpdate = Partial<Omit<z.input<typeof TrustedIpsSchema>, TImmutableDBKeys>>;
|
||||||
|
@ -16,5 +16,5 @@ export const UserActionsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export type TUserActions = z.infer<typeof UserActionsSchema>;
|
export type TUserActions = z.infer<typeof UserActionsSchema>;
|
||||||
export type TUserActionsInsert = Omit<TUserActions, TImmutableDBKeys>;
|
export type TUserActionsInsert = Omit<z.input<typeof UserActionsSchema>, TImmutableDBKeys>;
|
||||||
export type TUserActionsUpdate = Partial<Omit<TUserActions, TImmutableDBKeys>>;
|
export type TUserActionsUpdate = Partial<Omit<z.input<typeof UserActionsSchema>, TImmutableDBKeys>>;
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user