mirror of
https://github.com/Infisical/infisical.git
synced 2025-07-02 16:55:02 +00:00
Compare commits
370 Commits
patch-3
...
infisical/
Author | SHA1 | Date | |
---|---|---|---|
dcb6f5891f | |||
1254215b51 | |||
a6ead9396c | |||
d33ef9e4e1 | |||
4e20735f98 | |||
f010a3a932 | |||
bbf2634e73 | |||
1980f802fa | |||
6ecd289e6c | |||
b8a6f5dc54 | |||
dedbc4fd60 | |||
d14099990f | |||
3f5ab2a09e | |||
a191f437e9 | |||
1a375ec45b | |||
81f3a6a7a8 | |||
dc8b64708a | |||
dd3790c995 | |||
a91b6ebc03 | |||
e68d1d06a8 | |||
8f754d659a | |||
bef28fea2d | |||
28f15de8df | |||
66d258f02b | |||
d13eafcef7 | |||
6db47499de | |||
1cefb036e0 | |||
af77ad8b2f | |||
dd0f9f5216 | |||
29df6f067e | |||
4dc9a3692e | |||
49bb2121b9 | |||
07679d9318 | |||
fb271726fe | |||
f9e7d4ddd2 | |||
442c454932 | |||
8b22ee1fac | |||
8a10dc8983 | |||
d57920706a | |||
425611b409 | |||
b20489982d | |||
4b569ee4b4 | |||
af9661b221 | |||
53f16f01b8 | |||
f519d1cffc | |||
b8b28d2710 | |||
deab700716 | |||
4d184003a8 | |||
9849312317 | |||
79454a6aea | |||
8e0fb9fe9b | |||
a729114376 | |||
0c20cb0f91 | |||
d1597ed8da | |||
6cee8dc7e5 | |||
13040439c3 | |||
9a4f294749 | |||
2436a572f0 | |||
7cd21e3a93 | |||
e28416b50b | |||
9677836b76 | |||
ca858f8e13 | |||
c2beff493f | |||
34fafd815c | |||
c05ebbb864 | |||
372f2be2f3 | |||
23e621f557 | |||
464b80140f | |||
01cd496afe | |||
6094940a8b | |||
30b959babb | |||
cec14efe86 | |||
b3f090d87e | |||
1deb6827cf | |||
24dbf11962 | |||
20fb3906aa | |||
e7e2ca0f45 | |||
caabf2c952 | |||
35eade0206 | |||
6d1b79430d | |||
7864524944 | |||
adc90e91fe | |||
db7db0cc04 | |||
aa4d9ad267 | |||
27fd857120 | |||
205e46571a | |||
70a6a7cfa1 | |||
558315c24b | |||
a2bd808196 | |||
cfb0d4ee96 | |||
15fc4fd609 | |||
83bff9ae14 | |||
86ba6355cf | |||
6b427adfe0 | |||
01f711ad19 | |||
fa572f7ee0 | |||
249edf98e9 | |||
753a4daf69 | |||
b9320ed9bd | |||
8eace5528f | |||
9407c16e83 | |||
dcdcc40a4a | |||
edd78eaeba | |||
c21ea6fb75 | |||
a60dbe523b | |||
bb9a6b4272 | |||
eaca1b694a | |||
0afb44af29 | |||
3b39e38c89 | |||
4189d1028d | |||
f227824fb8 | |||
49d6918297 | |||
00212f1c72 | |||
987f0c9081 | |||
e4f00f74e9 | |||
ce580f417e | |||
c1662d6db5 | |||
2dae59c6be | |||
9bd764e535 | |||
e4f32f092a | |||
e02c082c7a | |||
80b6c4ad94 | |||
42eb01e1e2 | |||
b8157122e6 | |||
4f66749430 | |||
bfe5ee672b | |||
32a1a0a9e5 | |||
f7e1da65d5 | |||
6bf9bc1d2c | |||
59c747cf72 | |||
b04030a060 | |||
e8fd693da3 | |||
6c2803da93 | |||
4031f4a559 | |||
8ab89bc420 | |||
e46e87d758 | |||
9c2ef15314 | |||
3213dafba9 | |||
33c3c5ecc5 | |||
627c8711dc | |||
8d3d4f222f | |||
65d3038414 | |||
6b7b888fb4 | |||
bf059e0fe5 | |||
28fdf4ed4b | |||
2606e42079 | |||
b1285b401b | |||
3afafbb885 | |||
257547ff4d | |||
da4ae3c503 | |||
fb79e9e6fb | |||
5373cb6afb | |||
31c0bf6831 | |||
67618046c0 | |||
df642179ba | |||
c7d0f2325c | |||
bb6d482ff9 | |||
4f619d7e48 | |||
295c1e5d4a | |||
0be3ad9517 | |||
606ed25104 | |||
c880a48749 | |||
92f7b45e01 | |||
5fe8bdc00b | |||
9f813d72f2 | |||
d90fdac5ce | |||
87709dc86f | |||
deb8e74749 | |||
3519412639 | |||
0506389ada | |||
dd7c449483 | |||
c7572a3374 | |||
fe416556f2 | |||
20fb99f042 | |||
daa94db874 | |||
850e7bff98 | |||
bfaf87c4c2 | |||
55f1392faf | |||
0bf658e501 | |||
aed94ff5bb | |||
0d3f09d668 | |||
16f0ac6d43 | |||
6e6a1c87f2 | |||
b5aa6c0000 | |||
784cdb4201 | |||
17e61bfc68 | |||
a6a60b7bbb | |||
d154f68a59 | |||
f5159583ae | |||
771bec6d6d | |||
010963a80c | |||
0e1191f2ea | |||
8a6ab7f2f6 | |||
4f3582a98b | |||
498a90c484 | |||
76e5d61da5 | |||
53bb3bc610 | |||
1df7b88abf | |||
3670b16657 | |||
9a4b2f7d81 | |||
fadb36edb8 | |||
fbe5a1adb0 | |||
d0695a8998 | |||
a19e8ad016 | |||
15b57de0ed | |||
aaba4a0895 | |||
f3b37de3f3 | |||
fcfd6b3fb2 | |||
05205d1eff | |||
2243bcb3a4 | |||
356e981401 | |||
5b41fb0ff5 | |||
8893aec213 | |||
c4cb8f8008 | |||
046557c97f | |||
a15ba28c18 | |||
8386f4dcbd | |||
ada0fd9c5b | |||
6376c29e49 | |||
402692614e | |||
34de6d4e29 | |||
829e906650 | |||
b7cbb0f1a8 | |||
a50ffbb59d | |||
48eda0c684 | |||
ed89413689 | |||
0c94f77a6d | |||
e6068826f8 | |||
cfa0a2044e | |||
134b503c28 | |||
efcbf1aa88 | |||
284c18db07 | |||
1410a44610 | |||
746ffb3840 | |||
f9f12eafdf | |||
11470a5a0e | |||
9fe2190115 | |||
9e2bd31833 | |||
e88b0ad3c4 | |||
74644fd8bb | |||
2069ac1554 | |||
5a2516e0a7 | |||
b52bc3bed7 | |||
4a153e5658 | |||
7324822be5 | |||
766f301aea | |||
8fbc930012 | |||
0e5190a920 | |||
b815e3eb56 | |||
31231cfcca | |||
ee772e4a77 | |||
7bc29c5981 | |||
e9a89930da | |||
b85499859c | |||
7f17194c0f | |||
1e1ad450d2 | |||
5287b322d8 | |||
45d96be1ff | |||
12840bfdbd | |||
fef5369738 | |||
c94b7d63f6 | |||
485ddc5c50 | |||
edd9c66e49 | |||
0a3b85534b | |||
ec2cc5162e | |||
7ce472957c | |||
8529e0da3d | |||
e5a5433f10 | |||
ee6e518ff8 | |||
15a7222505 | |||
25d482cc62 | |||
785a2bec6a | |||
449466f326 | |||
4131e9c3f1 | |||
310595256f | |||
1737880e58 | |||
b72483f5f2 | |||
ee14bda706 | |||
e56463d52b | |||
ebd3d7c7c4 | |||
9ecbfe201b | |||
ba2a03897f | |||
304f14c0ed | |||
51e5c25e16 | |||
0f6490b1e7 | |||
f894e48fcb | |||
37cfa22619 | |||
94557344b7 | |||
d5063018eb | |||
51d68505d3 | |||
ade27ad072 | |||
683c512bce | |||
43ff28b5fb | |||
ce41855e84 | |||
d24461b17c | |||
1797e56f9f | |||
74f3ca5356 | |||
db27beaf0b | |||
d6e55f51f2 | |||
e9b5996567 | |||
094fe73917 | |||
dc3f85e92e | |||
c463256058 | |||
8df22302fd | |||
f37fa2bbf5 | |||
597c9d6f2a | |||
24d2eea930 | |||
382cb910af | |||
6725475575 | |||
026864951b | |||
287ed05ab7 | |||
37b036e614 | |||
024914c168 | |||
19e8b6d37b | |||
b6d648f1f3 | |||
a514a62a29 | |||
2f24956651 | |||
13d058025c | |||
8ccaa7f29b | |||
b83964051c | |||
0a2b078bdc | |||
40d16fa996 | |||
a3739cfe50 | |||
a73623258e | |||
6da39f41a6 | |||
69bbbfcfd8 | |||
c9d58ec77d | |||
cb364186d8 | |||
918afe05b6 | |||
e822820151 | |||
b5ac49eefe | |||
b21d1a0ed2 | |||
70f1122362 | |||
ea03db8a2c | |||
38d9abca17 | |||
5bed2580c3 | |||
d0b899897b | |||
1861dc85de | |||
bc6bf33674 | |||
44fd35baf5 | |||
8ddfee4c36 | |||
4d0bff4377 | |||
c7b2489d0b | |||
68eb0f8dd9 | |||
5941e8e836 | |||
80e50d13ec | |||
99c8dda4e1 | |||
14c8e3fa3b | |||
7aa3cb53a2 | |||
567309e848 | |||
f264340903 | |||
51b788cc5b | |||
8e0f424249 | |||
f3767d3963 | |||
51cbfdbc46 | |||
f5a580eb72 | |||
460ebf3296 | |||
7f7f11c970 | |||
f799e224a0 | |||
8a87277fe6 | |||
32805c726a | |||
6c4a6d31e4 | |||
e7b89b645f | |||
b60cf2eb07 | |||
cf5a79995f | |||
c51f09fd3a | |||
6cda14328b | |||
b551ee50e7 | |||
93aeacc6b6 | |||
5f29562fad |
@ -3,6 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "infisical/v*.*.*"
|
- "infisical/v*.*.*"
|
||||||
|
- "!infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backend-image:
|
backend-image:
|
||||||
|
57
.github/workflows/release-standalone-docker-img-postgres-offical.yml
vendored
Normal file
57
.github/workflows/release-standalone-docker-img-postgres-offical.yml
vendored
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
name: Release standalone docker image
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
infisical-standalone:
|
||||||
|
name: Build infisical standalone image postgres
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version from tag
|
||||||
|
id: extract_version
|
||||||
|
run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}"
|
||||||
|
- name: ☁️ Checkout source
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- name: 📦 Install dependencies to test all dependencies
|
||||||
|
run: npm ci --only-production
|
||||||
|
working-directory: backend
|
||||||
|
- name: version output
|
||||||
|
run: |
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.major }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.minor }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.patch }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.version_type }}"
|
||||||
|
echo "Output Value: ${{ steps.version.outputs.increment }}"
|
||||||
|
- name: Save commit hashes for tag
|
||||||
|
id: commit
|
||||||
|
uses: pr-mpt/actions-commit-hash@v2
|
||||||
|
- name: 🔧 Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v2
|
||||||
|
- name: 🐋 Login to Docker Hub
|
||||||
|
uses: docker/login-action@v2
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Set up Depot CLI
|
||||||
|
uses: depot/setup-action@v1
|
||||||
|
- name: 📦 Build backend and export to Docker
|
||||||
|
uses: depot/build-push-action@v1
|
||||||
|
with:
|
||||||
|
project: 64mmf0n610
|
||||||
|
token: ${{ secrets.DEPOT_PROJECT_TOKEN }}
|
||||||
|
push: true
|
||||||
|
context: .
|
||||||
|
tags: |
|
||||||
|
infisical/infisical:latest-postgres
|
||||||
|
infisical/infisical:${{ steps.commit.outputs.short }}
|
||||||
|
infisical/infisical:${{ steps.extract_version.outputs.version }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
file: Dockerfile.standalone-infisical
|
||||||
|
build-args: |
|
||||||
|
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
|
||||||
|
INFISICAL_PLATFORM_VERSION=${{ steps.extract_version.outputs.version }}
|
@ -3,6 +3,7 @@ on:
|
|||||||
push:
|
push:
|
||||||
tags:
|
tags:
|
||||||
- "infisical/v*.*.*"
|
- "infisical/v*.*.*"
|
||||||
|
- "!infisical/v*.*.*-postgres"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
infisical-standalone:
|
infisical-standalone:
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,6 +1,7 @@
|
|||||||
# backend
|
# backend
|
||||||
node_modules
|
node_modules
|
||||||
.env
|
.env
|
||||||
|
.env.test
|
||||||
.env.dev
|
.env.dev
|
||||||
.env.gamma
|
.env.gamma
|
||||||
.env.prod
|
.env.prod
|
||||||
@ -61,4 +62,4 @@ yarn-error.log*
|
|||||||
# Editor specific
|
# Editor specific
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
|
||||||
frontend-build
|
frontend-build
|
||||||
|
@ -108,7 +108,7 @@ brews:
|
|||||||
zsh_completion.install "completions/infisical.zsh" => "_infisical"
|
zsh_completion.install "completions/infisical.zsh" => "_infisical"
|
||||||
fish_completion.install "completions/infisical.fish"
|
fish_completion.install "completions/infisical.fish"
|
||||||
man1.install "manpages/infisical.1.gz"
|
man1.install "manpages/infisical.1.gz"
|
||||||
- name: 'infisical@{{.Version}}'
|
- name: "infisical@{{.Version}}"
|
||||||
tap:
|
tap:
|
||||||
owner: Infisical
|
owner: Infisical
|
||||||
name: homebrew-get-cli
|
name: homebrew-get-cli
|
||||||
@ -186,12 +186,14 @@ aurs:
|
|||||||
# man pages
|
# man pages
|
||||||
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
|
install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz"
|
||||||
|
|
||||||
# dockers:
|
dockers:
|
||||||
# - dockerfile: cli/docker/Dockerfile
|
- dockerfile: docker/alpine
|
||||||
# goos: linux
|
goos: linux
|
||||||
# goarch: amd64
|
goarch: amd64
|
||||||
# ids:
|
ids:
|
||||||
# - infisical
|
- all-other-builds
|
||||||
# image_templates:
|
image_templates:
|
||||||
# - "infisical/cli:{{ .Version }}"
|
- "infisical/cli:{{ .Version }}"
|
||||||
# - "infisical/cli:latest"
|
- "infisical/cli:{{ .Major }}.{{ .Minor }}"
|
||||||
|
- "infisical/cli:{{ .Major }}"
|
||||||
|
- "infisical/cli:latest"
|
||||||
|
@ -2,7 +2,7 @@ ARG POSTHOG_HOST=https://app.posthog.com
|
|||||||
ARG POSTHOG_API_KEY=posthog-api-key
|
ARG POSTHOG_API_KEY=posthog-api-key
|
||||||
ARG INTERCOM_ID=intercom-id
|
ARG INTERCOM_ID=intercom-id
|
||||||
|
|
||||||
FROM node:16-alpine AS base
|
FROM node:20-alpine AS base
|
||||||
|
|
||||||
FROM base AS frontend-dependencies
|
FROM base AS frontend-dependencies
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ RUN npm ci --only-production
|
|||||||
|
|
||||||
COPY /backend .
|
COPY /backend .
|
||||||
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh
|
||||||
|
RUN npm i -D tsconfig-paths
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
# Production stage
|
# Production stage
|
||||||
@ -103,14 +104,17 @@ ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \
|
|||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
|
||||||
COPY --from=backend-runner /app /backend
|
COPY --from=backend-runner /app /backend
|
||||||
|
COPY --from=backend-runner /app/dist/services/smtp/templates /backend/dist/templates
|
||||||
|
|
||||||
COPY --from=frontend-runner /app ./backend/frontend-build
|
COPY --from=frontend-runner /app ./backend/frontend-build
|
||||||
|
|
||||||
|
|
||||||
ENV PORT 8080
|
ENV PORT 8080
|
||||||
|
ENV HOST=0.0.0.0
|
||||||
ENV HTTPS_ENABLED false
|
ENV HTTPS_ENABLED false
|
||||||
ENV NODE_ENV production
|
ENV NODE_ENV production
|
||||||
ENV STANDALONE_BUILD true
|
ENV STANDALONE_BUILD true
|
||||||
|
ENV STANDALONE_MODE true
|
||||||
WORKDIR /backend
|
WORKDIR /backend
|
||||||
|
|
||||||
ENV TELEMETRY_ENABLED true
|
ENV TELEMETRY_ENABLED true
|
||||||
@ -119,10 +123,8 @@ HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
|||||||
CMD node healthcheck.js
|
CMD node healthcheck.js
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
EXPOSE 443
|
||||||
|
|
||||||
USER non-root-user
|
USER non-root-user
|
||||||
|
|
||||||
CMD ["./standalone-entrypoint.sh"]
|
CMD ["./standalone-entrypoint.sh"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3
Makefile
3
Makefile
@ -7,6 +7,9 @@ push:
|
|||||||
up-dev:
|
up-dev:
|
||||||
docker-compose -f docker-compose.dev.yml up --build
|
docker-compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
up-pg-dev:
|
||||||
|
docker compose -f docker-compose.pg.yml up --build
|
||||||
|
|
||||||
i-dev:
|
i-dev:
|
||||||
infisical run -- docker-compose -f docker-compose.dev.yml up --build
|
infisical run -- docker-compose -f docker-compose.dev.yml up --build
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ Note that this security address should be used only for undisclosed vulnerabilit
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview).
|
Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/getting-started).
|
||||||
|
|
||||||
Not sure where to get started? You can:
|
Not sure where to get started? You can:
|
||||||
|
|
||||||
|
11
backend-mongo/.dockerignore
Normal file
11
backend-mongo/.dockerignore
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
.env.*
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
Dockerfile
|
||||||
|
.dockerignore
|
||||||
|
docker-compose.*
|
||||||
|
.DS_Store
|
||||||
|
*.swp
|
||||||
|
*~
|
2
backend-mongo/.eslintignore
Normal file
2
backend-mongo/.eslintignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
built
|
33
backend-mongo/Dockerfile
Normal file
33
backend-mongo/Dockerfile
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# Build stage
|
||||||
|
FROM node:16-alpine AS build
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only-production
|
||||||
|
|
||||||
|
COPY . .
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Production stage
|
||||||
|
FROM node:16-alpine
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ENV npm_config_cache /home/node/.npm
|
||||||
|
|
||||||
|
COPY package*.json ./
|
||||||
|
RUN npm ci --only-production && npm cache clean --force
|
||||||
|
|
||||||
|
COPY --from=build /app .
|
||||||
|
|
||||||
|
RUN apk add --no-cache bash curl && curl -1sLf \
|
||||||
|
'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \
|
||||||
|
&& apk add infisical=0.8.1 && apk add --no-cache git
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=10s --timeout=3s --start-period=10s \
|
||||||
|
CMD node healthcheck.js
|
||||||
|
|
||||||
|
EXPOSE 4000
|
||||||
|
|
||||||
|
CMD ["node", "build/index.js"]
|
Before Width: | Height: | Size: 493 KiB After Width: | Height: | Size: 493 KiB |
6
backend-mongo/nodemon.json
Normal file
6
backend-mongo/nodemon.json
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"watch": ["src"],
|
||||||
|
"ext": ".ts,.js",
|
||||||
|
"ignore": [],
|
||||||
|
"exec": "ts-node ./src/index.ts"
|
||||||
|
}
|
32861
backend-mongo/package-lock.json
generated
Normal file
32861
backend-mongo/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
148
backend-mongo/package.json
Normal file
148
backend-mongo/package.json
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"@aws-sdk/client-secrets-manager": "^3.319.0",
|
||||||
|
"@casl/ability": "^6.5.0",
|
||||||
|
"@casl/mongoose": "^7.2.1",
|
||||||
|
"@godaddy/terminus": "^4.12.0",
|
||||||
|
"@node-saml/passport-saml": "^4.0.4",
|
||||||
|
"@octokit/rest": "^19.0.5",
|
||||||
|
"@sentry/node": "^7.77.0",
|
||||||
|
"@sentry/tracing": "^7.48.0",
|
||||||
|
"@serdnam/pino-cloudwatch-transport": "^1.0.4",
|
||||||
|
"@types/crypto-js": "^4.1.1",
|
||||||
|
"@types/libsodium-wrappers": "^0.7.10",
|
||||||
|
"@ucast/mongo2js": "^1.3.4",
|
||||||
|
"ajv": "^8.12.0",
|
||||||
|
"argon2": "^0.30.3",
|
||||||
|
"aws-sdk": "^2.1364.0",
|
||||||
|
"axios": "^1.6.0",
|
||||||
|
"axios-retry": "^3.4.0",
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
|
"bigint-conversion": "^2.4.0",
|
||||||
|
"cookie-parser": "^1.4.6",
|
||||||
|
"cors": "^2.8.5",
|
||||||
|
"crypto-js": "^4.2.0",
|
||||||
|
"dotenv": "^16.0.1",
|
||||||
|
"express": "^4.18.1",
|
||||||
|
"express-async-errors": "^3.1.1",
|
||||||
|
"express-rate-limit": "^6.7.0",
|
||||||
|
"express-validator": "^6.14.2",
|
||||||
|
"handlebars": "^4.7.7",
|
||||||
|
"helmet": "^5.1.1",
|
||||||
|
"infisical-node": "^1.2.1",
|
||||||
|
"ioredis": "^5.3.2",
|
||||||
|
"jmespath": "^0.16.0",
|
||||||
|
"js-yaml": "^4.1.0",
|
||||||
|
"jsonwebtoken": "^9.0.0",
|
||||||
|
"jsrp": "^0.2.4",
|
||||||
|
"libsodium-wrappers": "^0.7.10",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"mongoose": "^7.4.1",
|
||||||
|
"mysql2": "^3.6.2",
|
||||||
|
"nanoid": "^3.3.6",
|
||||||
|
"node-cache": "^5.1.2",
|
||||||
|
"nodemailer": "^6.8.0",
|
||||||
|
"ora": "^5.4.1",
|
||||||
|
"passport": "^0.6.0",
|
||||||
|
"passport-github": "^1.1.0",
|
||||||
|
"passport-gitlab2": "^5.0.0",
|
||||||
|
"passport-google-oauth20": "^2.0.0",
|
||||||
|
"pg": "^8.11.3",
|
||||||
|
"pino": "^8.16.1",
|
||||||
|
"pino-http": "^8.5.1",
|
||||||
|
"posthog-node": "^2.6.0",
|
||||||
|
"probot": "^12.3.3",
|
||||||
|
"query-string": "^7.1.3",
|
||||||
|
"rate-limit-mongo": "^2.3.2",
|
||||||
|
"rimraf": "^3.0.2",
|
||||||
|
"swagger-ui-express": "^4.6.2",
|
||||||
|
"tweetnacl": "^1.0.3",
|
||||||
|
"tweetnacl-util": "^0.15.1",
|
||||||
|
"typescript": "^4.9.3",
|
||||||
|
"utility-types": "^3.10.0",
|
||||||
|
"zod": "^3.22.3"
|
||||||
|
},
|
||||||
|
"overrides": {
|
||||||
|
"rate-limit-mongo": {
|
||||||
|
"mongodb": "5.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"name": "infisical-api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "src/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node build/index.js",
|
||||||
|
"dev": "nodemon index.js",
|
||||||
|
"swagger-autogen": "node ./swagger/index.ts",
|
||||||
|
"build": "rimraf ./build && tsc && cp -R ./src/templates ./build && cp -R ./src/data ./build",
|
||||||
|
"lint": "eslint . --ext .ts",
|
||||||
|
"lint-and-fix": "eslint . --ext .ts --fix",
|
||||||
|
"lint-staged": "lint-staged",
|
||||||
|
"pretest": "docker compose -f test-resources/docker-compose.test.yml up -d",
|
||||||
|
"test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles; npm run posttest",
|
||||||
|
"test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json",
|
||||||
|
"posttest": "docker compose -f test-resources/docker-compose.test.yml down"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/Infisical/infisical-api.git"
|
||||||
|
},
|
||||||
|
"author": "",
|
||||||
|
"license": "ISC",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/Infisical/infisical-api/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/Infisical/infisical-api#readme",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@jest/globals": "^29.3.1",
|
||||||
|
"@posthog/plugin-scaffold": "^1.3.4",
|
||||||
|
"@swc/core": "^1.3.99",
|
||||||
|
"@swc/helpers": "^0.5.3",
|
||||||
|
"@types/bcrypt": "^5.0.0",
|
||||||
|
"@types/bcryptjs": "^2.4.2",
|
||||||
|
"@types/bull": "^4.10.0",
|
||||||
|
"@types/cookie-parser": "^1.4.3",
|
||||||
|
"@types/cors": "^2.8.12",
|
||||||
|
"@types/express": "^4.17.14",
|
||||||
|
"@types/jest": "^29.5.0",
|
||||||
|
"@types/jmespath": "^0.15.1",
|
||||||
|
"@types/jsonwebtoken": "^8.5.9",
|
||||||
|
"@types/lodash": "^4.14.191",
|
||||||
|
"@types/node": "^18.11.3",
|
||||||
|
"@types/nodemailer": "^6.4.6",
|
||||||
|
"@types/passport": "^1.0.12",
|
||||||
|
"@types/pg": "^8.10.7",
|
||||||
|
"@types/picomatch": "^2.3.0",
|
||||||
|
"@types/pino": "^7.0.5",
|
||||||
|
"@types/supertest": "^2.0.12",
|
||||||
|
"@types/swagger-jsdoc": "^6.0.1",
|
||||||
|
"@types/swagger-ui-express": "^4.1.3",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
||||||
|
"@typescript-eslint/parser": "^5.40.1",
|
||||||
|
"cross-env": "^7.0.3",
|
||||||
|
"eslint": "^8.26.0",
|
||||||
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
|
"install": "^0.13.0",
|
||||||
|
"jest": "^29.3.1",
|
||||||
|
"jest-junit": "^15.0.0",
|
||||||
|
"nodemon": "^2.0.19",
|
||||||
|
"npm": "^8.19.3",
|
||||||
|
"pino-pretty": "^10.2.3",
|
||||||
|
"regenerator-runtime": "^0.14.0",
|
||||||
|
"smee-client": "^1.2.3",
|
||||||
|
"supertest": "^6.3.3",
|
||||||
|
"swagger-autogen": "^2.23.5",
|
||||||
|
"ts-jest": "^29.0.3",
|
||||||
|
"ts-node": "^10.9.1"
|
||||||
|
},
|
||||||
|
"jest-junit": {
|
||||||
|
"outputDirectory": "reports",
|
||||||
|
"outputName": "jest-junit.xml",
|
||||||
|
"ancestorSeparator": " › ",
|
||||||
|
"uniqueOutputName": "false",
|
||||||
|
"suiteNameTemplate": "{filepath}",
|
||||||
|
"classNameTemplate": "{classname}",
|
||||||
|
"titleTemplate": "{title}"
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -6,6 +6,9 @@ export const client = new InfisicalClient({
|
|||||||
token: process.env.INFISICAL_TOKEN!
|
token: process.env.INFISICAL_TOKEN!
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const getIsMigrationMode = async () =>
|
||||||
|
(await client.getSecret("MIGRATION_MODE")).secretValue === "true";
|
||||||
|
|
||||||
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
export const getPort = async () => (await client.getSecret("PORT")).secretValue || 4000;
|
||||||
export const getEncryptionKey = async () => {
|
export const getEncryptionKey = async () => {
|
||||||
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
const secretValue = (await client.getSecret("ENCRYPTION_KEY")).secretValue;
|
@ -3,11 +3,11 @@ import { IServerConfig, ServerConfig } from "../models/serverConfig";
|
|||||||
let serverConfig: IServerConfig;
|
let serverConfig: IServerConfig;
|
||||||
|
|
||||||
export const serverConfigInit = async () => {
|
export const serverConfigInit = async () => {
|
||||||
const cfg = await ServerConfig.findOne({});
|
const cfg = await ServerConfig.findOne({}).lean();
|
||||||
if (!cfg) {
|
if (!cfg) {
|
||||||
const cfg = new ServerConfig();
|
const cfg = new ServerConfig();
|
||||||
await cfg.save();
|
await cfg.save();
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
} else {
|
} else {
|
||||||
serverConfig = cfg;
|
serverConfig = cfg;
|
||||||
}
|
}
|
||||||
@ -19,6 +19,6 @@ export const getServerConfig = () => serverConfig;
|
|||||||
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
export const updateServerConfig = async (data: Partial<IServerConfig>) => {
|
||||||
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
const cfg = await ServerConfig.findByIdAndUpdate(serverConfig._id, data, { new: true });
|
||||||
if (!cfg) throw new Error("Failed to update server config");
|
if (!cfg) throw new Error("Failed to update server config");
|
||||||
serverConfig = cfg;
|
serverConfig = cfg.toObject();
|
||||||
return serverConfig;
|
return serverConfig;
|
||||||
};
|
};
|
@ -1,5 +1,5 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { getHttpsEnabled } from "../../config";
|
import { getHttpsEnabled, getIsMigrationMode } from "../../config";
|
||||||
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
import { getServerConfig, updateServerConfig as setServerConfig } from "../../config/serverConfig";
|
||||||
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
import { initializeDefaultOrg, issueAuthTokens } from "../../helpers";
|
||||||
import { validateRequest } from "../../helpers/validation";
|
import { validateRequest } from "../../helpers/validation";
|
||||||
@ -8,9 +8,10 @@ import { TelemetryService } from "../../services";
|
|||||||
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors";
|
||||||
import * as reqValidator from "../../validation/admin";
|
import * as reqValidator from "../../validation/admin";
|
||||||
|
|
||||||
export const getServerConfigInfo = (_req: Request, res: Response) => {
|
export const getServerConfigInfo = async (_req: Request, res: Response) => {
|
||||||
const config = getServerConfig();
|
const config = getServerConfig();
|
||||||
return res.send({ config });
|
const isMigrationModeOn = await getIsMigrationMode();
|
||||||
|
return res.send({ config: { ...config, isMigrationModeOn } });
|
||||||
};
|
};
|
||||||
|
|
||||||
export const updateServerConfig = async (req: Request, res: Response) => {
|
export const updateServerConfig = async (req: Request, res: Response) => {
|
@ -2,7 +2,7 @@ import { Request, Response } from "express";
|
|||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import { standardRequest } from "../../config/request";
|
import { standardRequest } from "../../config/request";
|
||||||
import { getApps, getTeams, revokeAccess } from "../../integrations";
|
import { getApps, getTeams, revokeAccess } from "../../integrations";
|
||||||
import { Bot, IntegrationAuth, Workspace } from "../../models";
|
import { Bot, IIntegrationAuth, Integration, IntegrationAuth, Workspace } from "../../models";
|
||||||
import { EventType } from "../../ee/models";
|
import { EventType } from "../../ee/models";
|
||||||
import { IntegrationService } from "../../services";
|
import { IntegrationService } from "../../services";
|
||||||
import { EEAuditLogService } from "../../ee/services";
|
import { EEAuditLogService } from "../../ee/services";
|
||||||
@ -130,7 +130,6 @@ export const oAuthExchange = async (req: Request, res: Response) => {
|
|||||||
export const saveIntegrationToken = async (req: Request, res: Response) => {
|
export const saveIntegrationToken = async (req: Request, res: Response) => {
|
||||||
// TODO: refactor
|
// TODO: refactor
|
||||||
// TODO: check if access token is valid for each integration
|
// TODO: check if access token is valid for each integration
|
||||||
let integrationAuth;
|
|
||||||
const {
|
const {
|
||||||
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
|
body: { workspaceId, integration, url, accessId, namespace, accessToken, refreshToken }
|
||||||
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
|
} = await validateRequest(reqValidator.SaveIntegrationAccessTokenV1, req);
|
||||||
@ -152,31 +151,21 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
if (!bot) throw new Error("Bot must be enabled to save integration access token");
|
if (!bot) throw new Error("Bot must be enabled to save integration access token");
|
||||||
|
|
||||||
integrationAuth = await IntegrationAuth.findOneAndUpdate(
|
let integrationAuth = await new IntegrationAuth({
|
||||||
{
|
workspace: new Types.ObjectId(workspaceId),
|
||||||
workspace: new Types.ObjectId(workspaceId),
|
integration,
|
||||||
integration
|
url,
|
||||||
},
|
namespace,
|
||||||
{
|
algorithm: ALGORITHM_AES_256_GCM,
|
||||||
workspace: new Types.ObjectId(workspaceId),
|
keyEncoding: ENCODING_SCHEME_UTF8,
|
||||||
integration,
|
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
||||||
url,
|
? {
|
||||||
namespace,
|
metadata: {
|
||||||
algorithm: ALGORITHM_AES_256_GCM,
|
authMethod: "serviceAccount"
|
||||||
keyEncoding: ENCODING_SCHEME_UTF8,
|
|
||||||
...(integration === INTEGRATION_GCP_SECRET_MANAGER
|
|
||||||
? {
|
|
||||||
metadata: {
|
|
||||||
authMethod: "serviceAccount"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
: {})
|
}
|
||||||
},
|
: {})
|
||||||
{
|
}).save();
|
||||||
new: true,
|
|
||||||
upsert: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
// encrypt and save integration access details
|
// encrypt and save integration access details
|
||||||
if (refreshToken) {
|
if (refreshToken) {
|
||||||
@ -188,12 +177,12 @@ export const saveIntegrationToken = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
// encrypt and save integration access details
|
// encrypt and save integration access details
|
||||||
if (accessId || accessToken) {
|
if (accessId || accessToken) {
|
||||||
integrationAuth = await IntegrationService.setIntegrationAuthAccess({
|
integrationAuth = (await IntegrationService.setIntegrationAuthAccess({
|
||||||
integrationAuthId: integrationAuth._id.toString(),
|
integrationAuthId: integrationAuth._id.toString(),
|
||||||
accessId,
|
accessId,
|
||||||
accessToken,
|
accessToken,
|
||||||
accessExpiresAt: undefined
|
accessExpiresAt: undefined
|
||||||
});
|
})) as IIntegrationAuth;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!integrationAuth) throw new Error("Failed to save integration access token");
|
if (!integrationAuth) throw new Error("Failed to save integration access token");
|
||||||
@ -1208,13 +1197,64 @@ export const getIntegrationAuthTeamCityBuildConfigs = async (req: Request, res:
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete all integration authorizations and integrations for workspace with id [workspaceId]
|
||||||
|
* with integration name [integration]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const deleteIntegrationAuths = async (req: Request, res: Response) => {
|
||||||
|
const {
|
||||||
|
query: { integration, workspaceId }
|
||||||
|
} = await validateRequest(reqValidator.DeleteIntegrationAuthsV1, req);
|
||||||
|
|
||||||
|
const { permission } = await getAuthDataProjectPermissions({
|
||||||
|
authData: req.authData,
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Delete,
|
||||||
|
ProjectPermissionSub.Integrations
|
||||||
|
);
|
||||||
|
|
||||||
|
const integrationAuths = await IntegrationAuth.deleteMany({
|
||||||
|
integration,
|
||||||
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
const integrations = await Integration.deleteMany({
|
||||||
|
integration,
|
||||||
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
|
});
|
||||||
|
|
||||||
|
await EEAuditLogService.createAuditLog(
|
||||||
|
req.authData,
|
||||||
|
{
|
||||||
|
type: EventType.UNAUTHORIZE_INTEGRATION,
|
||||||
|
metadata: {
|
||||||
|
integration
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
return res.status(200).send({
|
||||||
|
integrationAuths,
|
||||||
|
integrations
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete integration authorization with id [integrationAuthId]
|
* Delete integration authorization with id [integrationAuthId]
|
||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteIntegrationAuth = async (req: Request, res: Response) => {
|
export const deleteIntegrationAuthById = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
params: { integrationAuthId }
|
params: { integrationAuthId }
|
||||||
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);
|
} = await validateRequest(reqValidator.DeleteIntegrationAuthV1, req);
|
@ -251,6 +251,21 @@ export const deleteIntegration = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (!deletedIntegration) throw new Error("Failed to find integration");
|
if (!deletedIntegration) throw new Error("Failed to find integration");
|
||||||
|
|
||||||
|
const numOtherIntegrationsUsingSameAuth = await Integration.countDocuments({
|
||||||
|
integrationAuth: deletedIntegration.integrationAuth,
|
||||||
|
_id: {
|
||||||
|
$nin: [deletedIntegration._id]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (numOtherIntegrationsUsingSameAuth === 0) {
|
||||||
|
// no other integrations are using the same integration auth
|
||||||
|
// -> delete integration auth associated with the integration being deleted
|
||||||
|
await IntegrationAuth.deleteOne({
|
||||||
|
_id: deletedIntegration.integrationAuth
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
await EEAuditLogService.createAuditLog(
|
await EEAuditLogService.createAuditLog(
|
||||||
req.authData,
|
req.authData,
|
@ -111,11 +111,17 @@ export const createSecretImp = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: new Types.ObjectId(workspaceId)
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Create,
|
ProjectPermissionActions.Create,
|
||||||
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: directory })
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment: secretImport.environment, secretPath: secretImport.secretPath })
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const folders = await Folder.findOne({
|
const folders = await Folder.findOne({
|
||||||
@ -323,7 +329,7 @@ export const updateSecretImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Edit,
|
ProjectPermissionActions.Edit,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -331,6 +337,13 @@ export const updateSecretImport = async (req: Request, res: Response) => {
|
|||||||
secretPath
|
secretPath
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
secretImports.forEach(({ environment, secretPath }) => {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath })
|
||||||
|
);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const orderBefore = importSecDoc.imports;
|
const orderBefore = importSecDoc.imports;
|
||||||
@ -453,7 +466,7 @@ export const deleteSecretImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Delete,
|
ProjectPermissionActions.Delete,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -620,7 +633,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: new Types.ObjectId(workspaceId)
|
workspaceId: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
||||||
@ -677,7 +690,7 @@ export const getAllSecretsFromImport = async (req: Request, res: Response) => {
|
|||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
workspaceId: importSecDoc.workspace
|
workspaceId: importSecDoc.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
ForbiddenError.from(permission).throwUnlessCan(
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
ProjectPermissionActions.Read,
|
ProjectPermissionActions.Read,
|
||||||
subject(ProjectPermissionSub.Secrets, {
|
subject(ProjectPermissionSub.Secrets, {
|
@ -60,6 +60,52 @@ const packageUniversalAuthClientSecretData = (identityUniversalAuthClientSecret:
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const renewAccessToken = async (req: Request, res: Response) => {
|
export const renewAccessToken = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Renew access token'
|
||||||
|
#swagger.description = 'Renew access token'
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"accessToken": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Access token to renew",
|
||||||
|
"example": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"accessToken": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "(Same) Access token after successful renewal"
|
||||||
|
},
|
||||||
|
"expiresIn": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "TTL of access token in seconds"
|
||||||
|
},
|
||||||
|
"tokenType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Type of access token (e.g. Bearer)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Access token and its details"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
body: {
|
body: {
|
||||||
accessToken
|
accessToken
|
||||||
@ -83,9 +129,14 @@ export const renewAccessToken = async (req: Request, res: Response) => {
|
|||||||
accessTokenTTL,
|
accessTokenTTL,
|
||||||
accessTokenLastRenewedAt,
|
accessTokenLastRenewedAt,
|
||||||
accessTokenMaxTTL,
|
accessTokenMaxTTL,
|
||||||
createdAt: accessTokenCreatedAt
|
createdAt: accessTokenCreatedAt,
|
||||||
|
accessTokenNumUses,
|
||||||
|
accessTokenNumUsesLimit
|
||||||
} = identityAccessToken;
|
} = identityAccessToken;
|
||||||
|
|
||||||
|
if (accessTokenNumUses >= accessTokenNumUsesLimit) {
|
||||||
|
throw BadRequestError({ message: "Unable to renew because access token number of uses limit reached" })
|
||||||
|
}
|
||||||
|
|
||||||
// ttl check
|
// ttl check
|
||||||
if (accessTokenTTL > 0) {
|
if (accessTokenTTL > 0) {
|
||||||
@ -150,6 +201,57 @@ export const renewAccessToken = async (req: Request, res: Response) => {
|
|||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const loginIdentityUniversalAuth = async (req: Request, res: Response) => {
|
export const loginIdentityUniversalAuth = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Login with Universal Auth'
|
||||||
|
#swagger.description = 'Login with Universal Auth'
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Client ID for identity to login with Universal Auth",
|
||||||
|
"example": "..."
|
||||||
|
},
|
||||||
|
"clientSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Client Secret for identity to login with Universal Auth",
|
||||||
|
"example": "..."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"accessToken": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Access token issued after successful login"
|
||||||
|
},
|
||||||
|
"expiresIn": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "TTL of access token in seconds"
|
||||||
|
},
|
||||||
|
"tokenType": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Type of access token (e.g. Bearer)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Access token and its details"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
body: {
|
body: {
|
||||||
clientId,
|
clientId,
|
||||||
@ -303,7 +405,105 @@ export const loginIdentityUniversalAuth = async (req: Request, res: Response) =>
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addIdentityUniversalAuth = async (req: Request, res: Response) => {
|
/**
|
||||||
|
* Attach identity universal auth method onto identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
export const attachIdentityUniversalAuth = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Attach Universal Auth configuration onto identity'
|
||||||
|
#swagger.description = 'Attach Universal Auth configuration onto identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity to attach Universal Auth onto",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientSecretTrustedIps": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
"properties": {
|
||||||
|
"ipAddress": {
|
||||||
|
type: "string",
|
||||||
|
description: "IP address to trust",
|
||||||
|
default: "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.",
|
||||||
|
"example": "...",
|
||||||
|
"default": [{ ipAddress: "0.0.0.0/0" }]
|
||||||
|
},
|
||||||
|
"accessTokenTTL": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.",
|
||||||
|
"example": "...",
|
||||||
|
"default": 100
|
||||||
|
},
|
||||||
|
"accessTokenMaxTTL": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.",
|
||||||
|
"example": "...",
|
||||||
|
"default": 2592000
|
||||||
|
},
|
||||||
|
"accessTokenNumUsesLimit": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.",
|
||||||
|
"example": "...",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"accessTokenTrustedIps": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
"properties": {
|
||||||
|
"ipAddress": {
|
||||||
|
type: "string",
|
||||||
|
description: "IP address to trust",
|
||||||
|
default: "0.0.0.0/0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.",
|
||||||
|
"example": "...",
|
||||||
|
"default": [{ ipAddress: "0.0.0.0/0" }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityUniversalAuth": {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuth'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of attached Universal Auth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId },
|
params: { identityId },
|
||||||
body: {
|
body: {
|
||||||
@ -350,7 +550,7 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
// validate trusted ips
|
// validate trusted ips
|
||||||
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
const reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -364,7 +564,7 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
const reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -414,7 +614,98 @@ export const addIdentityUniversalAuth = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update identity universal auth method on identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
export const updateIdentityUniversalAuth = async (req: Request, res: Response) => {
|
export const updateIdentityUniversalAuth = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Update Universal Auth configuration on identity'
|
||||||
|
#swagger.description = 'Update Universal Auth configuration on identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity to update Universal Auth on",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientSecretTrustedIps": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
"properties": {
|
||||||
|
"ipAddress": {
|
||||||
|
type: "string",
|
||||||
|
description: "IP address to trust"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "List of IPs or CIDR ranges that the Client Secret can be used from together with the Client ID to get back an access token. By default, Client Secrets are given the 0.0.0.0/0 entry representing all possible IPv4 addresses.",
|
||||||
|
"example": "...",
|
||||||
|
},
|
||||||
|
"accessTokenTTL": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The incremental lifetime for an acccess token in seconds; a value of 0 implies an infinite incremental lifetime.",
|
||||||
|
"example": "...",
|
||||||
|
},
|
||||||
|
"accessTokenMaxTTL": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum lifetime for an acccess token in seconds; a value of 0 implies an infinite maximum lifetime.",
|
||||||
|
"example": "...",
|
||||||
|
},
|
||||||
|
"accessTokenNumUsesLimit": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum number of times that an access token can be used; a value of 0 implies infinite number of uses.",
|
||||||
|
"example": "...",
|
||||||
|
},
|
||||||
|
"accessTokenTrustedIps": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
type: "object",
|
||||||
|
"properties": {
|
||||||
|
"ipAddress": {
|
||||||
|
type: "string",
|
||||||
|
description: "IP address to trust"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "List of IPs or CIDR ranges that access tokens can be used from. By default, each token is given the 0.0.0.0/0 entry representing all possible IPv4 addresses.",
|
||||||
|
"example": "...",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityUniversalAuth": {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuth'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of updated Universal Auth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId },
|
params: { identityId },
|
||||||
body: {
|
body: {
|
||||||
@ -459,7 +750,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
let reformattedClientSecretTrustedIps;
|
let reformattedClientSecretTrustedIps;
|
||||||
if (clientSecretTrustedIps) {
|
if (clientSecretTrustedIps) {
|
||||||
reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
reformattedClientSecretTrustedIps = clientSecretTrustedIps.map((clientSecretTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && clientSecretTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (clientSecretTrustedIp.ipAddress !== "0.0.0.0/0" && clientSecretTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -476,7 +767,7 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
let reformattedAccessTokenTrustedIps;
|
let reformattedAccessTokenTrustedIps;
|
||||||
if (accessTokenTrustedIps) {
|
if (accessTokenTrustedIps) {
|
||||||
reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
reformattedAccessTokenTrustedIps = accessTokenTrustedIps.map((accessTokenTrustedIp) => {
|
||||||
if (!plan.ipAllowlisting && accessTokenTrustedIp.ipAddress !== "0.0.0.0/0") return res.status(400).send({
|
if (!plan.ipAllowlisting && (accessTokenTrustedIp.ipAddress !== "0.0.0.0/0" && accessTokenTrustedIp.ipAddress !== "::/0")) return res.status(400).send({
|
||||||
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
message: "Failed to add IP access range to service token due to plan restriction. Upgrade plan to add IP access range."
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -526,7 +817,43 @@ export const updateIdentityUniversalAuth = async (req: Request, res: Response) =
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return identity universal auth method on identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
export const getIdentityUniversalAuth = async (req: Request, res: Response) => {
|
export const getIdentityUniversalAuth = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Retrieve Universal Auth configuration on identity'
|
||||||
|
#swagger.description = 'Retrieve Universal Auth configuration on identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity to retrieve Universal Auth on",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityUniversalAuth": {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuth'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of retrieved Universal Auth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId }
|
params: { identityId }
|
||||||
} = await validateRequest(reqValidator.GetUniversalAuthForIdentityV1, req);
|
} = await validateRequest(reqValidator.GetUniversalAuthForIdentityV1, req);
|
||||||
@ -577,7 +904,77 @@ export const getIdentityUniversalAuth = async (req: Request, res: Response) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create client secret for identity universal auth method on identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
export const createUniversalAuthClientSecret = async (req: Request, res: Response) => {
|
export const createUniversalAuthClientSecret = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Create Universal Auth Client Secret for identity'
|
||||||
|
#swagger.description = 'Create Universal Auth Client Secret for identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity to create Universal Auth Client Secret for",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"description": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A description for the Client Secret to create.",
|
||||||
|
"example": "..."
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The time-to-live for the Client Secret to create. By default, the TTL will be set to 0 which implies that the Client Secret will never expire; a value of 0 implies an infinite lifetime.",
|
||||||
|
"example": "...",
|
||||||
|
"default": 0
|
||||||
|
},
|
||||||
|
"numUsesLimit": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The maximum number of times that the Client Secret can be used together with the Client ID to get back an access token; a value of 0 implies infinite number of uses.",
|
||||||
|
"example": "...",
|
||||||
|
"default": 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The created Client Secret"
|
||||||
|
},
|
||||||
|
"clientSecretData": {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuthClientSecretData'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the created Client Secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId },
|
params: { identityId },
|
||||||
body: {
|
body: {
|
||||||
@ -660,7 +1057,46 @@ export const createUniversalAuthClientSecret = async (req: Request, res: Respons
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getUniversalAuthClientSecrets = async (req: Request, res: Response) => {
|
/**
|
||||||
|
* Return list of client secret details for identity universal auth method on identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
|
export const getUniversalAuthClientSecretsDetails = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'List Universal Auth Client Secrets for identity'
|
||||||
|
#swagger.description = 'List Universal Auth Client Secrets for identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity for which to get Client Secrets for",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientSecretData": {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuthClientSecretData'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the Client Secrets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId }
|
params: { identityId }
|
||||||
} = await validateRequest(reqValidator.GetUniversalAuthClientSecretsV1, req);
|
} = await validateRequest(reqValidator.GetUniversalAuthClientSecretsV1, req);
|
||||||
@ -720,7 +1156,50 @@ export const getUniversalAuthClientSecrets = async (req: Request, res: Response)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revoke client secret for identity universal auth method on identity with id [identityId]
|
||||||
|
* @param req
|
||||||
|
* @param res
|
||||||
|
*/
|
||||||
export const revokeUniversalAuthClientSecret = async (req: Request, res: Response) => {
|
export const revokeUniversalAuthClientSecret = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Revoke Universal Auth Client Secret for identity'
|
||||||
|
#swagger.description = 'Revoke Universal Auth Client Secret for identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity under which Client Secret was issued for",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['clientSecretId'] = {
|
||||||
|
"description": "ID of Client Secret to revoke",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"clientSecretData": {
|
||||||
|
$ref: '#/definitions/IdentityUniversalAuthClientSecretData'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the revoked Client Secret"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId, clientSecretId }
|
params: { identityId, clientSecretId }
|
||||||
} = await validateRequest(reqValidator.RevokeUniversalAuthClientSecretV1, req);
|
} = await validateRequest(reqValidator.RevokeUniversalAuthClientSecretV1, req);
|
@ -1,9 +1,13 @@
|
|||||||
import { Request, Response } from "express";
|
import { Request, Response } from "express";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
import {
|
import {
|
||||||
IdentityMembershipOrg,
|
IWorkspace,
|
||||||
Membership,
|
Identity,
|
||||||
|
IdentityMembership,
|
||||||
|
IdentityMembershipOrg,
|
||||||
|
Membership,
|
||||||
MembershipOrg,
|
MembershipOrg,
|
||||||
|
User,
|
||||||
Workspace
|
Workspace
|
||||||
} from "../../models";
|
} from "../../models";
|
||||||
import { Role } from "../../ee/models";
|
import { Role } from "../../ee/models";
|
||||||
@ -33,11 +37,12 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
*/
|
*/
|
||||||
export const getOrganizationMemberships = async (req: Request, res: Response) => {
|
export const getOrganizationMemberships = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Return organization memberships'
|
#swagger.summary = 'Return organization user memberships'
|
||||||
#swagger.description = 'Return organization memberships'
|
#swagger.description = 'Return organization user memberships'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['organizationId'] = {
|
#swagger.parameters['organizationId'] = {
|
||||||
@ -94,11 +99,12 @@ export const getOrganizationMemberships = async (req: Request, res: Response) =>
|
|||||||
*/
|
*/
|
||||||
export const updateOrganizationMembership = async (req: Request, res: Response) => {
|
export const updateOrganizationMembership = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Update organization membership'
|
#swagger.summary = 'Update organization user membership'
|
||||||
#swagger.description = 'Update organization membership'
|
#swagger.description = 'Update organization user membership'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['organizationId'] = {
|
#swagger.parameters['organizationId'] = {
|
||||||
@ -214,11 +220,12 @@ export const updateOrganizationMembership = async (req: Request, res: Response)
|
|||||||
*/
|
*/
|
||||||
export const deleteOrganizationMembership = async (req: Request, res: Response) => {
|
export const deleteOrganizationMembership = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Delete organization membership'
|
#swagger.summary = 'Delete organization user membership'
|
||||||
#swagger.description = 'Delete organization membership'
|
#swagger.description = 'Delete organization user membership'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['organizationId'] = {
|
#swagger.parameters['organizationId'] = {
|
||||||
@ -295,7 +302,8 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
#swagger.description = 'Return projects in organization that user is part of'
|
#swagger.description = 'Return projects in organization that user is part of'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['organizationId'] = {
|
#swagger.parameters['organizationId'] = {
|
||||||
@ -323,6 +331,7 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const {
|
const {
|
||||||
params: { organizationId }
|
params: { organizationId }
|
||||||
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
|
} = await validateRequest(reqValidator.GetOrgWorkspacesv2, req);
|
||||||
@ -348,13 +357,27 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) =>
|
|||||||
).map((w) => w._id.toString())
|
).map((w) => w._id.toString())
|
||||||
);
|
);
|
||||||
|
|
||||||
const workspaces = (
|
let workspaces: IWorkspace[] = [];
|
||||||
await Membership.find({
|
|
||||||
user: req.user._id
|
if (req.authData.authPayload instanceof Identity) {
|
||||||
}).populate("workspace")
|
workspaces = (
|
||||||
)
|
await IdentityMembership.find({
|
||||||
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
identity: req.authData.authPayload._id
|
||||||
.map((m) => m.workspace);
|
}).populate<{ workspace: IWorkspace }>("workspace")
|
||||||
|
)
|
||||||
|
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||||
|
.map((m) => m.workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.authData.authPayload instanceof User) {
|
||||||
|
workspaces = (
|
||||||
|
await Membership.find({
|
||||||
|
user: req.authData.authPayload._id
|
||||||
|
}).populate<{ workspace: IWorkspace }>("workspace")
|
||||||
|
)
|
||||||
|
.filter((m) => workspacesSet.has(m.workspace._id.toString()))
|
||||||
|
.map((m) => m.workspace);
|
||||||
|
}
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
||||||
workspaces
|
workspaces
|
||||||
@ -425,6 +448,40 @@ export const deleteOrganizationById = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getOrganizationIdentityMemberships = async (req: Request, res: Response) => {
|
export const getOrganizationIdentityMemberships = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Return organization identity memberships'
|
||||||
|
#swagger.description = 'Return organization identity memberships'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['organizationId'] = {
|
||||||
|
"description": "ID of organization",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityMemberships": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
$ref: "#/components/schemas/IdentityMembershipOrg"
|
||||||
|
},
|
||||||
|
"description": "Identity memberships of organization"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { organizationId }
|
params: { organizationId }
|
||||||
} = await validateRequest(reqValidator.GetOrgIdentityMembershipsV2, req);
|
} = await validateRequest(reqValidator.GetOrgIdentityMembershipsV2, req);
|
@ -13,7 +13,7 @@ import {
|
|||||||
ProjectPermissionSub,
|
ProjectPermissionSub,
|
||||||
getAuthDataProjectPermissions
|
getAuthDataProjectPermissions
|
||||||
} from "../../ee/services/ProjectRoleService";
|
} from "../../ee/services/ProjectRoleService";
|
||||||
import { ForbiddenError } from "@casl/ability";
|
import { ForbiddenError, subject } from "@casl/ability";
|
||||||
import { Types } from "mongoose";
|
import { Types } from "mongoose";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -86,6 +86,14 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
|
|||||||
ProjectPermissionSub.ServiceTokens
|
ProjectPermissionSub.ServiceTokens
|
||||||
);
|
);
|
||||||
|
|
||||||
|
scopes.forEach(({ environment, secretPath }) => {
|
||||||
|
ForbiddenError.from(permission).throwUnlessCan(
|
||||||
|
ProjectPermissionActions.Create,
|
||||||
|
subject(ProjectPermissionSub.Secrets, { environment, secretPath: secretPath })
|
||||||
|
);
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
const secret = crypto.randomBytes(16).toString("hex");
|
const secret = crypto.randomBytes(16).toString("hex");
|
||||||
const secretHash = await bcrypt.hash(secret, await getSaltRounds());
|
const secretHash = await bcrypt.hash(secret, await getSaltRounds());
|
||||||
|
|
@ -249,11 +249,12 @@ export const getWorkspaceServiceTokenData = async (req: Request, res: Response)
|
|||||||
*/
|
*/
|
||||||
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Return project memberships'
|
#swagger.summary = 'Return project user memberships'
|
||||||
#swagger.description = 'Return project memberships'
|
#swagger.description = 'Return project user memberships'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['workspaceId'] = {
|
#swagger.parameters['workspaceId'] = {
|
||||||
@ -312,11 +313,12 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const updateWorkspaceMembership = async (req: Request, res: Response) => {
|
export const updateWorkspaceMembership = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Update project membership'
|
#swagger.summary = 'Update project user membership'
|
||||||
#swagger.description = 'Update project membership'
|
#swagger.description = 'Update project user membership'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['workspaceId'] = {
|
#swagger.parameters['workspaceId'] = {
|
||||||
@ -340,7 +342,7 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
"properties": {
|
"properties": {
|
||||||
"role": {
|
"role": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Role of membership - either admin or member",
|
"description": "Role to update to for project membership",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -402,11 +404,12 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) =>
|
|||||||
*/
|
*/
|
||||||
export const deleteWorkspaceMembership = async (req: Request, res: Response) => {
|
export const deleteWorkspaceMembership = async (req: Request, res: Response) => {
|
||||||
/*
|
/*
|
||||||
#swagger.summary = 'Delete project membership'
|
#swagger.summary = 'Delete project user membership'
|
||||||
#swagger.description = 'Delete project membership'
|
#swagger.description = 'Delete project user membership'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['workspaceId'] = {
|
#swagger.parameters['workspaceId'] = {
|
||||||
@ -594,7 +597,60 @@ export const addIdentityToWorkspace = async (req: Request, res: Response) => {
|
|||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const updateIdentityWorkspaceRole = async (req: Request, res: Response) => {
|
export const updateIdentityWorkspaceRole = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Update project identity membership'
|
||||||
|
#swagger.description = 'Update project identity membership'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['workspaceId'] = {
|
||||||
|
"description": "ID of project",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity whose membership to update in project",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"role": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Role to update to for identity project membership",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityMembership": {
|
||||||
|
$ref: "#/components/schemas/IdentityMembership",
|
||||||
|
"description": "Updated identity membership"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { workspaceId, identityId },
|
params: { workspaceId, identityId },
|
||||||
body: {
|
body: {
|
||||||
@ -676,12 +732,48 @@ export const updateIdentityWorkspaceRole = async (req: Request, res: Response) =
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete identity with id [identityId] to workspace
|
* Delete identity with id [identityId] from workspace
|
||||||
* with id [workspaceId]
|
* with id [workspaceId]
|
||||||
* @param req
|
* @param req
|
||||||
* @param res
|
* @param res
|
||||||
*/
|
*/
|
||||||
export const deleteIdentityFromWorkspace = async (req: Request, res: Response) => {
|
export const deleteIdentityFromWorkspace = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Delete project identity membership'
|
||||||
|
#swagger.description = 'Delete project identity membership'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['workspaceId'] = {
|
||||||
|
"description": "ID of project",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity whose membership to delete in project",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityMembership": {
|
||||||
|
$ref: "#/components/schemas/IdentityMembership",
|
||||||
|
"description": "Deleted identity membership"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { workspaceId, identityId }
|
params: { workspaceId, identityId }
|
||||||
} = await validateRequest(reqValidator.DeleteIdentityFromWorkspaceV2, req);
|
} = await validateRequest(reqValidator.DeleteIdentityFromWorkspaceV2, req);
|
||||||
@ -732,7 +824,41 @@ export const deleteIdentityFromWorkspace = async (req: Request, res: Response) =
|
|||||||
* @param res
|
* @param res
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const getWorkspaceIdentityMemberships = async (req: Request, res: Response) => {
|
export const getWorkspaceIdentityMemberships = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Return project identity memberships'
|
||||||
|
#swagger.description = 'Return project identity memberships'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['workspaceId'] = {
|
||||||
|
"description": "ID of project",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identityMemberships": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
$ref: "#/components/schemas/IdentityMembership"
|
||||||
|
},
|
||||||
|
"description": "Identity memberships of project"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { workspaceId }
|
params: { workspaceId }
|
||||||
} = await validateRequest(reqValidator.GetWorkspaceIdentityMembersV2, req);
|
} = await validateRequest(reqValidator.GetWorkspaceIdentityMembersV2, req);
|
@ -348,7 +348,7 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const {
|
const {
|
||||||
query: { secretPath, environment, workspaceId, type, include_imports },
|
query: { secretPath, environment, workspaceId, type, include_imports, version },
|
||||||
params: { secretName }
|
params: { secretName }
|
||||||
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
|
} = await validateRequest(reqValidator.GetSecretByNameRawV3, req);
|
||||||
|
|
||||||
@ -371,7 +371,8 @@ export const getSecretByNameRaw = async (req: Request, res: Response) => {
|
|||||||
type,
|
type,
|
||||||
secretPath,
|
secretPath,
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
include_imports
|
include_imports,
|
||||||
|
version
|
||||||
});
|
});
|
||||||
|
|
||||||
const key = await BotService.getWorkspaceKeyWithBot({
|
const key = await BotService.getWorkspaceKeyWithBot({
|
||||||
@ -865,7 +866,7 @@ export const getSecrets = async (req: Request, res: Response) => {
|
|||||||
*/
|
*/
|
||||||
export const getSecretByName = async (req: Request, res: Response) => {
|
export const getSecretByName = async (req: Request, res: Response) => {
|
||||||
const {
|
const {
|
||||||
query: { secretPath, environment, workspaceId, type, include_imports },
|
query: { secretPath, environment, workspaceId, type, include_imports, version },
|
||||||
params: { secretName }
|
params: { secretName }
|
||||||
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
|
} = await validateRequest(reqValidator.GetSecretByNameV3, req);
|
||||||
|
|
||||||
@ -888,7 +889,8 @@ export const getSecretByName = async (req: Request, res: Response) => {
|
|||||||
type,
|
type,
|
||||||
secretPath,
|
secretPath,
|
||||||
authData: req.authData,
|
authData: req.authData,
|
||||||
include_imports
|
include_imports,
|
||||||
|
version
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(200).send({
|
return res.status(200).send({
|
@ -42,6 +42,58 @@ import { ForbiddenError } from "@casl/ability";
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const createIdentity = async (req: Request, res: Response) => {
|
export const createIdentity = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Create identity'
|
||||||
|
#swagger.description = 'Create identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of entity to create",
|
||||||
|
"example": "development"
|
||||||
|
},
|
||||||
|
"organizationId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID of organization where to create identity",
|
||||||
|
"example": "dev-environment"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Role to assume for organization membership",
|
||||||
|
"example": "no-access"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["name", "organizationId", "role"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identity": {
|
||||||
|
$ref: '#/definitions/Identity'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the created identity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
body: {
|
body: {
|
||||||
name,
|
name,
|
||||||
@ -120,6 +172,59 @@ export const createIdentity = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const updateIdentity = async (req: Request, res: Response) => {
|
export const updateIdentity = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Update identity'
|
||||||
|
#swagger.description = 'Update identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity to update",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.requestBody = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of entity to update to",
|
||||||
|
"example": "development"
|
||||||
|
},
|
||||||
|
"role": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Role to update to for organization membership",
|
||||||
|
"example": "no-access"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identity": {
|
||||||
|
$ref: '#/definitions/Identity'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the updated identity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId },
|
params: { identityId },
|
||||||
body: {
|
body: {
|
||||||
@ -242,6 +347,37 @@ export const createIdentity = async (req: Request, res: Response) => {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
export const deleteIdentity = async (req: Request, res: Response) => {
|
export const deleteIdentity = async (req: Request, res: Response) => {
|
||||||
|
/*
|
||||||
|
#swagger.summary = 'Delete identity'
|
||||||
|
#swagger.description = 'Delete identity'
|
||||||
|
|
||||||
|
#swagger.security = [{
|
||||||
|
"bearerAuth": []
|
||||||
|
}]
|
||||||
|
|
||||||
|
#swagger.parameters['identityId'] = {
|
||||||
|
"description": "ID of identity",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "path"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.responses[200] = {
|
||||||
|
content: {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"identity": {
|
||||||
|
$ref: '#/definitions/Identity'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": "Details of the deleted identity"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
const {
|
const {
|
||||||
params: { identityId }
|
params: { identityId }
|
||||||
} = await validateRequest(reqValidator.DeleteIdentityV1, req);
|
} = await validateRequest(reqValidator.DeleteIdentityV1, req);
|
@ -17,12 +17,12 @@ export const getSecretApprovalRequestCount = async (req: Request, res: Response)
|
|||||||
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
|
} = await validateRequest(reqValidator.getSecretApprovalRequestCount, req);
|
||||||
|
|
||||||
if (!(req.authData.authPayload instanceof User)) return;
|
if (!(req.authData.authPayload instanceof User)) return;
|
||||||
|
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: new Types.ObjectId(workspaceId)
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
const approvalRequestCount = await SecretApprovalRequest.aggregate([
|
const approvalRequestCount = await SecretApprovalRequest.aggregate([
|
||||||
@ -73,12 +73,12 @@ export const getSecretApprovalRequests = async (req: Request, res: Response) =>
|
|||||||
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
|
} = await validateRequest(reqValidator.getSecretApprovalRequests, req);
|
||||||
|
|
||||||
if (!(req.authData.authPayload instanceof User)) return;
|
if (!(req.authData.authPayload instanceof User)) return;
|
||||||
|
|
||||||
const membership = await Membership.findOne({
|
const membership = await Membership.findOne({
|
||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: new Types.ObjectId(workspaceId)
|
workspace: new Types.ObjectId(workspaceId)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
const query = {
|
const query = {
|
||||||
@ -168,13 +168,13 @@ export const getSecretApprovalRequestDetails = async (req: Request, res: Respons
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
// allow to fetch only if its admin or is the committer or approver
|
// allow to fetch only if its admin or is the committer or approver
|
||||||
if (
|
if (
|
||||||
membership.role !== "admin" &&
|
membership.role !== "admin" &&
|
||||||
secretApprovalRequest.committer !== membership.id &&
|
!secretApprovalRequest.committer.equals(membership.id) &&
|
||||||
!secretApprovalRequest.policy.approvers.find(
|
!secretApprovalRequest.policy.approvers.find(
|
||||||
(approverId) => approverId.toString() === membership._id.toString()
|
(approverId) => approverId.toString() === membership._id.toString()
|
||||||
)
|
)
|
||||||
@ -215,7 +215,7 @@ export const updateSecretApprovalReviewStatus = async (req: Request, res: Respon
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -257,7 +257,7 @@ export const mergeSecretApprovalRequest = async (req: Request, res: Response) =>
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
||||||
@ -307,7 +307,7 @@ export const updateSecretApprovalRequestStatus = async (req: Request, res: Respo
|
|||||||
user: req.authData.authPayload._id,
|
user: req.authData.authPayload._id,
|
||||||
workspace: secretApprovalRequest.workspace
|
workspace: secretApprovalRequest.workspace
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!membership) throw UnauthorizedRequestError();
|
if (!membership) throw UnauthorizedRequestError();
|
||||||
|
|
||||||
if (
|
if (
|
@ -62,15 +62,30 @@ export const getWorkspaceSecretSnapshots = async (req: Request, res: Response) =
|
|||||||
#swagger.description = 'Return project secret snapshots ids'
|
#swagger.description = 'Return project secret snapshots ids'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['workspaceId'] = {
|
#swagger.parameters['workspaceId'] = {
|
||||||
"description": "ID of project",
|
"description": "ID of project where to get secret snapshots for",
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['environment'] = {
|
||||||
|
"description": "Slug of environment where to get secret snapshots for",
|
||||||
|
"required": true,
|
||||||
|
"type": "string",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
|
||||||
|
#swagger.parameters['directory'] = {
|
||||||
|
"description": "Path where to get secret snapshots for like / or /foo/bar. Default is /",
|
||||||
|
"required": false,
|
||||||
|
"type": "string",
|
||||||
|
"in": "query"
|
||||||
|
}
|
||||||
|
|
||||||
#swagger.parameters['offset'] = {
|
#swagger.parameters['offset'] = {
|
||||||
"description": "Number of secret snapshots to skip",
|
"description": "Number of secret snapshots to skip",
|
||||||
"required": false,
|
"required": false,
|
||||||
@ -195,11 +210,12 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons
|
|||||||
#swagger.description = 'Roll back project secrets to those captured in a secret snapshot version.'
|
#swagger.description = 'Roll back project secrets to those captured in a secret snapshot version.'
|
||||||
|
|
||||||
#swagger.security = [{
|
#swagger.security = [{
|
||||||
"apiKeyAuth": []
|
"apiKeyAuth": [],
|
||||||
|
"bearerAuth": []
|
||||||
}]
|
}]
|
||||||
|
|
||||||
#swagger.parameters['workspaceId'] = {
|
#swagger.parameters['workspaceId'] = {
|
||||||
"description": "ID of project",
|
"description": "ID of project where to roll back",
|
||||||
"required": true,
|
"required": true,
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
@ -211,6 +227,14 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons
|
|||||||
"schema": {
|
"schema": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"environment": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Slug of environment where to roll back"
|
||||||
|
},
|
||||||
|
"directory": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path where to roll back for like / or /foo/bar. Default is /"
|
||||||
|
},
|
||||||
"version": {
|
"version": {
|
||||||
"type": "integer",
|
"type": "integer",
|
||||||
"description": "Version of secret snapshot to roll back to",
|
"description": "Version of secret snapshot to roll back to",
|
@ -8,7 +8,10 @@ export enum UserAgentType {
|
|||||||
WEB = "web",
|
WEB = "web",
|
||||||
CLI = "cli",
|
CLI = "cli",
|
||||||
K8_OPERATOR = "k8-operator",
|
K8_OPERATOR = "k8-operator",
|
||||||
OTHER = "other"
|
TERRAFORM = "terraform",
|
||||||
|
OTHER = "other",
|
||||||
|
PYTHON_SDK = "InfisicalPythonSDK",
|
||||||
|
NODE_SDK = "InfisicalNodeSDK"
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum EventType {
|
export enum EventType {
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user