Compare commits

..

94 Commits

Author SHA1 Message Date
c36aa3591a Merge branch 'main' of https://github.com/Infisical/infisical into main 2022-12-08 09:01:36 -05:00
58b252a9e9 Loosen email regex 2022-12-08 09:01:24 -05:00
dba4c03e37 Merge pull request #102 from Infisical/mv-turtle-patch-1
Update README.md
2022-12-07 23:49:35 -05:00
7b1be82bac Update README.md 2022-12-07 23:45:29 -05:00
3c449750d3 Merge pull request #92 from asharonbaltazar/feat-add-notif-timeout
Add Notification Timeout
2022-12-07 19:59:39 -05:00
006f61a0e8 Merge pull request #99 from reginaldbondoc/add-initial-quality-gate
Add PR gate workflows
2022-12-07 18:13:34 -05:00
ec85bfca04 Fix frontend build-arg 2022-12-07 23:45:19 +01:00
27353848c1 Add PR gate workflows 2022-12-07 23:25:41 +01:00
da6a8ccdea fix typo for layout 2022-12-07 16:45:45 -05:00
b5a4e42281 Merge pull request #98 from reginaldbondoc/main
Fix workspace type definition
2022-12-07 16:33:25 -05:00
1212b5a9db Change name 2022-12-07 22:23:47 +01:00
d99e21a91b Fix workspace type 2022-12-07 22:20:25 +01:00
112fc77a06 Merge branch 'main' of https://github.com/Infisical/infisical 2022-12-07 15:08:52 -05:00
c23be77738 Fixed the typescript error in Layout 2022-12-07 15:08:44 -05:00
0cea019bc2 Update push to docker action 2022-12-07 14:26:56 -05:00
1218dc09ed Merge pull request #93 from Infisical/snyk-upgrade-5c827737012080ebf6157c6e6fcd4f49
[Snyk] Upgrade typescript from 4.8.4 to 4.9.3
2022-12-07 13:47:22 -05:00
b89a221a5a Merge pull request #94 from Infisical/snyk-upgrade-5d7f8d449135ab93a65e39dda5bbc136
[Snyk] Upgrade @sentry/tracing from 7.17.4 to 7.19.0
2022-12-07 13:47:03 -05:00
c4124cc865 Merge branch 'main' into snyk-upgrade-5d7f8d449135ab93a65e39dda5bbc136 2022-12-07 13:46:50 -05:00
94b7a0aead Added another contributing option to readme 2022-12-07 13:44:11 -05:00
689f1d0d43 Merge pull request #95 from Infisical/snyk-upgrade-2f45d7571b1d2d04216e214a24b9e6c3
[Snyk] Upgrade @sentry/node from 7.17.4 to 7.19.0
2022-12-07 13:43:39 -05:00
c75c24d44e Merge pull request #96 from Infisical/snyk-upgrade-35bcf68242318cba0ddafd09b0bc335e
[Snyk] Upgrade express-rate-limit from 6.6.0 to 6.7.0
2022-12-07 13:43:26 -05:00
febdf48dea Merge pull request #97 from Infisical/snyk-upgrade-7100c673d3b4c2351515934460524fde
[Snyk] Upgrade mongoose from 6.7.1 to 6.7.2
2022-12-07 13:43:10 -05:00
688b383d8b Merge pull request #80 from reginaldbondoc/I-36-use-pre-built-frontend-image
I-36 Use pre-built frontend image instead of building Next.js app on boot
2022-12-07 13:36:43 -05:00
9436f40eac Merge pull request #90 from edgarrmondragon/feat/export-cmd
Add an `export` command
2022-12-07 13:35:26 -05:00
d45eff621b fix: upgrade mongoose from 6.7.1 to 6.7.2
Snyk has created this PR to upgrade mongoose from 6.7.1 to 6.7.2.

See this package in npm:
https://www.npmjs.com/package/mongoose

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-12-07 18:15:40 +00:00
761a60a216 fix: upgrade express-rate-limit from 6.6.0 to 6.7.0
Snyk has created this PR to upgrade express-rate-limit from 6.6.0 to 6.7.0.

See this package in npm:
https://www.npmjs.com/package/express-rate-limit

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-12-07 18:15:35 +00:00
0466bf4e3d fix: upgrade @sentry/node from 7.17.4 to 7.19.0
Snyk has created this PR to upgrade @sentry/node from 7.17.4 to 7.19.0.

See this package in npm:
https://www.npmjs.com/package/@sentry/node

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-12-07 18:15:31 +00:00
16a1366e6c fix: upgrade @sentry/tracing from 7.17.4 to 7.19.0
Snyk has created this PR to upgrade @sentry/tracing from 7.17.4 to 7.19.0.

See this package in npm:
https://www.npmjs.com/package/@sentry/tracing

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-12-07 18:15:27 +00:00
b06c8d241e fix: upgrade typescript from 4.8.4 to 4.9.3
Snyk has created this PR to upgrade typescript from 4.8.4 to 4.9.3.

See this package in npm:
https://www.npmjs.com/package/typescript

See this project in Snyk:
https://app.snyk.io/org/maidul98/project/35057e82-ed7d-4e19-ba4d-719a42135cd6?utm_source=github&utm_medium=referral&page=upgrade-pr
2022-12-07 18:15:22 +00:00
7bbaf4fee8 feat: move notifs to bottom right 2022-12-07 12:16:53 -05:00
91c8fd14df feat: add notif type 2022-12-07 12:15:17 -05:00
9e1112eb52 fix: hide notifs wrapper if no notifs 2022-12-07 12:04:53 -05:00
6050e65a59 fix: notif type is optional 2022-12-07 12:02:01 -05:00
bbc23aca55 Use encoding/csv to build the CSV output 2022-12-07 10:59:10 -06:00
9098bdc751 refactor: Change type to ensure notifs within state are Required<> 2022-12-07 11:58:17 -05:00
251426b559 feat: Add notification timeout 2022-12-07 11:57:39 -05:00
793eaee0c6 Address PR feedback 2022-12-07 10:54:24 -06:00
349865e6ef fix: clearNotification now requires string 2022-12-07 11:52:51 -05:00
add3075439 feat: create prop for Notification; small readability changes 2022-12-07 11:52:18 -05:00
3db1ff2411 modify error model 2022-12-07 11:06:30 -05:00
8cd9e20fa6 Update readme star gif 2022-12-07 09:30:38 -05:00
29ab13430f Merge branch 'main' into I-36-use-pre-built-frontend-image 2022-12-07 09:18:50 +01:00
90eb292721 Add an export command 2022-12-07 01:44:06 -06:00
5e1f6d3884 Merge pull request #84 from SH5H/main
Convert JS to TS
2022-12-06 23:36:56 -05:00
1310b176a9 Update README.md 2022-12-06 21:23:28 -05:00
ccf1010e94 Merge pull request #82 from asharonbaltazar/feat-error-notifs
Add Error Notifications
2022-12-06 21:09:07 -05:00
d46bf54a8d fix: wrap pushKeys args in obj 2022-12-06 21:07:40 -05:00
93703475fe Limit replacement to JS files only 2022-12-06 22:45:26 +01:00
991b10cc17 Convert JS to TS 2022-12-07 04:58:27 +09:00
60fcd34af5 Merge branch 'main' into feat-error-notifs 2022-12-06 13:10:31 -05:00
f60e0cf7ee feat: separate components from Notification Provider 2022-12-06 12:50:49 -05:00
9071fafd06 feat: fix import paths 2022-12-06 12:50:09 -05:00
9499aa1097 feat: move NotificationProvider into Notifications folder 2022-12-06 12:49:44 -05:00
389bf0b41f feat: add NotificationProvider to _app.tsx 2022-12-06 12:26:19 -05:00
6ed5b9e706 feat: create initial NotificationProvider component 2022-12-06 12:25:55 -05:00
209673d744 Merge branch 'main' into I-36-use-pre-built-frontend-image 2022-12-06 18:13:10 +01:00
baacc310bb Merge pull request #77 from SH5H/jsconvert
Convert JS to TS
2022-12-06 09:04:50 -05:00
1e16a18469 Merge branch 'main' of https://github.com/Infisical/infisical 2022-12-06 02:28:40 -05:00
df1ade4f5f Changed [NAME]'s project to Example Project 2022-12-06 02:28:34 -05:00
944cc5b32c Fixed the bug with start keys 2022-12-06 02:27:28 -05:00
a83d536ea4 Improve GH Action workflow for building images 2022-12-06 00:17:24 +01:00
1454911085 Merge branch 'Infisical:main' into I-36-use-pre-built-frontend-image 2022-12-05 23:40:14 +01:00
9e73b3431e Delete workspace type file 2022-12-06 06:15:58 +09:00
4a105a72e9 Update comment for new util 2022-12-06 05:55:14 +09:00
a47decd31f Convert JS to TS 2022-12-06 05:53:34 +09:00
c5a422fe64 update self host docs 2022-12-05 15:26:20 -05:00
bb47f7a92f Pre-bake some vars and change telemetry handling 2022-12-05 21:17:59 +01:00
13f2ab9425 update steps number 2022-12-05 14:41:09 -05:00
ac2c50b161 Merge pull request #76 from Infisical/upload-helm-chart-action
Upload helm chart action and docs for k8
2022-12-05 14:33:03 -05:00
afb374ff13 Add docs for k8 support 2022-12-05 14:32:16 -05:00
e98b76cba5 remove manual namespace 2022-12-05 12:57:18 -05:00
3e2ed62e50 update readme of helm repo 2022-12-05 12:31:48 -05:00
8e15dfc3d9 Merge pull request #73 from Infisical/upload-helm-chart-action
Upload helm chart action
2022-12-05 12:20:32 -05:00
6fb22b68dd update workflow file name 2022-12-05 12:17:06 -05:00
05a19a2201 Rewrite upload steps action 2022-12-05 12:13:52 -05:00
9ee5f3d41b upload helm chart to cloudsmith 2022-12-05 12:04:23 -05:00
142a38ae3c Merge branch 'main' into I-36-use-pre-built-frontend-image 2022-12-05 17:50:11 +01:00
e67620c3ce helm release on dispatch 2022-12-05 10:48:18 -05:00
e8e6b72422 pause helm chart release 2022-12-05 10:46:56 -05:00
4cc4edcb7e Merge branch 'main' of https://github.com/Infisical/infisical into main 2022-12-05 10:45:09 -05:00
2acea4f085 push new cli release to populate release page 2022-12-05 10:45:02 -05:00
0dd546813a Create helm-chart-release.yaml 2022-12-05 10:37:33 -05:00
d82dfa5504 create helm repo install file 2022-12-05 10:28:49 -05:00
b13b0693ba Updated menu in docs 2022-12-05 00:11:47 -05:00
e00c3ab9e2 Expanded contributing docs 2022-12-05 00:07:03 -05:00
088668e1b0 Fix let -> const 2022-12-04 23:18:39 -05:00
b21cb521da Tranforming more components to typescript (#47) 2022-12-04 23:03:57 -05:00
b677ab6429 feat: add react TS types 2022-12-04 22:03:07 -05:00
4ae88b2e47 Fix merge conflict 2022-12-03 17:14:48 +01:00
43fb35381f Merge branch 'I-36-use-pre-built-frontend-image' of github.com:reginaldbondoc/infisical into I-36-use-pre-built-frontend-image 2022-12-03 16:24:05 +01:00
023c744a8e Merge branch 'main' into I-36-use-pre-built-frontend-image 2022-12-03 13:11:23 +01:00
a5618681df Merge branch 'Infisical:main' into I-36-use-pre-built-frontend-image 2022-11-30 22:46:52 +01:00
a84fc847db Merge branch 'main' into I-36-use-pre-built-frontend-image 2022-11-30 22:10:27 +01:00
c68eaa613c Use pre-built frontend image in prod compose file 2022-11-29 21:09:50 +01:00
71 changed files with 2027 additions and 759 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 106 KiB

View File

@ -0,0 +1,41 @@
name: Check Backend Pull Request
on:
pull_request:
types: [ opened, synchronize ]
paths:
- 'backend/**'
- '!backend/README.md'
- '!backend/.*'
- 'backend/.eslintrc.js'
jobs:
check-be-pr:
name: Check
runs-on: ubuntu-latest
steps:
-
name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: 🔧 Setup Node 16
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: backend/package-lock.json
-
name: 📦 Install dependencies
run: npm ci --only-production --ignore-scripts
working-directory: backend
# -
# name: 🧪 Run tests
# run: npm run test:ci
# working-directory: backend
-
name: 🏗️ Run build
run: npm run build
working-directory: backend

View File

@ -0,0 +1,41 @@
name: Check Frontend Pull Request
on:
pull_request:
types: [ opened, synchronize ]
paths:
- 'frontend/**'
- '!frontend/README.md'
- '!frontend/.*'
- 'frontend/.eslintrc.js'
jobs:
check-fe-pr:
name: Check
runs-on: ubuntu-latest
steps:
-
name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: 🔧 Setup Node 16
uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
cache-dependency-path: frontend/package-lock.json
-
name: 📦 Install dependencies
run: npm ci --only-production --ignore-scripts
working-directory: frontend
# -
# name: 🧪 Run tests
# run: npm run test:ci
# working-directory: frontend
-
name: 🏗️ Run build
run: npm run build
working-directory: frontend

View File

@ -3,35 +3,88 @@ name: Push to Docker Hub
on: [workflow_dispatch]
jobs:
docker:
backend-image:
name: Build backend image
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
-
name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: Set up QEMU
name: 🔧 Set up QEMU
uses: docker/setup-qemu-action@v2
-
name: Set up Docker Buildx
name: 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v2
-
name: Login to Docker Hub
name: 🐋 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
# -
# name: 📦 Build backend and export to Docker
# uses: docker/build-push-action@v3
# with:
# load: true
# context: backend
# tags: infisical/backend:test
# -
# name: 🧪 Test backend image
# run: |
# docker run --rm infisical/backend:test
-
name: Build and push backend
name: 🏗️ Build backend and push
uses: docker/build-push-action@v3
with:
push: true
context: backend
tags: infisical/backend:test
tags: infisical/backend:latest
platforms: linux/amd64,linux/arm64
frontend-image:
name: Build frontend image
runs-on: ubuntu-latest
steps:
-
name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: Build and push frontend
name: 🔧 Set up QEMU
uses: docker/setup-qemu-action@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: 📦 Build frontend and export to Docker
# uses: docker/build-push-action@v3
# with:
# load: true
# context: frontend
# tags: infisical/frontend:test
# build-args: |
# POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}
# -
# name: 🧪 Test frontend image
# run: |
# docker run --rm infisical/frontend:test
-
name: 🏗️ Build frontend and push
uses: docker/build-push-action@v3
with:
push: true
file: frontend/Dockerfile.dev
context: frontend
tags: infisical/frontend:test
tags: infisical/frontend:latest
platforms: linux/amd64,linux/arm64
build-args: |
POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }}

View File

@ -0,0 +1,22 @@
name: Release Helm Charts
on: [workflow_dispatch]
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: v3.10.0
- name: Install python
uses: actions/setup-python@v4
- name: Install Cloudsmith CLI
run: pip install --upgrade cloudsmith-cli
- name: Build and push helm package to Cloudsmith
run: cd helm-charts && sh upload-to-cloudsmith.sh
env:
CLOUDSMITH_API_KEY: ${{ secrets.CLOUDSMITH_API_KEY }}

View File

@ -1,4 +1,4 @@
name: goreleaser
name: Go releaser
on:
push:

View File

@ -48,11 +48,17 @@
And more.
## Get started
## 🚀 Get started
To quickly get started, visit our [get started guide](https://infisical.com/docs/getting-started/introduction).
## What's cool about this?
<p>
<a href="https://infisical.com/docs/self-hosting/overview" target="_blank"><img src="https://user-images.githubusercontent.com/78047717/206356882-2b773eed-b0da-4725-ae2f-83e3cd7f2713.png" height=120 /> </a>
<a href="https://www.youtube.com/watch?v=JS3OKYU2078" target="_blank"><img src="https://user-images.githubusercontent.com/78047717/206356600-8833b128-6cae-408c-a703-07b2fc6aff4b.png" height=120 /> </a>
<a href="https://app.infisical.com/signup" target="_blank"><img src="https://user-images.githubusercontent.com/78047717/206355970-f4c09062-b88f-452a-94e0-9c61a0651170.png" height=120></a>
</p>
## 🔥 What's cool about this?
Infisical makes secret management simple and end-to-end encrypted by default. We're on a mission to make it more accessible to all developers, <i>not just security teams</i>.
@ -62,20 +68,22 @@ If you care about efficiency and security, then Infisical is right for you.
We are currently working hard to make Infisical more extensive. Need any integrations or want a new feature? Feel free to [create an issue](https://github.com/Infisical/infisical/issues) or [contribute](https://infisical.com/docs/contributing/overview) directly to the repository.
## 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).
Not sure where to get started? [Book a free, non-pressure pairing sessions with one of our teammates](mailto:tony@infisical.com?subject=Pairing%20session&body=I'd%20like%20to%20do%20a%20pairing%20session!)!
Not sure where to get started? You can:
- [Book a free, non-pressure pairing sessions with one of our teammates](mailto:tony@infisical.com?subject=Pairing%20session&body=I'd%20like%20to%20do%20a%20pairing%20session!)!
- Join our <a href="https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g">Slack</a>, and ask us any questions there.
## Community & Support
## 💚 Community & Support
- [Slack](https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g) (For live discussion with the community and the Infisical team)
- [GitHub Discussions](https://github.com/Infisical/infisical/discussions) (For help with building and deeper conversations about features)
- [GitHub Issues](https://github.com/Infisical/infisical-cli/issues) (For any bugs and errors you encounter using Infisical)
- [Twitter](https://twitter.com/infisical) (Get news fast)
## Status
## 🐥 Status
- [x] Public Alpha: Anyone can sign up over at [infisical.com](https://infisical.com) but go easy on us, there are kinks and we're just getting started.
- [ ] Public Beta: Stable enough for most non-enterprise use-cases.
@ -83,13 +91,13 @@ Not sure where to get started? [Book a free, non-pressure pairing sessions with
We're currently in Public Alpha.
## Stay Up-to-Date
## 🚨 Stay Up-to-Date
Infisical officially launched as v.1.0 on November 21st, 2022. However, a lot of new features are coming very quickly. Watch **releases** of this repository to be notified about future updates:
![infisical-star-github](https://github.com/Infisical/infisical/blob/main/.github/images/star-infisical.gif?raw=true)
## Integrations
## 🔌 Integrations
We're currently setting the foundation and building [integrations](https://infisical.com/docs/integrations/overview) so secrets can be synced everywhere. Any help is welcome! :)
@ -261,15 +269,15 @@ We're currently setting the foundation and building [integrations](https://infis
</table>
## Open-source vs. paid
## 🏘 Open-source vs. paid
This repo is entirely MIT licensed, with the exception of the `ee` directory which will contain premium enterprise features requiring a Infisical license in the future. We're currently focused on developing non-enterprise offerings first that should suit most use-cases.
## Security
## 🛡 Security
Looking to report a security vulnerability? Please don't post about it in GitHub issue. Instead, refer to our [SECURITY.md](./SECURITY.md) file.
## Contributors 🦸
## 🦸 Contributors
[//]: contributor-faces
@ -277,4 +285,4 @@ Looking to report a security vulnerability? Please don't post about it in GitHub
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a>
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mv-turtle"><img src="https://avatars.githubusercontent.com/u/78047717?s=96&v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/reginaldbondoc"><img src="https://avatars.githubusercontent.com/u/7693108?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/SH5H"><img src="https://avatars.githubusercontent.com/u/25437192?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/asharonbaltazar"><img src="https://avatars.githubusercontent.com/u/58940073?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/edgarrmondragon"><img src="https://avatars.githubusercontent.com/u/16805946?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/hanywang2"><img src="https://avatars.githubusercontent.com/u/44352119?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/tobias-mintlify"><img src="https://avatars.githubusercontent.com/u/110702161?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/0xflotus"><img src="https://avatars.githubusercontent.com/u/26602940?v=4" width="50" height="50" alt=""/></a>

View File

@ -10,7 +10,7 @@
"license": "ISC",
"dependencies": {
"@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.14.0",
"@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1",
"axios": "^1.1.3",
"bigint-conversion": "^2.2.2",
@ -19,13 +19,13 @@
"crypto-js": "^4.1.1",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-rate-limit": "^6.5.1",
"express-rate-limit": "^6.7.0",
"express-validator": "^6.14.2",
"handlebars": "^4.7.7",
"helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4",
"mongoose": "^6.7.1",
"mongoose": "^6.7.2",
"nodemailer": "^6.8.0",
"posthog-node": "^2.1.0",
"query-string": "^7.1.1",
@ -33,7 +33,7 @@
"stripe": "^10.7.0",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"typescript": "^4.8.4"
"typescript": "^4.9.3"
},
"devDependencies": {
"@posthog/plugin-scaffold": "^1.3.4",
@ -2608,13 +2608,13 @@
}
},
"node_modules/@sentry/node": {
"version": "7.17.4",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.17.4.tgz",
"integrity": "sha512-cR+Gsir9c/tzFWxvk4zXkMQy6tNRHEYixHrb88XIjZVYDqDS9l2/bKs5nJusdmaUeLtmPp5Et2o7RJyS7gvKTQ==",
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
"integrity": "sha512-yG7Tx32WqOkEHVotFLrumCcT9qlaSDTkFNZ+yLSvZXx74ifsE781DzBA9W7K7bBdYO3op+p2YdsOKzf3nPpAyQ==",
"dependencies": {
"@sentry/core": "7.17.4",
"@sentry/types": "7.17.4",
"@sentry/utils": "7.17.4",
"@sentry/core": "7.19.0",
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"cookie": "^0.4.1",
"https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3",
@ -2624,14 +2624,80 @@
"node": ">=8"
}
},
"node_modules/@sentry/tracing": {
"version": "7.17.4",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.17.4.tgz",
"integrity": "sha512-9Fz6DI16ddnd970mlB5MiCNRSmSXp4SVZ1Yv3L22oS3kQeNxjBTE+htYNwJzSPrQp9aL/LqTYwlnrCy24u9XQA==",
"node_modules/@sentry/node/node_modules/@sentry/core": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.19.0.tgz",
"integrity": "sha512-YF9cTBcAnO4R44092BJi5Wa2/EO02xn2ziCtmNgAVTN2LD31a/YVGxGBt/FDr4Y6yeuVehaqijVVvtpSmXrGJw==",
"dependencies": {
"@sentry/core": "7.17.4",
"@sentry/types": "7.17.4",
"@sentry/utils": "7.17.4",
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/node/node_modules/@sentry/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.19.0.tgz",
"integrity": "sha512-oGRAT6lfzoKrxO1mvxiSj0XHxWPd6Gd1wpPGuu6iJo03xgWDS+MIlD1h2unqL4N5fAzLjzmbC2D2lUw50Kn2pA==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/node/node_modules/@sentry/utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.19.0.tgz",
"integrity": "sha512-2L6lq+c9Ol2uiRxQDdcgoapmHJp24MhMN0gIkn2alSfMJ+ls6bGXzQHx6JAIdoOiwFQXRZHKL9ecfAc8O+vItA==",
"dependencies": {
"@sentry/types": "7.19.0",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.19.0.tgz",
"integrity": "sha512-SWY17M3TsgBePaGowUcSqBwaT0TJQzuNexVnLojuU0k6F57L9hubvP9zaoosoCfARXQ/3NypAFWnlJyf570rFQ==",
"dependencies": {
"@sentry/core": "7.19.0",
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/core": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.19.0.tgz",
"integrity": "sha512-YF9cTBcAnO4R44092BJi5Wa2/EO02xn2ziCtmNgAVTN2LD31a/YVGxGBt/FDr4Y6yeuVehaqijVVvtpSmXrGJw==",
"dependencies": {
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.19.0.tgz",
"integrity": "sha512-oGRAT6lfzoKrxO1mvxiSj0XHxWPd6Gd1wpPGuu6iJo03xgWDS+MIlD1h2unqL4N5fAzLjzmbC2D2lUw50Kn2pA==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/tracing/node_modules/@sentry/utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.19.0.tgz",
"integrity": "sha512-2L6lq+c9Ol2uiRxQDdcgoapmHJp24MhMN0gIkn2alSfMJ+ls6bGXzQHx6JAIdoOiwFQXRZHKL9ecfAc8O+vItA==",
"dependencies": {
"@sentry/types": "7.19.0",
"tslib": "^1.9.3"
},
"engines": {
@ -4517,9 +4583,9 @@
}
},
"node_modules/express-rate-limit": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"engines": {
"node": ">= 12.9.0"
},
@ -6452,9 +6518,9 @@
}
},
"node_modules/mongoose": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.1.tgz",
"integrity": "sha512-qbagtqSyvIhUz4EWzXC00EA0DJHFrQwlzTlNGX5DjiESoJiPKqkEga1k9hviFKRFgBna+OlW54mkdi+0+AqxCw==",
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.2.tgz",
"integrity": "sha512-lrP2V5U1qhaf+z33fiIn7aYAZZ1fVDly+TkFRjTujNBF/FIHESATj2RbgAOSlWqv32fsZXkXejXzeVfjbv35Ow==",
"dependencies": {
"bson": "^4.7.0",
"kareem": "2.4.1",
@ -10508,9 +10574,9 @@
}
},
"node_modules/typescript": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==",
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -13058,28 +13124,80 @@
}
},
"@sentry/node": {
"version": "7.17.4",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.17.4.tgz",
"integrity": "sha512-cR+Gsir9c/tzFWxvk4zXkMQy6tNRHEYixHrb88XIjZVYDqDS9l2/bKs5nJusdmaUeLtmPp5Et2o7RJyS7gvKTQ==",
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
"integrity": "sha512-yG7Tx32WqOkEHVotFLrumCcT9qlaSDTkFNZ+yLSvZXx74ifsE781DzBA9W7K7bBdYO3op+p2YdsOKzf3nPpAyQ==",
"requires": {
"@sentry/core": "7.17.4",
"@sentry/types": "7.17.4",
"@sentry/utils": "7.17.4",
"@sentry/core": "7.19.0",
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"cookie": "^0.4.1",
"https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/core": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.19.0.tgz",
"integrity": "sha512-YF9cTBcAnO4R44092BJi5Wa2/EO02xn2ziCtmNgAVTN2LD31a/YVGxGBt/FDr4Y6yeuVehaqijVVvtpSmXrGJw==",
"requires": {
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.19.0.tgz",
"integrity": "sha512-oGRAT6lfzoKrxO1mvxiSj0XHxWPd6Gd1wpPGuu6iJo03xgWDS+MIlD1h2unqL4N5fAzLjzmbC2D2lUw50Kn2pA=="
},
"@sentry/utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.19.0.tgz",
"integrity": "sha512-2L6lq+c9Ol2uiRxQDdcgoapmHJp24MhMN0gIkn2alSfMJ+ls6bGXzQHx6JAIdoOiwFQXRZHKL9ecfAc8O+vItA==",
"requires": {
"@sentry/types": "7.19.0",
"tslib": "^1.9.3"
}
}
}
},
"@sentry/tracing": {
"version": "7.17.4",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.17.4.tgz",
"integrity": "sha512-9Fz6DI16ddnd970mlB5MiCNRSmSXp4SVZ1Yv3L22oS3kQeNxjBTE+htYNwJzSPrQp9aL/LqTYwlnrCy24u9XQA==",
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.19.0.tgz",
"integrity": "sha512-SWY17M3TsgBePaGowUcSqBwaT0TJQzuNexVnLojuU0k6F57L9hubvP9zaoosoCfARXQ/3NypAFWnlJyf570rFQ==",
"requires": {
"@sentry/core": "7.17.4",
"@sentry/types": "7.17.4",
"@sentry/utils": "7.17.4",
"@sentry/core": "7.19.0",
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
},
"dependencies": {
"@sentry/core": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.19.0.tgz",
"integrity": "sha512-YF9cTBcAnO4R44092BJi5Wa2/EO02xn2ziCtmNgAVTN2LD31a/YVGxGBt/FDr4Y6yeuVehaqijVVvtpSmXrGJw==",
"requires": {
"@sentry/types": "7.19.0",
"@sentry/utils": "7.19.0",
"tslib": "^1.9.3"
}
},
"@sentry/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.19.0.tgz",
"integrity": "sha512-oGRAT6lfzoKrxO1mvxiSj0XHxWPd6Gd1wpPGuu6iJo03xgWDS+MIlD1h2unqL4N5fAzLjzmbC2D2lUw50Kn2pA=="
},
"@sentry/utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.19.0.tgz",
"integrity": "sha512-2L6lq+c9Ol2uiRxQDdcgoapmHJp24MhMN0gIkn2alSfMJ+ls6bGXzQHx6JAIdoOiwFQXRZHKL9ecfAc8O+vItA==",
"requires": {
"@sentry/types": "7.19.0",
"tslib": "^1.9.3"
}
}
}
},
"@sentry/types": {
@ -14523,9 +14641,9 @@
}
},
"express-rate-limit": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==",
"version": "6.7.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
"integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"requires": {}
},
"express-validator": {
@ -15964,9 +16082,9 @@
}
},
"mongoose": {
"version": "6.7.1",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.1.tgz",
"integrity": "sha512-qbagtqSyvIhUz4EWzXC00EA0DJHFrQwlzTlNGX5DjiESoJiPKqkEga1k9hviFKRFgBna+OlW54mkdi+0+AqxCw==",
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.2.tgz",
"integrity": "sha512-lrP2V5U1qhaf+z33fiIn7aYAZZ1fVDly+TkFRjTujNBF/FIHESATj2RbgAOSlWqv32fsZXkXejXzeVfjbv35Ow==",
"requires": {
"bson": "^4.7.0",
"kareem": "2.4.1",
@ -18825,9 +18943,9 @@
}
},
"typescript": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ=="
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA=="
},
"uglify-js": {
"version": "3.17.4",

View File

@ -1,7 +1,7 @@
{
"dependencies": {
"@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.14.0",
"@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1",
"axios": "^1.1.3",
"bigint-conversion": "^2.2.2",
@ -10,13 +10,13 @@
"crypto-js": "^4.1.1",
"dotenv": "^16.0.1",
"express": "^4.18.1",
"express-rate-limit": "^6.5.1",
"express-rate-limit": "^6.7.0",
"express-validator": "^6.14.2",
"handlebars": "^4.7.7",
"helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4",
"mongoose": "^6.7.1",
"mongoose": "^6.7.2",
"nodemailer": "^6.8.0",
"posthog-node": "^2.1.0",
"query-string": "^7.1.1",
@ -24,7 +24,7 @@
"stripe": "^10.7.0",
"tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1",
"typescript": "^4.8.4"
"typescript": "^4.9.3"
},
"name": "infisical-api",
"version": "1.0.0",

View File

@ -106,7 +106,7 @@ const initializeDefaultOrg = async ({
// initialize a default workspace inside the new organization
const workspace = await createWorkspace({
name: `${user.firstName}'s Project`,
name: `Example Project`,
organizationId: organization._id.toString()
});

140
cli/packages/cmd/export.go Normal file
View File

@ -0,0 +1,140 @@
/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
*/
package cmd
import (
"encoding/csv"
"encoding/json"
"fmt"
"strings"
"github.com/Infisical/infisical-merge/packages/models"
"github.com/Infisical/infisical-merge/packages/util"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
const (
FormatDotenv string = "dotenv"
FormatJson string = "json"
FormatCSV string = "csv"
)
// exportCmd represents the export command
var exportCmd = &cobra.Command{
Use: "export",
Short: "Used to export environment variables to a file",
DisableFlagsInUseLine: true,
Example: "infisical export --env=prod --format=json > secrets.json",
Args: cobra.NoArgs,
PreRun: toggleDebug,
Run: func(cmd *cobra.Command, args []string) {
envName, err := cmd.Flags().GetString("env")
if err != nil {
log.Errorln("Unable to parse the environment flag")
log.Debugln(err)
return
}
shouldExpandSecrets, err := cmd.Flags().GetBool("expand")
if err != nil {
log.Errorln("Unable to parse the substitute flag")
log.Debugln(err)
return
}
projectId, err := cmd.Flags().GetString("projectId")
if err != nil {
log.Errorln("Unable to parse the project id flag")
log.Debugln(err)
return
}
format, err := cmd.Flags().GetString("format")
if err != nil {
log.Errorln("Unable to parse the format flag")
log.Debugln(err)
return
}
envsFromApi, err := util.GetAllEnvironmentVariables(projectId, envName)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your Infisical token. Double check the token, project id or environment name (dev, prod, ect.)")
log.Debugln(err)
return
}
var output string
if shouldExpandSecrets {
substitutions := util.SubstituteSecrets(envsFromApi)
output, err = formatEnvs(substitutions, format)
if err != nil {
log.Errorln(err)
return
}
} else {
output, err = formatEnvs(envsFromApi, format)
if err != nil {
log.Errorln(err)
return
}
}
fmt.Print(output)
},
}
func init() {
rootCmd.AddCommand(exportCmd)
exportCmd.Flags().StringP("env", "e", "dev", "Set the environment (dev, prod, etc.) from which your secrets should be pulled from")
exportCmd.Flags().String("projectId", "", "The project ID from which your secrets should be pulled from")
exportCmd.Flags().Bool("expand", true, "Parse shell parameter expansions in your secrets")
exportCmd.Flags().StringP("format", "f", "dotenv", "Set the format of the output file (dotenv, json, csv)")
}
// Format according to the format flag
func formatEnvs(envs []models.SingleEnvironmentVariable, format string) (string, error) {
switch strings.ToLower(format) {
case FormatDotenv:
return formatAsDotEnv(envs), nil
case FormatJson:
return formatAsJson(envs), nil
case FormatCSV:
return formatAsCSV(envs), nil
default:
return "", fmt.Errorf("invalid format flag: %s", format)
}
}
// Format environment variables as a CSV file
func formatAsCSV(envs []models.SingleEnvironmentVariable) string {
csvString := &strings.Builder{}
writer := csv.NewWriter(csvString)
writer.Write([]string{"Key", "Value"})
for _, env := range envs {
writer.Write([]string{env.Key, env.Value})
}
writer.Flush()
return csvString.String()
}
// Format environment variables as a dotenv file
func formatAsDotEnv(envs []models.SingleEnvironmentVariable) string {
var dotenv string
for _, env := range envs {
dotenv += fmt.Sprintf("%s='%s'\n", env.Key, env.Value)
}
return dotenv
}
// Format environment variables as a JSON file
func formatAsJson(envs []models.SingleEnvironmentVariable) string {
// Dump as a json array
json, err := json.Marshal(envs)
if err != nil {
log.Errorln("Unable to marshal environment variables to JSON")
log.Debugln(err)
return ""
}
return string(json)
}

View File

@ -114,7 +114,7 @@ func init() {
func askForLoginCredentials() (email string, password string, err error) {
validateEmail := func(input string) error {
matched, err := regexp.MatchString("^[\\w!#$%&'*+/=?`{|}~^-]+(?:\\.[\\w!#$%&'*+/=?`{|}~^-]+)*@(?:[a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", input)
matched, err := regexp.MatchString("^\\S+@\\S+$", input)
if err != nil || !matched {
return errors.New("this doesn't look like an email address")
}

View File

@ -15,7 +15,7 @@ var rootCmd = &cobra.Command{
Short: "Infisical CLI is used to inject environment variables into any process",
Long: `Infisical is a simple, end-to-end encrypted service that enables teams to sync and manage their environment variables across their development life cycle.`,
CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: "0.1.5",
Version: "0.1.8",
}
// Execute adds all child commands to the root command and sets flags appropriately.

View File

@ -47,46 +47,11 @@ var runCmd = &cobra.Command{
return
}
var envsFromApi []models.SingleEnvironmentVariable
infisicalToken := os.Getenv(util.INFISICAL_TOKEN_NAME)
if infisicalToken == "" {
hasUserLoggedInbefore, loggedInUserEmail, err := util.IsUserLoggedIn()
if err != nil {
log.Info("Unexpected issue occurred while checking login status. To see more details, add flag --debug")
log.Debugln(err)
return
}
if !hasUserLoggedInbefore {
log.Infoln("No logged in user. To login, please run command [infisical login]")
return
}
userCreds, err := util.GetUserCredsFromKeyRing(loggedInUserEmail)
if err != nil {
log.Infoln("Unable to get user creds from key ring")
log.Debug(err)
return
}
if !util.WorkspaceConfigFileExists() {
log.Infoln("Your project is not connected to a project yet. Run command [infisical init]")
return
}
envsFromApi, err = util.GetSecretsFromAPIUsingCurrentLoggedInUser(envName, userCreds)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your logged in credentials. If the issue persists, double check your project id/try logging in again.")
log.Debugln(err)
return
}
} else {
envsFromApi, err = util.GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your Infisical token. Double check the token, project id or environment name (dev, prod, ect.)")
log.Debugln(err)
return
}
envsFromApi, err := util.GetAllEnvironmentVariables(projectId, envName)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your Infisical token. Double check the token, project id or environment name (dev, prod, ect.)")
log.Debugln(err)
return
}
if shouldExpandSecrets {

View File

@ -5,10 +5,13 @@ import log "github.com/sirupsen/logrus"
// Custom error type so that we can give helpful messages in CLI
type Error struct {
Err error
DebugMessage string
FriendlyMessage string
}
func (e *Error) printFriendlyMessage() {
log.Infoln(e.FriendlyMessage)
}
func (e *Error) printDebuError() {
log.Debugln(e.Err)
}

View File

@ -4,6 +4,7 @@ import (
"encoding/base64"
"errors"
"fmt"
"os"
"regexp"
"strings"
@ -184,6 +185,52 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string,
return listOfEnv, nil
}
func GetAllEnvironmentVariables(projectId string, envName string) ([]models.SingleEnvironmentVariable, error) {
var envsFromApi []models.SingleEnvironmentVariable
infisicalToken := os.Getenv(INFISICAL_TOKEN_NAME)
if infisicalToken == "" {
hasUserLoggedInbefore, loggedInUserEmail, err := IsUserLoggedIn()
if err != nil {
log.Info("Unexpected issue occurred while checking login status. To see more details, add flag --debug")
log.Debugln(err)
return envsFromApi, err
}
if !hasUserLoggedInbefore {
log.Infoln("No logged in user. To login, please run command [infisical login]")
return envsFromApi, fmt.Errorf("user not logged in")
}
userCreds, err := GetUserCredsFromKeyRing(loggedInUserEmail)
if err != nil {
log.Infoln("Unable to get user creds from key ring")
log.Debug(err)
return envsFromApi, err
}
if !WorkspaceConfigFileExists() {
log.Infoln("Your project is not connected to a project yet. Run command [infisical init]")
return envsFromApi, fmt.Errorf("project not initialized")
}
envsFromApi, err = GetSecretsFromAPIUsingCurrentLoggedInUser(envName, userCreds)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your logged in credentials. If the issue persists, double check your project id/try logging in again.")
log.Debugln(err)
return envsFromApi, err
}
} else {
envsFromApi, err := GetSecretsFromAPIUsingInfisicalToken(infisicalToken, envName, projectId)
if err != nil {
log.Errorln("Something went wrong when pulling secrets using your Infisical token. Double check the token, project id or environment name (dev, prod, ect.)")
log.Debugln(err)
return envsFromApi, err
}
}
return envsFromApi, nil
}
func GetWorkSpacesFromAPI(userCreds models.UserCredentials) (workspaces []models.Workspace, err error) {
// create http client
httpClient := resty.New().

View File

@ -23,7 +23,6 @@ services:
build:
context: ./backend
dockerfile: Dockerfile
image: infisical/backend
volumes:
- ./backend/src:/app/src
- ./backend/nodemon.json:/app/nodemon.json
@ -43,7 +42,6 @@ services:
build:
context: ./frontend
dockerfile: Dockerfile.dev
image: infisical/frontend
volumes:
- ./frontend/pages:/app/pages
- ./frontend/public:/app/public
@ -52,12 +50,8 @@ services:
env_file: .env
environment:
- NEXT_PUBLIC_ENV=development
- NEXT_PUBLIC_WEBSITE_URL=${SITE_URL}
- NEXT_PUBLIC_POSTHOG_HOST=${POSTHOG_HOST}
- NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
- NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
- NEXT_PUBLIC_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
networks:
- infisical-dev
@ -78,6 +72,8 @@ services:
container_name: infisical-dev-mongo-express
image: mongo-express
restart: always
depends_on:
- mongo
env_file: .env
environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_USERNAME}
@ -93,4 +89,4 @@ volumes:
driver: local
networks:
infisical-dev:
infisical-dev:

View File

@ -17,14 +17,10 @@ services:
- infisical
backend:
platform: linux/amd64
container_name: infisical-backend
restart: unless-stopped
depends_on:
- mongo
build:
context: ./backend
dockerfile: Dockerfile
image: infisical/backend
command: npm run start
env_file: .env
@ -34,24 +30,17 @@ services:
- infisical
frontend:
platform: linux/amd64
container_name: infisical-frontend
restart: unless-stopped
depends_on:
- backend
build:
context: ./frontend
dockerfile: Dockerfile.prod
image: infisical/frontend
env_file: .env
environment:
- NEXT_PUBLIC_ENV=production
- NEXT_PUBLIC_WEBSITE_URL=${SITE_URL}
- NEXT_PUBLIC_POSTHOG_HOST=${POSTHOG_HOST}
- NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
# - NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
- INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
- NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
- NEXT_PUBLIC_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
networks:
- infisical
@ -73,4 +62,4 @@ volumes:
driver: local
networks:
infisical:
infisical:

33
docs/cli/export.mdx Normal file
View File

@ -0,0 +1,33 @@
---
title: "infisical export"
---
```bash
infisical export [options]
```
## Description
Export environment variables from the platform into a file format.
## Options
| Option | Description | Default value |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `--env` | Used to set the environment that secrets are pulled from. Accepted values: `dev`, `staging`, `test`, `prod` | `dev` |
| `--projectId` | Used to determine from which infisical project your secrets will be exported from (only required if injecting via the service token method). | `None` |
| `--expand` | Parse shell parameter expansions in your secrets (e.g., `${DOMAIN}`) | `true` |
| `--format` | Format of the output file. Accepted values: `dotenv`, `csv` and `json` | `dotenv` |
## Examples
```bash
# Export variables to a .env file
infisical export > .env
# Export variables to a CSV file
infisical export --format=csv > secrets.csv
# Export variables to a JSON file
infisical export --format=json > secrets.json
```

16
docs/contributing/FAQ.mdx Normal file
View File

@ -0,0 +1,16 @@
---
title: "Frequently Asked Questions"
description: "Have any questions? [Join our Slack community](https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g)."
---
## Problem with SMTP
You can normally populate `SMTP_USERNAME` and `SMTP_PASSWORD` with your usual login and password (you could also create a 'burner' email). Sometimes, there still are problems.
You can go to your Gmail account settings > security and enable “less secure apps”. This would allow Infisical to use your Gmail to send emails.
If it still doesn't work, [this](https://stackoverflow.com/questions/72547853/unable-to-send-email-in-c-sharp-less-secure-app-access-not-longer-available/72553362#72553362) should help.
## `MONGO_URL` issues
Your `MONGO_URL` should be something like `mongodb://root:example@mongo:27017/?authSource=admin`. If you want to change it (not recommended), you should make sure that you keep this URL in line with `MONGO_USERNAME=root` and `MONGO_PASSWORD=example`.

View File

@ -102,8 +102,11 @@
"pages": [
"self-hosting/overview",
{
"group": "Deployments",
"pages": ["self-hosting/deployments/linux"]
"group": "Deployments options",
"pages": [
"self-hosting/deployments/linux",
"self-hosting/deployments/kubernetes"
]
},
{
"group": "Configuration",
@ -162,7 +165,8 @@
"pages": [
"contributing/overview",
"contributing/code-of-conduct",
"contributing/developing"
"contributing/developing",
"contributing/FAQ"
]
}
],

View File

@ -9,24 +9,24 @@ Configuring Infisical requires setting some environment variables. There is a fi
| Variable | Description | Default Value |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------- | ---------------- |
| `PRIVATE_KEY` | ❗️ NaCl-generated server secret key | `None` |
| `PUBLIC_KEY` | ❗️ NaCl-generated server public key | `None` |
| `ENCRYPTION_KEY` | ❗️ Strong hex encryption key | `None` |
| `JWT_SIGNUP_SECRET` | ❗JWT token secret | `None` |
| `JWT_REFRESH_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_AUTH_SECRET` | ❗️ JWT token secret | `None` |
| `PRIVATE_KEY` | ❗️ NaCl-generated server secret key | `None` |
| `PUBLIC_KEY` | ❗️ NaCl-generated server public key | `None` |
| `ENCRYPTION_KEY` | ❗️ Strong hex encryption key | `None` |
| `JWT_SIGNUP_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_REFRESH_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_AUTH_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_SIGNUP_LIFETIME` | JWT token lifetime expressed in seconds or a string describing a time span (e.g. 60, "2 days", "10h", "7d") | `15m` |
| `JWT_REFRESH_LIFETIME` | JWT token lifetime expressed in seconds or a string describing a time span (e.g. 60, "2 days", "10h", "7d") | `90d` |
| `JWT_AUTH_LIFETIME` | JWT token lifetime expressed in seconds or a string describing a time span (e.g. 60, "2 days", "10h", "7d") | `10d` |
| `EMAIL_TOKEN_LIFETIME` | Email OTP/magic-link lifetime expressed in seconds | `86400` |
| `MONGO_URL` | ❗️ MongoDB instance connection string either to container instance or MongoDB Cloud | `None` |
| `MONGO_URL` | ❗️ MongoDB instance connection string either to container instance or MongoDB Cloud | `None` |
| `MONGO_USERNAME` | MongoDB username if using container | `None` |
| `MONGO_PASSWORD` | MongoDB password if using container | `None` |
| `SITE_URL` | ❗️ Site URL - should be an absolute URL including the protocol (e.g. `https://app.infisical.com`) | `None` |
| `SMT_HOST` | Whether the user joined the community | `smtp.gmail.com` |
| `SMTP_NAME` | Hostname to connect to for establishing SMTP connections (e.g. `Team`) | `None` |
| `SMTP_USERNAME` | ❗️ Credential to connect to host (e.g. `team@infisical.com`) | `None` |
| `SMTP_PASSWORD` | ❗️ Credential to connect to host | `None` |
| `SITE_URL` | ❗️ Site URL - should be an absolute URL including the protocol (e.g. `https://app.infisical.com`) | `None` |
| `SMTP_HOST` | Hostname to connect to for establishing SMTP connections | `smtp.gmail.com` |
| `SMTP_NAME` | Name label to be used in From field (e.g. `Team`) | `None` |
| `SMTP_USERNAME` | ❗️ Credential to connect to host (e.g. `team@infisical.com`) | `None` |
| `SMTP_PASSWORD` | ❗️ Credential to connect to host | `None` |
| `TELEMETRY_ENABLED` | `true` or `false`. [More](../overview). | `true` |
| `OAUTH_CLIENT_SECRET_HEROKU` | OAuth client secret for Heroku integration | `None` |
| `OAUTH_TOKEN_URL_HEROKU` | OAuth token URL for Heroku integration | `None` |

View File

@ -0,0 +1,54 @@
---
title: "Kubernetes"
description: "Deploy with Kubernetes"
---
<Info>
Self-host vs. Infisical Cloud
Self-hosting Infisical means managing the service yourself, taking care of upgrades, scaling, security, etc.
If you're less technical and looking for a hands-free experience with minimal overhead then we recommend Infisical Cloud.
</Info>
**Prerequisites**
- You have understanding of [Kubernetes](https://kubernetes.io/)
- You have understanding of [Helm package manager](https://helm.sh/)
- You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster
#### 1. Fill our environment variables
Before you can deploy the Helm chart, you must fill out the required environment variables. To do so, please either download or copy the
contents of [this file](https://raw.githubusercontent.com/Infisical/infisical/main/helm-charts/infisical/values.yaml) to a `.yaml` file.
_Refer to the available [environment variables](../../self-hosting/configuration/envars)_
Once you have a local copy of the values file, fill our the required environment variables and save the file.
#### 2. Install Infisical Helm repository
```bash
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
```
#### 3. Install the Helm chart
By default, the helm chart will be installed on your default namespace. If you wish to install the Chart on a different namespace, you may specify
that by adding the `--namespace <namespace-to-install-to>` to your `helm install` command.
```bash
## Installs to default namespace
helm install infisical-helm-charts/infisical --values <path to the values.yaml you downloaded/created in step 2>
```
<Note>
If you have not filled out all of the required environment variables, you will see an error message prompting you to
do so.
</Note>
4. Your Infisical installation is complete and should be running on the host name you specified in Ingress in `values.yaml`.
Note: Please allow an additional time (2 minutes) for the frontend pods to be fully ready.

View File

@ -9,17 +9,22 @@ Self-hosting Infisical means managing the service yourself, taking care of upgra
If you're less technical and looking for a hands-free experience with minimal overhead then we recommend Infisical Cloud.
Infisical Cloud also comes with some extra features unavailabe in the self-hosted edition. You can find more information about Infisical Cloud's offering on the pricing page.
Infisical Cloud also comes with some extra features unavailable in the self-hosted edition. You can find more information about Infisical Cloud's offering on the pricing page.
</Info>
## Deployment options
Infisical can be deployed on a Linux VM with docker-compose. We're rolling out more specific deployment options for DigitalOcean, AWS, GCP, and Azure soon.
Infisical can be deployed on a Linux VM with docker-compose and Kubernetes. We're rolling out more specific deployment options for DigitalOcean, AWS, GCP, and Azure soon.
Options:
- [Linux VM](/self-hosting/deployments/linux)
<CardGroup cols={2}>
<Card title="Any Linux" icon="square-1" color="#ea5a0c" href="/self-hosting/deployments/linux">
Deploy to any Linux with Docker
</Card>
<Card title="Kubernetes" icon="square-2" color="#0285c7" href="/self-hosting/deployments/kubernetes">
Deploy to your Kubernetes cluster
</Card>
</CardGroup>
## Telemetry

64
frontend/Dockerfile Normal file
View File

@ -0,0 +1,64 @@
ARG POSTHOG_HOST=https://app.posthog.com
ARG POSTHOG_API_KEY=posthog-api-key
FROM node:16-alpine AS deps
# Install dependencies only when needed. Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.
# RUN apk add --no-cache libc6-compat
WORKDIR /app
# Copy over dependency files
COPY package.json package-lock.json next.config.js ./
# Install dependencies
RUN npm ci --only-production
# Rebuild the source code only when needed
FROM node:16-alpine AS builder
WORKDIR /app
# Copy dependencies
COPY --from=deps /app/node_modules ./node_modules
# Copy all files
COPY . .
ENV NODE_ENV production
ENV NEXT_PUBLIC_ENV production
ARG POSTHOG_HOST
ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST
ARG POSTHOG_API_KEY
ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY
# Build
RUN npm run build
# Production image
FROM node:16-alpine AS runner
WORKDIR /app
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images
VOLUME /app/.next/cache/images
ARG POSTHOG_API_KEY
ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \
BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY
COPY --chown=nextjs:nodejs --chmod=555 scripts ./scripts
COPY --from=builder /app/public ./public
RUN chown nextjs:nodejs ./public/data
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
ENV NEXT_TELEMETRY_DISABLED 1
CMD ["/app/scripts/start.sh"]

View File

@ -4,12 +4,11 @@ import {
ENV,
POSTHOG_API_KEY,
POSTHOG_HOST,
TELEMETRY_ENABLED,
} from "../utilities/config";
export const initPostHog = () => {
if (typeof window !== "undefined") {
if (ENV == "production" && TELEMETRY_ENABLED) {
if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) { // eslint-disable-line
posthog.init(POSTHOG_API_KEY, {
api_host: POSTHOG_HOST,
});

View File

@ -1,19 +1,27 @@
import React from "react";
import { useState } from "react";
import React, { useState } from "react";
import { useRouter } from "next/router";
import {
faCircle,
faCircleExclamation,
faE,
faEye,
faEyeSlash,
} from "@fortawesome/free-solid-svg-icons";
import { faCircle, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import guidGenerator from "../utilities/randomId";
import Error from "./Error";
const InputField = (props) => {
interface InputFieldProps {
static?: boolean;
label: string;
type: string;
value: string;
placeholder?: string;
isRequired: boolean;
disabled?: boolean;
error?: boolean;
text?: string;
name?: string;
blurred?: boolean;
errorText?: string;
onChangeHandler: (value: string) => void;
}
const InputField = (props: InputFieldProps) => {
const [passwordVisible, setPasswordVisible] = useState(false);
const router = useRouter();
@ -67,7 +75,7 @@ const InputField = (props) => {
>
<input
onChange={(e) => props.onChangeHandler(e.target.value)}
type={passwordVisible == false ? props.type : "text"}
type={passwordVisible === false ? props.type : "text"}
placeholder={props.placeholder}
value={props.value}
required={props.isRequired}

View File

@ -1,3 +1,4 @@
/* eslint-disable no-unexpected-multiline */
/* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react";
import Link from "next/link";
@ -22,6 +23,7 @@ import getWorkspaces from "~/pages/api/workspace/getWorkspaces";
import uploadKeys from "~/pages/api/workspace/uploadKeys";
import NavBarDashboard from "../navigation/NavBarDashboard";
import { tempLocalStorage } from "../utilities/checks/tempLocalStorage";
import {
decryptAssymmetric,
encryptAssymmetric,
@ -30,13 +32,17 @@ import Button from "./buttons/Button";
import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog";
import Listbox from "./Listbox";
export default function Layout({ children }) {
interface LayoutProps {
children: React.ReactNode;
}
export default function Layout({ children }: LayoutProps) {
const router = useRouter();
const [workspaceList, setWorkspaceList] = useState([]);
const [workspaceMapping, setWorkspaceMapping] = useState([{ 1: 2 }]);
const [workspaceSelected, setWorkspaceSelected] = useState("∞");
let [newWorkspaceName, setNewWorkspaceName] = useState("");
let [isOpen, setIsOpen] = useState(false);
const [newWorkspaceName, setNewWorkspaceName] = useState("");
const [isOpen, setIsOpen] = useState(false);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(false);
@ -44,158 +50,186 @@ export default function Layout({ children }) {
setIsOpen(false);
}
function openModal() {
setIsOpen(true);
}
// TODO: what to do about the fact that 2ids can have the same name
/**
* When a user creates a new workspace, redirect them to the page of the new workspace.
* @param {*} workspaceName
*/
async function submitModal(workspaceName, addAllUsers) {
async function submitModal(workspaceName: string, addAllUsers: boolean) {
setLoading(true);
// timeout code.
setTimeout(() => setLoading(false), 1500);
const workspaces = await getWorkspaces();
const currentWorkspaces = workspaces.map((workspace) => workspace.name);
if (!currentWorkspaces.includes(workspaceName)) {
const newWorkspace = await createWorkspace(
workspaceName,
localStorage.getItem("orgData.id")
);
let newWorkspaceId;
try {
newWorkspaceId = newWorkspace._id;
} catch (error) {
console.log(error);
}
if (addAllUsers) {
let orgUsers = await getOrganizationUsers({
orgId: localStorage.getItem("orgData.id"),
try {
const workspaces = await getWorkspaces();
const currentWorkspaces = workspaces.map((workspace) => workspace.name);
if (!currentWorkspaces.includes(workspaceName)) {
const newWorkspace = await createWorkspace({
workspaceName,
organizationId: tempLocalStorage("orgData.id"),
});
orgUsers.map(async (user) => {
if (user.status == "accepted") {
let result = await addUserToWorkspace(
user.user.email,
newWorkspaceId
);
if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
const newWorkspaceId = newWorkspace._id;
// assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({
ciphertext: result.latestKey.encryptedKey,
nonce: result.latestKey.nonce,
publicKey: result.latestKey.sender.publicKey,
privateKey: PRIVATE_KEY,
});
if (addAllUsers) {
const orgUsers = await getOrganizationUsers({
orgId: tempLocalStorage("orgData.id"),
});
orgUsers.map(async (user: any) => {
if (user.status == "accepted") {
const result = await addUserToWorkspace(
user.user.email,
newWorkspaceId
);
if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = tempLocalStorage("PRIVATE_KEY");
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: key,
publicKey: result.invitee.publicKey,
privateKey: PRIVATE_KEY,
});
// assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({
ciphertext: result.latestKey.encryptedKey,
nonce: result.latestKey.nonce,
publicKey: result.latestKey.sender.publicKey,
privateKey: PRIVATE_KEY,
});
uploadKeys(newWorkspaceId, result.invitee._id, ciphertext, nonce);
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: key,
publicKey: result.invitee.publicKey,
privateKey: PRIVATE_KEY,
}) as { ciphertext: string; nonce: string };
uploadKeys(
newWorkspaceId,
result.invitee._id,
ciphertext,
nonce
);
}
}
}
});
});
}
router.push("/dashboard/" + newWorkspaceId + "?Development");
setIsOpen(false);
setNewWorkspaceName("");
} else {
console.error("A project with this name already exists.");
setError(true);
setLoading(false);
}
router.push("/dashboard/" + newWorkspaceId + "?Development");
setIsOpen(false);
setNewWorkspaceName("");
} else {
setError("A project with this name already exists.");
} catch (err) {
console.error(err);
setError(true);
setLoading(false);
}
}
function openModal() {
setIsOpen(true);
}
const menuItems = [
{
href:
"/dashboard/" + workspaceMapping[workspaceSelected] + "?Development",
"/dashboard/" +
workspaceMapping[workspaceSelected as any] +
"?Development",
title: "Secrets",
emoji: <FontAwesomeIcon icon={faKey} />,
},
{
href: "/users/" + workspaceMapping[workspaceSelected],
href: "/users/" + workspaceMapping[workspaceSelected as any],
title: "Members",
emoji: <FontAwesomeIcon icon={faUser} />,
},
{
href: "/integrations/" + workspaceMapping[workspaceSelected],
href: "/integrations/" + workspaceMapping[workspaceSelected as any],
title: "Integrations",
emoji: <FontAwesomeIcon icon={faPlug} />,
},
{
href: "/settings/project/" + workspaceMapping[workspaceSelected],
href: "/settings/project/" + workspaceMapping[workspaceSelected as any],
title: "Project Settings",
emoji: <FontAwesomeIcon icon={faGear} />,
},
];
useEffect(async () => {
useEffect(() => {
// Put a user in a workspace if they're not in one yet
if (
localStorage.getItem("orgData.id") == null ||
localStorage.getItem("orgData.id") == ""
) {
const userOrgs = await getOrganizations();
localStorage.setItem("orgData.id", userOrgs[0]._id);
}
let orgUserProjects = await getOrganizationUserProjects({
orgId: localStorage.getItem("orgData.id"),
});
let userWorkspaces = orgUserProjects;
if (
userWorkspaces.length == 0 &&
router.asPath != "/noprojects" &&
!router.asPath.includes("settings")
) {
router.push("/noprojects");
} else if (router.asPath != "/noprojects") {
const intendedWorkspaceId = router.asPath
.split("/")[router.asPath.split("/").length - 1].split("?")[0];
// If a user is not a member of a workspace they are trying to access, just push them to one of theirs
if (
intendedWorkspaceId != "heroku" &&
!userWorkspaces
.map((workspace) => workspace._id)
.includes(intendedWorkspaceId)
) {
router.push("/dashboard/" + userWorkspaces[0]._id + "?Development");
} else {
setWorkspaceList(userWorkspaces.map((workspace) => workspace.name));
setWorkspaceMapping(
Object.fromEntries(
userWorkspaces.map((workspace) => [workspace.name, workspace._id])
)
);
setWorkspaceSelected(
Object.fromEntries(
userWorkspaces.map((workspace) => [workspace._id, workspace.name])
)[
router.asPath
.split("/")[router.asPath.split("/").length - 1].split("?")[0]]
);
const putUserInWorkSpace = async () => {
if (tempLocalStorage("orgData.id") === "") {
const userOrgs = await getOrganizations();
localStorage.setItem("orgData.id", userOrgs[0]._id);
}
}
const orgUserProjects = await getOrganizationUserProjects({
orgId: tempLocalStorage("orgData.id"),
});
const userWorkspaces = orgUserProjects;
if (
userWorkspaces.length == 0 &&
router.asPath != "/noprojects" &&
!router.asPath.includes("settings")
) {
router.push("/noprojects");
} else if (router.asPath != "/noprojects") {
const intendedWorkspaceId = router.asPath
.split("/")
[router.asPath.split("/").length - 1].split("?")[0];
// If a user is not a member of a workspace they are trying to access, just push them to one of theirs
if (
intendedWorkspaceId != "heroku" &&
!userWorkspaces
.map((workspace: { _id: string }) => workspace._id)
.includes(intendedWorkspaceId)
) {
router.push("/dashboard/" + userWorkspaces[0]._id + "?Development");
} else {
setWorkspaceList(
userWorkspaces.map((workspace: any) => workspace.name)
);
setWorkspaceMapping(
Object.fromEntries(
userWorkspaces.map((workspace: any) => [
workspace.name,
workspace._id,
])
) as any
);
setWorkspaceSelected(
Object.fromEntries(
userWorkspaces.map((workspace: any) => [
workspace._id,
workspace.name,
])
)[
router.asPath
.split("/")
[router.asPath.split("/").length - 1].split("?")[0]
]
);
}
}
};
putUserInWorkSpace();
}, []);
useEffect(() => {
try {
if (
workspaceMapping[workspaceSelected] &&
workspaceMapping[workspaceSelected] !==
workspaceMapping[Number(workspaceSelected)] &&
`${workspaceMapping[Number(workspaceSelected)]}` !==
router.asPath
.split("/")[router.asPath.split("/").length - 1].split("?")[0]
.split("/")
[router.asPath.split("/").length - 1].split("?")[0]
) {
router.push("/dashboard/" + workspaceMapping[workspaceSelected] + "?Development");
router.push(
"/dashboard/" +
workspaceMapping[Number(workspaceSelected)] +
"?Development"
);
localStorage.setItem(
"projectData.id",
workspaceMapping[workspaceSelected]
`${workspaceMapping[Number(workspaceSelected)]}`
);
}
} catch (error) {
@ -212,18 +246,18 @@ export default function Layout({ children }) {
<nav className="flex flex-col justify-between items-between h-full">
{/* <div className="py-6"></div> */}
<div>
<div className="flex justify-center w-full mt-[4.5rem] mb-6 bg-bunker-600 w-full h-20 flex flex-col items-center px-4">
<div className="flex justify-center w-full mt-[4.5rem] mb-6 bg-bunker-600 h-20 flex-col items-center px-4">
<div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
PROJECT
</div>
{workspaceList.length > 0 ? (
<Listbox
selected={workspaceSelected}
onChange={setWorkspaceSelected}
onChange={setWorkspaceSelected as any}
data={workspaceList}
buttonAction={openModal}
text=""
workspaceMapping={workspaceMapping}
// workspaceMapping={workspaceMapping as any}
/>
) : (
<Button
@ -249,12 +283,18 @@ export default function Layout({ children }) {
className={`flex relative px-0.5 py-2.5 text-white text-sm rounded cursor-pointer bg-primary-50/10`}
>
<div className="absolute top-0 my-1 ml-1 inset-0 bg-primary w-1 rounded-xl mr-1"></div>
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg">{emoji}</p>
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg">
{emoji}
</p>
{title}
</div>
) : router.asPath == "/noprojects" ? (
<div className={`flex p-2.5 text-white text-sm rounded`}>
<p className="w-10 flex items-center justify-center text-lg">{emoji}</p>
<div
className={`flex p-2.5 text-white text-sm rounded`}
>
<p className="w-10 flex items-center justify-center text-lg">
{emoji}
</p>
{title}
</div>
) : (
@ -262,7 +302,9 @@ export default function Layout({ children }) {
<div
className={`flex p-2.5 text-white text-sm rounded cursor-pointer hover:bg-primary-50/5`}
>
<p className="w-10 flex items-center justify-center text-lg">{emoji}</p>
<p className="w-10 flex items-center justify-center text-lg">
{emoji}
</p>
{title}
</div>
</Link>
@ -277,15 +319,21 @@ export default function Layout({ children }) {
className={`flex relative px-0.5 py-2.5 text-white text-sm rounded cursor-pointer bg-primary-50/10`}
>
<div className="absolute top-0 my-1 ml-1 inset-0 bg-primary w-1 rounded-xl mr-1"></div>
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg"><FontAwesomeIcon icon={faBookOpen}/></p>
<p className="w-6 ml-4 mr-2 flex items-center justify-center text-lg">
<FontAwesomeIcon icon={faBookOpen} />
</p>
Infisical Guide
</div>
) : (
<Link href={`/home/` + workspaceMapping[workspaceSelected]}>
<Link
href={`/home/` + workspaceMapping[workspaceSelected as any]}
>
<div
className={`flex p-2.5 text-white text-sm rounded cursor-pointer hover:bg-primary-50/5 mt-max border border-dashed border-bunker-400`}
>
<p className="w-10 flex items-center justify-center text-lg"><FontAwesomeIcon icon={faBookOpen}/></p>
<p className="w-10 flex items-center justify-center text-lg">
<FontAwesomeIcon icon={faBookOpen} />
</p>
Infisical Guide
</div>
</Link>
@ -305,7 +353,7 @@ export default function Layout({ children }) {
<main className="flex-1 bg-bunker-800">{children}</main>
</div>
</div>
<div className="block md:hidden bg-bunker-800 w-screen h-screen flex flex-col justify-center items-center">
<div className="md:hidden bg-bunker-800 w-screen h-screen flex flex-col justify-center items-center">
<FontAwesomeIcon
icon={faMobile}
className="text-gray-300 text-7xl mb-8"

View File

@ -8,14 +8,13 @@ import {
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Listbox, Transition } from "@headlessui/react";
type ListBoxProps = {
selected: string,
onChange: () => void,
data: string[],
text: string,
buttonAction: () => void,
width: string,
interface ListBoxProps {
selected: string;
onChange: () => void;
data: string[];
text: string;
buttonAction: () => void;
isFull?: boolean;
}
/**
@ -35,14 +34,14 @@ export default function ListBox({
data,
text,
buttonAction,
width,
} : ListBoxProps): JSX.Element {
isFull,
}: ListBoxProps): JSX.Element {
return (
<Listbox value={selected} onChange={onChange}>
<div className="relative">
<Listbox.Button
className={`text-gray-400 relative ${
width == "full" ? "w-full" : "w-52"
isFull ? "w-full" : "w-52"
} cursor-default rounded-md bg-white/[0.07] hover:bg-white/[0.11] duration-200 py-2.5 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm`}
>
<div className="flex flex-row">

View File

@ -12,7 +12,7 @@ type ButtonProps = {
text: string;
onButtonPressed: () => void;
loading?: boolean;
color: string;
color?: string;
size: string;
icon?: IconProp;
active?: boolean;

View File

@ -37,7 +37,7 @@ const AddServiceTokenDialog = ({
const [serviceTokenCopied, setServiceTokenCopied] = useState(false);
const generateServiceToken = async () => {
const latestFileKey = await getLatestFileKey(workspaceId);
const latestFileKey = await getLatestFileKey({ workspaceId });
const key = decryptAssymmetric({
ciphertext: latestFileKey.latestKey.encryptedKey,

View File

@ -88,7 +88,7 @@ const UserTable = ({
}, [userData, myUser]);
const grantAccess = async (id, publicKey) => {
let result = await getLatestFileKey(router.query.id);
let result = await getLatestFileKey({workspaceId: router.query.id});
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");

View File

@ -0,0 +1,61 @@
import { useEffect, useRef } from "react";
import { faXmarkCircle } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import classnames from "classnames";
import { Notification as NotificationType } from "./NotificationProvider";
interface NotificationProps {
notification: Required<NotificationType>;
clearNotification: (text: string) => void;
}
const Notification = ({
notification,
clearNotification,
}: NotificationProps) => {
const timeout = useRef<number>();
const handleClearNotification = () => clearNotification(notification.text);
const setNotifTimeout = () => {
timeout.current = window.setTimeout(
handleClearNotification,
notification.timeoutMs
);
};
const cancelNotifTimeout = () => {
clearTimeout(timeout.current);
};
useEffect(() => {
setNotifTimeout();
return cancelNotifTimeout;
}, []);
return (
<div
className={classnames(
"w-full flex items-center justify-between px-4 py-3 rounded pointer-events-auto",
{
"bg-green-600": notification.type === "success",
"bg-red-500": notification.type === "error",
"bg-blue-500": notification.type === "info",
}
)}
role="alert"
>
<p className="text-white text-sm font-bold">{notification.text}</p>
<button
className="bg-white/5 rounded-lg p-3"
onClick={() => clearNotification(notification.text)}
>
<FontAwesomeIcon className="text-white" icon={faXmarkCircle} />
</button>
</div>
);
};
export default Notification;

View File

@ -0,0 +1,69 @@
import { createContext, ReactNode, useContext, useState } from "react";
import Notifications from "./Notifications";
type NotificationType = "success" | "error" | "info";
export type Notification = {
text: string;
type?: NotificationType;
timeoutMs?: number;
};
type NotificationContextState = {
createNotification: (newNotification: Notification) => void;
};
const NotificationContext = createContext<NotificationContextState>({
createNotification: () => console.log("createNotification not set!"),
});
export const useNotificationContext = () => useContext(NotificationContext);
interface NotificationProviderProps {
children: ReactNode;
}
const NotificationProvider = ({ children }: NotificationProviderProps) => {
const [notifications, setNotifications] = useState<Required<Notification>[]>(
[]
);
const clearNotification = (text: string) => {
return setNotifications((state) =>
state.filter((notif) => notif.text !== text)
);
};
const createNotification = ({
text,
type = "success",
timeoutMs = 2000,
}: Notification) => {
const doesNotifExist = notifications.some((notif) => notif.text === text);
if (doesNotifExist) {
return;
}
const newNotification: Required<Notification> = { text, type, timeoutMs };
return setNotifications((state) => [...state, newNotification]);
};
return (
<NotificationContext.Provider
value={{
createNotification,
}}
>
<Notifications
notifications={notifications}
clearNotification={clearNotification}
/>
{children}
</NotificationContext.Provider>
);
};
export default NotificationProvider;

View File

@ -0,0 +1,30 @@
import Notification from "./Notification";
import { Notification as NotificationType } from "./NotificationProvider";
interface NoticationsProps {
notifications: Required<NotificationType>[];
clearNotification: (text: string) => void;
}
const Notifications = ({
notifications,
clearNotification,
}: NoticationsProps) => {
if (!notifications.length) {
return null;
}
return (
<div className="hidden fixed z-50 md:flex md:flex-col-reverse bottom-1 gap-y-2 w-96 h-full right-1 pointer-events-none">
{notifications.map((notif) => (
<Notification
key={notif.text}
notification={notif}
clearNotification={clearNotification}
/>
))}
</div>
);
};
export default Notifications;

View File

@ -25,12 +25,12 @@ export default function NavHeader({ pageName, isProjectRelated } : { pageName: s
useEffect(() => {
(async () => {
const orgId = localStorage.getItem("orgData.id")
let org = await getOrganization({
const org = await getOrganization({
orgId: orgId ? orgId : "",
});
setOrgName(org.name);
let workspace = await getProjectInfo({
const workspace = await getProjectInfo({
projectId: String(router.query.id),
});
setWorkspaceName(workspace.name);

View File

@ -3,7 +3,7 @@ import token from "~/pages/api/auth/Token";
export default class SecurityClient {
static #token = "";
contructor() {}
constructor() {}
static setToken(token) {
this.#token = token;

View File

@ -4,10 +4,10 @@ import login2 from "~/pages/api/auth/Login2";
import getOrganizations from "~/pages/api/organization/getOrgs";
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
import { initPostHog } from "../analytics/posthog";
import pushKeys from "./secrets/pushKeys";
import { ENV } from "./config";
import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
import SecurityClient from "./SecurityClient";
import Telemetry from "./telemetry/Telemetry";
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
@ -32,7 +32,8 @@ const attemptLogin = async (
isLogin
) => {
try {
let userWorkspace, userOrg;
const telemetry = new Telemetry().getInstance();
client.init(
{
username: email,
@ -41,66 +42,38 @@ const attemptLogin = async (
async () => {
const clientPublicKey = client.getPublicKey();
let serverPublicKey, salt;
try {
let res = await login1(email, clientPublicKey);
res = await res.json();
serverPublicKey = res.serverPublicKey;
salt = res.salt;
} catch (err) {
setErrorLogin(true);
console.log("Wrong password", err);
}
const { serverPublicKey, salt } = await login1(email, clientPublicKey);
let response;
try {
client.setSalt(salt);
client.setServerPublicKey(serverPublicKey);
const clientProof = client.getProof(); // called M1
response = await login2(email, clientProof);
} catch (err) {
setErrorLogin(true);
console.log("Password verification failed");
}
// if everything works, go the main dashboard page.
try {
if (response.status == "200") {
response = await response.json();
SecurityClient.setToken(response["token"]);
const publicKey = response["publicKey"];
const encryptedPrivateKey = response["encryptedPrivateKey"];
const iv = response["iv"];
const tag = response["tag"];
// if everything works, go the main dashboard page.
const { token, publicKey, encryptedPrivateKey, iv, tag } =
await login2(email, clientProof);
SecurityClient.setToken(token);
const PRIVATE_KEY = Aes256Gcm.decrypt(
encryptedPrivateKey,
iv,
tag,
password
.slice(0, 32)
.padStart(
32 +
(password.slice(0, 32).length - new Blob([password]).size),
"0"
)
);
const privateKey = Aes256Gcm.decrypt(
encryptedPrivateKey,
iv,
tag,
password
.slice(0, 32)
.padStart(
32 + (password.slice(0, 32).length - new Blob([password]).size),
"0"
)
);
try {
localStorage.setItem("publicKey", publicKey);
localStorage.setItem("encryptedPrivateKey", encryptedPrivateKey);
localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag);
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
} catch (err) {
setErrorLogin(true);
console.error(
"Unable to send the tokens in local storage:" + err.message
);
}
} else {
setErrorLogin(true);
}
saveTokenToLocalStorage({
token,
publicKey,
encryptedPrivateKey,
iv,
tag,
privateKey,
});
const userOrgs = await getOrganizations();
const userOrgsData = userOrgs.map((org) => org._id);
@ -134,20 +107,14 @@ const attemptLogin = async (
// If user is logging in for the first time, add the example keys
if (isSignUp) {
await pushKeys(
{
await pushKeys({
obj: {
DATABASE_URL: [
"mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net",
"personal",
],
DB_USERNAME: [
"user1234",
"personal",
],
DB_PASSWORD: [
"ah8jak3hk8dhiu4dw7whxwe1l",
"personal",
],
DB_USERNAME: ["user1234", "personal"],
DB_PASSWORD: ["ah8jak3hk8dhiu4dw7whxwe1l", "personal"],
TWILIO_AUTH_TOKEN: [
"hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG",
"shared",
@ -155,20 +122,13 @@ const attemptLogin = async (
WEBSITE_URL: ["http://localhost:3000", "shared"],
STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
},
projectToLogin,
"Development"
);
workspaceId: projectToLogin,
env: "Development",
});
}
try {
if (email) {
if (ENV == "production") {
const posthog = initPostHog();
posthog.identify(email);
posthog.capture("User Logged In");
}
}
} catch (error) {
console.log("posthog", error);
if (email) {
telemetry.identify(email);
telemetry.capture("User Logged In");
}
if (isLogin) {

View File

@ -1,18 +1,21 @@
interface PasswordCheckProps {
password: string;
currentErrorCheck: boolean;
setPasswordErrorLength: (value: boolean) => void;
setPasswordErrorNumber: (value: boolean) => void;
setPasswordErrorLowerCase: (value: boolean) => void;
}
/**
* This function checks a user password with respect to some criteria.
* @param {*} password
* @param {*} setPasswordError
* @param {*} setPasswordErrorMessage
* @param {*} currentErrorCheck
* @returns
*/
const passwordCheck = (
const passwordCheck = ({
password,
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
currentErrorCheck
) => {
currentErrorCheck,
}: PasswordCheckProps) => {
let errorCheck = currentErrorCheck;
if (!password || password.length < 14) {
setPasswordErrorLength(true);

View File

@ -0,0 +1,11 @@
// this is temporary util function. create error handling logic for localStorage and delete this.
export const tempLocalStorage = (key: string) => {
const value = localStorage.getItem(key);
if (value === null || value === "") {
console.warn("No value found in localStorage for key");
return "";
}
return value;
};

View File

@ -4,8 +4,6 @@ const POSTHOG_HOST =
process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
const STRIPE_PRODUCT_PRO = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_PRO!;
const STRIPE_PRODUCT_STARTER = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_STARTER!;
const TELEMETRY_ENABLED =
process.env.NEXT_PUBLIC_TELEMETRY_ENABLED! !== "false";
export {
ENV,
@ -13,5 +11,4 @@ export {
POSTHOG_HOST,
STRIPE_PRODUCT_PRO,
STRIPE_PRODUCT_STARTER,
TELEMETRY_ENABLED,
};

View File

@ -0,0 +1,29 @@
interface Props {
publicKey: string;
encryptedPrivateKey: string;
iv: string;
tag: string;
privateTag: string;
}
export const saveTokenToLocalStorage = ({
publicKey,
encryptedPrivateKey,
iv,
tag,
privateTag,
}: Props) => {
try {
localStorage.setItem("publicKey", publicKey);
localStorage.setItem("encryptedPrivateKey", encryptedPrivateKey);
localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag);
localStorage.setItem("PRIVATE_KEY", privateTag);
} catch (err) {
if (err instanceof Error) {
throw new Error(
"Unable to send the tokens in local storage:" + err.message
);
}
}
};

View File

@ -7,20 +7,30 @@ import { envMapping } from "../../../public/data/frequentConstants";
const crypto = require("crypto");
const {
decryptAssymmetric,
decryptSymmetric,
encryptSymmetric,
encryptAssymmetric,
} = require("../cryptography/crypto");
const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util");
export interface IK {
publicKey: string;
userId: string;
}
const pushKeys = async (obj, workspaceId, env) => {
let sharedKey = await getLatestFileKey(workspaceId);
/**
* This function pushes the keys to the database after decrypting them end-to-end
* @param {object} obj
* @param {object} obj.obj - object with all the key pairs
* @param {object} obj.workspaceId - the id of a project to which a user is pushing
* @param {object} obj.env - which environment a user is pushing to
*/
const pushKeys = async({ obj, workspaceId, env }: { obj: object; workspaceId: string; env: string; }) => {
const sharedKey = await getLatestFileKey({ workspaceId });
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY");
let randomBytes;
let randomBytes: string;
if (Object.keys(sharedKey).length > 0) {
// case: a (shared) key exists for the workspace
randomBytes = decryptAssymmetric({
@ -51,11 +61,11 @@ const pushKeys = async (obj, workspaceId, env) => {
iv: ivValue,
tag: tagValue,
} = encryptSymmetric({
plaintext: obj[key][0],
plaintext: obj[key as keyof typeof obj][0],
key: randomBytes,
});
const visibility = obj[key][1] != null ? obj[key][1] : "personal";
const visibility = obj[key as keyof typeof obj][1] != null ? obj[key as keyof typeof obj][1] : "personal";
return {
ciphertextKey,
@ -65,7 +75,7 @@ const pushKeys = async (obj, workspaceId, env) => {
ciphertextValue,
ivValue,
tagValue,
hashValue: crypto.createHash("sha256").update(obj[key][0]).digest("hex"),
hashValue: crypto.createHash("sha256").update(obj[key as keyof typeof obj][0]).digest("hex"),
type: visibility,
};
});
@ -76,7 +86,7 @@ const pushKeys = async (obj, workspaceId, env) => {
});
// assymmetrically encrypt key with each receiver public keys
const keys = publicKeys.map((k) => {
const keys = publicKeys.map((k: IK) => {
const { ciphertext, nonce } = encryptAssymmetric({
plaintext: randomBytes,
publicKey: k.publicKey,
@ -95,7 +105,7 @@ const pushKeys = async (obj, workspaceId, env) => {
workspaceId,
secrets,
keys,
environment: envMapping[env],
environment: envMapping[env as keyof typeof envMapping],
});
};

View File

@ -0,0 +1,44 @@
/* eslint-disable */
import { initPostHog } from "~/components/analytics/posthog";
import { ENV } from "~/components/utilities/config";
class Capturer {
constructor() {
this.api = initPostHog();
}
capture(item) {
if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) {
try {
api.capture(item);
} catch (error) {
console.error("PostHog", error);
}
}
}
identify(id) {
if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) {
try {
api.identify(id);
} catch (error) {
console.error("PostHog", error);
}
}
}
}
class Telemetry {
constructor() {
if (!Telemetry.instance) {
Telemetry.instance = new Capturer();
}
}
getInstance() {
return Telemetry.instance;
}
}
module.exports = Telemetry;

View File

@ -50,13 +50,13 @@
"devDependencies": {
"@tailwindcss/typography": "^0.5.4",
"@types/node": "18.11.9",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "^10.4.7",
"eslint": "^8.29.0",
"eslint-config-next": "^13.0.5",
"eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^8.0.0",
"postcss": "^8.4.14",
"prettier": "2.7.1",
@ -64,6 +64,32 @@
"typescript": "^4.9.3"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"peer": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"peer": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
@ -75,12 +101,83 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/generator": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz",
"integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==",
"node_modules/@babel/compat-data": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
"peer": true,
"dependencies": {
"@babel/types": "^7.19.0",
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.20.5",
"@babel/helper-compilation-targets": "^7.20.0",
"@babel/helper-module-transforms": "^7.20.2",
"@babel/helpers": "^7.20.5",
"@babel/parser": "^7.20.5",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
"@babel/types": "^7.20.5",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.1",
"semver": "^6.3.0"
},
"engines": {
"node": ">=6.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/babel"
}
},
"node_modules/@babel/core/node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"peer": true,
"dependencies": {
"ms": "2.1.2"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/@babel/core/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"peer": true
},
"node_modules/@babel/core/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/generator": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
"dependencies": {
"@babel/types": "^7.20.5",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
},
@ -99,6 +196,33 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.20.0",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz",
"integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==",
"peer": true,
"dependencies": {
"@babel/compat-data": "^7.20.0",
"@babel/helper-validator-option": "^7.18.6",
"browserslist": "^4.21.3",
"semver": "^6.3.0"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"peer": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-environment-visitor": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
@ -141,6 +265,25 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz",
"integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==",
"peer": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
"@babel/helper-simple-access": "^7.20.2",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.1",
"@babel/types": "^7.20.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
@ -149,6 +292,18 @@
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-simple-access": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
"peer": true,
"dependencies": {
"@babel/types": "^7.20.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
@ -161,17 +316,40 @@
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==",
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz",
"integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==",
"peer": true,
"dependencies": {
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
"@babel/types": "^7.20.5"
},
"engines": {
"node": ">=6.9.0"
}
@ -190,9 +368,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz",
"integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==",
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
"bin": {
"parser": "bin/babel-parser.js"
},
@ -252,18 +430,18 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz",
"integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==",
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"dependencies": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.19.0",
"@babel/generator": "^7.20.5",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.19.1",
"@babel/types": "^7.19.0",
"@babel/parser": "^7.20.5",
"@babel/types": "^7.20.5",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@ -293,12 +471,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/@babel/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz",
"integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==",
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"dependencies": {
"@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
},
"engines": {
@ -1143,9 +1321,9 @@
"optional": true
},
"node_modules/@types/react": {
"version": "18.0.15",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
"version": "18.0.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
"dependencies": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@ -1882,7 +2060,6 @@
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
"integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -2472,8 +2649,7 @@
"node_modules/electron-to-chromium": {
"version": "1.4.206",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz",
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==",
"dev": true
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA=="
},
"node_modules/emoji-regex": {
"version": "9.2.2",
@ -2595,7 +2771,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -2901,27 +3076,6 @@
"semver": "bin/semver.js"
}
},
"node_modules/eslint-plugin-prettier": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
"dev": true,
"dependencies": {
"prettier-linter-helpers": "^1.0.0"
},
"engines": {
"node": ">=12.0.0"
},
"peerDependencies": {
"eslint": ">=7.28.0",
"prettier": ">=2.0.0"
},
"peerDependenciesMeta": {
"eslint-config-prettier": {
"optional": true
}
}
},
"node_modules/eslint-plugin-react": {
"version": "7.31.11",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz",
@ -3289,12 +3443,6 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"node_modules/fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"node_modules/fast-glob": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@ -3523,6 +3671,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/get-intrinsic": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
@ -4253,6 +4410,18 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"peer": true,
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/jsonp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
@ -5153,8 +5322,7 @@
"node_modules/node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
},
"node_modules/normalize-path": {
"version": "3.0.0",
@ -5624,18 +5792,6 @@
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"dependencies": {
"fast-diff": "^1.1.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -7042,7 +7198,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
"integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -7248,6 +7403,28 @@
}
},
"dependencies": {
"@ampproject/remapping": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"peer": true,
"requires": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
},
"dependencies": {
"@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"peer": true,
"requires": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
}
}
},
"@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
@ -7256,12 +7433,64 @@
"@babel/highlight": "^7.18.6"
}
},
"@babel/generator": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz",
"integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==",
"@babel/compat-data": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==",
"peer": true
},
"@babel/core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
"peer": true,
"requires": {
"@babel/types": "^7.19.0",
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.20.5",
"@babel/helper-compilation-targets": "^7.20.0",
"@babel/helper-module-transforms": "^7.20.2",
"@babel/helpers": "^7.20.5",
"@babel/parser": "^7.20.5",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
"@babel/types": "^7.20.5",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.1",
"semver": "^6.3.0"
},
"dependencies": {
"debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"peer": true,
"requires": {
"ms": "2.1.2"
}
},
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"peer": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"peer": true
}
}
},
"@babel/generator": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz",
"integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==",
"requires": {
"@babel/types": "^7.20.5",
"@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1"
}
@ -7274,6 +7503,26 @@
"@babel/types": "^7.18.6"
}
},
"@babel/helper-compilation-targets": {
"version": "7.20.0",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.0.tgz",
"integrity": "sha512-0jp//vDGp9e8hZzBc6N/KwA5ZK3Wsm/pfm4CrY7vzegkVxc65SgSn6wYOnwHe9Js9HRQ1YTCKLGPzDtaS3RoLQ==",
"peer": true,
"requires": {
"@babel/compat-data": "^7.20.0",
"@babel/helper-validator-option": "^7.18.6",
"browserslist": "^4.21.3",
"semver": "^6.3.0"
},
"dependencies": {
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"peer": true
}
}
},
"@babel/helper-environment-visitor": {
"version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz",
@ -7304,11 +7553,36 @@
"@babel/types": "^7.18.6"
}
},
"@babel/helper-module-transforms": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.2.tgz",
"integrity": "sha512-zvBKyJXRbmK07XhMuujYoJ48B5yvvmM6+wcpv6Ivj4Yg6qO7NOZOSnvZN9CRl1zz1Z4cKf8YejmCMh8clOoOeA==",
"peer": true,
"requires": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
"@babel/helper-simple-access": "^7.20.2",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/helper-validator-identifier": "^7.19.1",
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.1",
"@babel/types": "^7.20.2"
}
},
"@babel/helper-plugin-utils": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
"integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw=="
},
"@babel/helper-simple-access": {
"version": "7.20.2",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz",
"integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==",
"peer": true,
"requires": {
"@babel/types": "^7.20.2"
}
},
"@babel/helper-split-export-declaration": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz",
@ -7318,14 +7592,31 @@
}
},
"@babel/helper-string-parser": {
"version": "7.18.10",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw=="
"version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
},
"@babel/helper-validator-identifier": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz",
"integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w=="
},
"@babel/helper-validator-option": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g=="
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"peer": true
},
"@babel/helpers": {
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz",
"integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==",
"peer": true,
"requires": {
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
"@babel/types": "^7.20.5"
}
},
"@babel/highlight": {
"version": "7.18.6",
@ -7338,9 +7629,9 @@
}
},
"@babel/parser": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz",
"integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A=="
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA=="
},
"@babel/plugin-syntax-jsx": {
"version": "7.18.6",
@ -7379,18 +7670,18 @@
}
},
"@babel/traverse": {
"version": "7.19.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz",
"integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==",
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"requires": {
"@babel/code-frame": "^7.18.6",
"@babel/generator": "^7.19.0",
"@babel/generator": "^7.20.5",
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.19.1",
"@babel/types": "^7.19.0",
"@babel/parser": "^7.20.5",
"@babel/types": "^7.20.5",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@ -7411,12 +7702,12 @@
}
},
"@babel/types": {
"version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz",
"integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==",
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"requires": {
"@babel/helper-string-parser": "^7.18.10",
"@babel/helper-validator-identifier": "^7.18.6",
"@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0"
}
},
@ -7666,7 +7957,8 @@
"@headlessui/react": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz",
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q=="
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==",
"requires": {}
},
"@humanwhocodes/config-array": {
"version": "0.11.7",
@ -8007,9 +8299,9 @@
"optional": true
},
"@types/react": {
"version": "18.0.15",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz",
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==",
"version": "18.0.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
"integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
"requires": {
"@types/prop-types": "*",
"@types/scheduler": "*",
@ -8247,7 +8539,8 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true
"dev": true,
"requires": {}
},
"acorn-node": {
"version": "1.8.2",
@ -8450,7 +8743,8 @@
"axios-auth-refresh": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/axios-auth-refresh/-/axios-auth-refresh-3.3.3.tgz",
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg=="
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg==",
"requires": {}
},
"axobject-query": {
"version": "2.2.0",
@ -8531,7 +8825,6 @@
"version": "4.21.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
"integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001370",
"electron-to-chromium": "^1.4.202",
@ -8980,8 +9273,7 @@
"electron-to-chromium": {
"version": "1.4.206",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz",
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==",
"dev": true
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA=="
},
"emoji-regex": {
"version": "9.2.2",
@ -9082,8 +9374,7 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
},
"escape-string-regexp": {
"version": "1.0.5",
@ -9400,15 +9691,6 @@
}
}
},
"eslint-plugin-prettier": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz",
"integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==",
"dev": true,
"requires": {
"prettier-linter-helpers": "^1.0.0"
}
},
"eslint-plugin-react": {
"version": "7.31.11",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz",
@ -9464,13 +9746,15 @@
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
"dev": true
"dev": true,
"requires": {}
},
"eslint-plugin-simple-import-sort": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
"integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
"dev": true
"dev": true,
"requires": {}
},
"eslint-scope": {
"version": "7.1.1",
@ -9583,12 +9867,6 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true
},
"fast-diff": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz",
"integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==",
"dev": true
},
"fast-glob": {
"version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@ -9755,6 +10033,12 @@
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true
},
"gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"peer": true
},
"get-intrinsic": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
@ -10269,6 +10553,12 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true
},
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"peer": true
},
"jsonp": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
@ -10854,8 +11144,7 @@
"node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
},
"normalize-path": {
"version": "3.0.0",
@ -11161,15 +11450,6 @@
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true
},
"prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"requires": {
"fast-diff": "^1.1.2"
}
},
"process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@ -11441,7 +11721,8 @@
"react-table": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA=="
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==",
"requires": {}
},
"read-cache": {
"version": "1.0.0",
@ -11482,7 +11763,8 @@
"redux-thunk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q=="
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
"requires": {}
},
"regenerator-runtime": {
"version": "0.13.11",
@ -11834,7 +12116,8 @@
"styled-jsx": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA=="
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
"requires": {}
},
"stylis": {
"version": "4.0.13",
@ -12179,7 +12462,6 @@
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
"integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
"dev": true,
"requires": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
@ -12197,12 +12479,14 @@
"use-memo-one": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ=="
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
"requires": {}
},
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
},
"util-deprecate": {
"version": "1.0.2",

View File

@ -53,6 +53,7 @@
"devDependencies": {
"@tailwindcss/typography": "^0.5.4",
"@types/node": "18.11.9",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "^10.4.7",

View File

@ -2,11 +2,11 @@ import { useEffect } from "react";
import { useRouter } from "next/router";
import { config } from "@fortawesome/fontawesome-svg-core";
import { initPostHog } from "~/components/analytics/posthog";
import Layout from "~/components/basic/layout";
import Layout from "~/components/basic/Layout";
import NotificationProvider from "~/components/context/Notifications/NotificationProvider";
import RouteGuard from "~/components/RouteGuard";
import { publicPaths } from "~/const";
import { ENV } from "~/utilities/config";
import Telemetry from "~/utilities/telemetry/Telemetry";
import "@fortawesome/fontawesome-svg-core/styles.css";
import "../styles/globals.css";
@ -15,17 +15,14 @@ config.autoAddCss = false;
const App = ({ Component, pageProps, ...appProps }) => {
const router = useRouter();
const posthog = initPostHog();
useEffect(() => {
// Init for auto capturing
const posthog = initPostHog();
const telemetry = new Telemetry().getInstance();
const handleRouteChange = () => {
if (typeof window !== "undefined") {
if (ENV == "production") {
posthog.capture("$pageview");
}
telemetry.capture("$pageview");
}
};
@ -46,9 +43,11 @@ const App = ({ Component, pageProps, ...appProps }) => {
return (
<RouteGuard>
<Layout>
<Component {...pageProps} />
</Layout>
<NotificationProvider>
<Layout>
<Component {...pageProps} />
</Layout>
</NotificationProvider>
</RouteGuard>
);
};

View File

@ -1,20 +0,0 @@
/**
* This is the first step of the login process (pake)
* @param {*} email
* @param {*} clientPublicKey
* @returns
*/
const login1 = (email, clientPublicKey) => {
return fetch("/api/v1/auth/login1", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: email,
clientPublicKey,
}),
});
};
export default login1;

View File

@ -0,0 +1,32 @@
interface Login1 {
serverPublicKey: string;
salt: string;
}
/**
* This is the first step of the login process (pake)
* @param {*} email
* @param {*} clientPublicKey
* @returns
*/
const login1 = async (email: string, clientPublicKey: string) => {
const response = await fetch("/api/v1/auth/login1", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: email,
clientPublicKey,
}),
});
// need precise error handling about the status code
if (response?.status === 200) {
const data = (await response.json()) as unknown as Login1;
return data;
}
throw new Error("Wrong password");
};
export default login1;

View File

@ -1,28 +0,0 @@
/**
* This is the second step of the login process
* @param {*} email
* @param {*} clientPublicKey
* @returns
*/
const login2 = (email, clientProof) => {
return fetch("/api/v1/auth/login2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: email,
clientProof,
}),
credentials: "include",
}).then((res) => {
if (res.status == 200) {
console.log("User logged in", res);
return res;
} else {
console.log("Failed to log in");
}
});
};
export default login2;

View File

@ -0,0 +1,36 @@
interface Login2Response {
encryptedPrivateKey: string;
iv: string;
publicKey: string;
tag: string;
token: string;
}
/**
* This is the second step of the login process
* @param {*} email
* @param {*} clientPublicKey
* @returns
*/
const login2 = async (email: string, clientProof: string) => {
const response = await fetch("/api/v1/auth/login2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
email: email,
clientProof,
}),
credentials: "include",
});
// need precise error handling about the status code
if (response.status == 200) {
const data = (await response.json()) as unknown as Login2Response;
return data;
}
throw new Error("Password verification failed");
};
export default login2;

View File

@ -6,7 +6,7 @@ import SecurityClient from "~/utilities/SecurityClient";
* @param {*} res
* @returns
*/
const getOrganizationUserProjects = (req, res) => {
const getOrganizationUserProjects = (req) => {
return SecurityClient.fetchCall(
"/api/v1/organization/" + req.orgId + "/my-workspaces",
{

View File

@ -6,7 +6,7 @@ import SecurityClient from "~/utilities/SecurityClient";
* @param {string} obj.orgId - organization Id
* @returns
*/
const getOrganizationUsers = ({ orgId }) => {
const getOrganizationUsers = ({ orgId }: { orgId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/organization/" + orgId + "/users",
{
@ -16,7 +16,7 @@ const getOrganizationUsers = ({ orgId }) => {
},
}
).then(async (res) => {
if (res.status == 200) {
if (res?.status == 200) {
return (await res.json()).users;
} else {
console.log("Failed to get org users");

View File

@ -1,11 +1,12 @@
import SecurityClient from "~/utilities/SecurityClient";
/**
* This route creates a new workspace for a user.
* @param {*} workspaceName
* This route creates a new workspace for a user within a certain organization.
* @param {string} workspaceName - project Name
* @param {string} organizationId - org ID
* @returns
*/
const createWorkspace = (workspaceName, organizationId) => {
const createWorkspace = ( { workspaceName, organizationId }: { workspaceName: string; organizationId: string; }) => {
return SecurityClient.fetchCall("/api/v1/workspace", {
method: "POST",
headers: {
@ -16,7 +17,7 @@ const createWorkspace = (workspaceName, organizationId) => {
organizationId: organizationId,
}),
}).then(async (res) => {
if (res.status == 200) {
if (res?.status == 200) {
return (await res.json()).workspace;
} else {
console.log("Failed to create a project");

View File

@ -2,10 +2,10 @@ import SecurityClient from "~/utilities/SecurityClient";
/**
* Get the latest key pairs from a certain workspace
* @param {*} workspaceId
* @param {string} workspaceId
* @returns
*/
const getLatestFileKey = (workspaceId) => {
const getLatestFileKey = ({ workspaceId } : { workspaceId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/key/" + workspaceId + "/latest",
{
@ -15,7 +15,7 @@ const getLatestFileKey = (workspaceId) => {
},
}
).then(async (res) => {
if (res.status == 200) {
if (res?.status == 200) {
return await res.json();
} else {
console.log("Failed to get the latest key pairs for a certain project");

View File

@ -2,13 +2,12 @@ import SecurityClient from "~/utilities/SecurityClient";
/**
* This route lets us get the public keys of everyone in your workspace.
* @param {*} req
* @param {*} res
* @param {string} workspaceId
* @returns
*/
const getWorkspaceKeys = (req, res) => {
const getWorkspaceKeys = ({ workspaceId }: { workspaceId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/workspace/" + req.workspaceId + "/keys",
"/api/v1/workspace/" + workspaceId + "/keys",
{
method: "GET",
headers: {
@ -16,7 +15,7 @@ const getWorkspaceKeys = (req, res) => {
},
}
).then(async (res) => {
if (res.status == 200) {
if (res?.status == 200) {
return (await res.json()).publicKeys;
} else {
console.log("Failed to get the public keys of everyone in the workspace");

View File

@ -2,13 +2,12 @@ import SecurityClient from "~/utilities/SecurityClient";
/**
* This route lets us get all the users in the workspace.
* @param {*} req
* @param {*} res
* @param {string} workspaceId - workspace ID
* @returns
*/
const getWorkspaceUsers = (req, res) => {
const getWorkspaceUsers = ({ workspaceId }: { workspaceId: string; }) => {
return SecurityClient.fetchCall(
"/api/v1/workspace/" + req.workspaceId + "/users",
"/api/v1/workspace/" + workspaceId + "/users",
{
method: "GET",
headers: {
@ -16,7 +15,7 @@ const getWorkspaceUsers = (req, res) => {
},
}
).then(async (res) => {
if (res.status == 200) {
if (res?.status == 200) {
return (await res.json()).users;
} else {
console.log("Failed to get Project Users");

View File

@ -1,24 +0,0 @@
import SecurityClient from "~/utilities/SecurityClient";
/**
* This route lets us get the public keys of everyone in your workspace.
* @param {*} req
* @param {*} res
* @returns
*/
const getWorkspaces = (req, res) => {
return SecurityClient.fetchCall("/api/v1/workspace", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
}).then(async (res) => {
if (res.status == 200) {
return (await res.json()).workspaces;
} else {
console.log("Failed to get projects");
}
});
};
export default getWorkspaces;

View File

@ -0,0 +1,30 @@
import SecurityClient from "~/utilities/SecurityClient";
interface Workspace {
__v: number;
_id: string;
name: string;
organization: string;
}
/**
* This route lets us get the workspaces of a certain user
* @returns
*/
const getWorkspaces = () => {
return SecurityClient.fetchCall("/api/v1/workspace", {
method: "GET",
headers: {
"Content-Type": "application/json",
},
}).then(async (res) => {
if (res?.status == 200) {
const data = (await res.json()) as unknown as { workspaces: Workspace[] };
return data.workspaces;
}
throw new Error("Failed to get projects");
});
};
export default getWorkspaces;

View File

@ -26,6 +26,7 @@ import { Menu, Transition } from "@headlessui/react";
import Button from "~/components/basic/buttons/Button";
import ListBox from "~/components/basic/Listbox";
import BottonRightPopup from "~/components/basic/popups/BottomRightPopup";
import { useNotificationContext } from "~/components/context/Notifications/NotificationProvider";
import DashboardInputField from "~/components/dashboard/DashboardInputField";
import DropZone from "~/components/dashboard/DropZone";
import NavHeader from "~/components/navigation/NavHeader";
@ -60,7 +61,7 @@ const KeyPair = ({
modifyValue,
modifyVisibility,
isBlurred,
duplicates
duplicates,
}) => {
const [randomStringLength, setRandomStringLength] = useState(32);
@ -227,6 +228,8 @@ export default function Dashboard() {
const [checkDocsPopUpVisible, setCheckDocsPopUpVisible] = useState(false);
const [hasUserEverPushed, setHasUserEverPushed] = useState(false);
const { createNotification } = useNotificationContext();
// #TODO: fix save message for changing reroutes
// const beforeRouteHandler = (url) => {
// const warningText =
@ -370,46 +373,61 @@ export default function Dashboard() {
);
// Checking if any of the secret keys start with a number - if so, don't do anything
const nameErrors = !Object.keys(obj).map(key => !isNaN(key.charAt(0))).every(v => v === false);
const duplicatesExist = data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item)).length > 0;
const nameErrors = !Object.keys(obj)
.map((key) => !isNaN(key.charAt(0)))
.every((v) => v === false);
const duplicatesExist =
data
?.map((item) => item[2])
.filter(
(item, index) => index !== data?.map((item) => item[2]).indexOf(item)
).length > 0;
if (nameErrors) {
console.log("Solve all name errors first!");
} else if (duplicatesExist) {
console.log("Remove the duplicated entries first!");
} else {
// Once "Save changed is clicked", disable that button
setButtonReady(false);
pushKeys(obj, router.query.id, env);
/**
* Check which integrations are active for this project and environment
* If there are any, update environment variables for those integrations
*/
let integrations = await getWorkspaceIntegrations({
workspaceId: router.query.id,
});
integrations.map(async (integration) => {
if (
envMapping[env] == integration.environment &&
integration.isActive == true
) {
let objIntegration = Object.assign(
{},
...data.map((row) => ({ [row[2]]: row[3] }))
);
await pushKeysIntegration({
obj: objIntegration,
integrationId: integration._id,
});
}
return createNotification({
text: "Solve all name errors first!",
type: "error",
});
}
// If this user has never saved environment variables before, show them a prompt to read docs
if (!hasUserEverPushed) {
setCheckDocsPopUpVisible(true);
await registerUserAction({ action: "first_time_secrets_pushed" });
if (duplicatesExist) {
return createNotification({
text: "Your secrets weren't saved; please fix the conflicts first.",
type: "error",
});
}
// Once "Save changed is clicked", disable that button
setButtonReady(false);
pushKeys({ obj, workspaceId: router.query.id, env });
/**
* Check which integrations are active for this project and environment
* If there are any, update environment variables for those integrations
*/
let integrations = await getWorkspaceIntegrations({
workspaceId: router.query.id,
});
integrations.map(async (integration) => {
if (
envMapping[env] == integration.environment &&
integration.isActive == true
) {
let objIntegration = Object.assign(
{},
...data.map((row) => ({ [row[2]]: row[3] }))
);
await pushKeysIntegration({
obj: objIntegration,
integrationId: integration._id,
});
}
});
// If this user has never saved environment variables before, show them a prompt to read docs
if (!hasUserEverPushed) {
setCheckDocsPopUpVisible(true);
await registerUserAction({ action: "first_time_secrets_pushed" });
}
};
@ -649,7 +667,13 @@ export default function Dashboard() {
modifyKey={listenChangeKey}
modifyVisibility={listenChangeVisibility}
isBlurred={blurred}
duplicates={data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item))}
duplicates={data
?.map((item) => item[2])
.filter(
(item, index) =>
index !==
data?.map((item) => item[2]).indexOf(item)
)}
/>
))}
</div>
@ -697,7 +721,13 @@ export default function Dashboard() {
modifyKey={listenChangeKey}
modifyVisibility={listenChangeVisibility}
isBlurred={blurred}
duplicates={data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item))}
duplicates={data
?.map((item) => item[2])
.filter(
(item, index) =>
index !==
data?.map((item) => item[2]).indexOf(item)
)}
/>
))}
</div>

View File

@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from "react";
import ReactCodeInput from "react-code-input";
import dynamic from "next/dynamic";
import Head from "next/head";
import Image from "next/image";
@ -20,7 +21,7 @@ import completeAccountInformationSignup from "./api/auth/CompleteAccountInformat
import sendVerificationEmail from "./api/auth/SendVerificationEmail";
import getWorkspaces from "./api/workspace/getWorkspaces";
const ReactCodeInput = dynamic(import("react-code-input"));
// const ReactCodeInput = dynamic(import("react-code-input"));
const nacl = require("tweetnacl");
const jsrp = require("jsrp");
nacl.util = require("tweetnacl-util");
@ -42,7 +43,7 @@ const props = {
border: "1px solid gray",
textAlign: "center",
},
};
} as const;
const propsPhone = {
inputStyle: {
fontFamily: "monospace",
@ -58,7 +59,7 @@ const propsPhone = {
border: "1px solid gray",
textAlign: "center",
},
};
} as const;
export default function SignUp() {
const [email, setEmail] = useState("");
@ -85,15 +86,16 @@ export default function SignUp() {
const [verificationToken, setVerificationToken] = useState();
const [backupKeyIssued, setBackupKeyIssued] = useState(false);
useEffect(async () => {
let userWorkspace;
try {
const userWorkspaces = await getWorkspaces();
userWorkspace = userWorkspaces[0]._id;
router.push("/dashboard/" + userWorkspace);
} catch (error) {
console.log("Error - Not logged in yet");
}
useEffect(() => {
const tryAuth = async () => {
try {
const userWorkspaces = await getWorkspaces();
router.push("/dashboard/" + userWorkspaces[0]._id);
} catch (error) {
console.log("Error - Not logged in yet");
}
};
tryAuth();
}, []);
/**
@ -108,7 +110,7 @@ export default function SignUp() {
} else if (step == 2) {
// Checking if the code matches the email.
const response = await checkEmailVerificationCode(email, code);
if (response.status == "200" || code == "111222") {
if (response.status === 200 || code == "111222") {
setVerificationToken((await response.json()).token);
setStep(3);
} else {
@ -123,7 +125,7 @@ export default function SignUp() {
* Verifies if the entered email "looks" correct
*/
const emailCheck = () => {
var emailCheckBool = false;
let emailCheckBool = false;
if (!email) {
setEmailError(true);
setEmailErrorMessage("Please enter your email.");
@ -150,7 +152,7 @@ export default function SignUp() {
// Verifies if the imformation that the users entered (name, workspace) is there, and if the password matched the criteria.
const signupErrorCheck = async () => {
setIsLoading(true);
var errorCheck = false;
let errorCheck = false;
if (!firstName) {
setFirstNameError(true);
errorCheck = true;
@ -163,13 +165,13 @@ export default function SignUp() {
} else {
setLastNameError(false);
}
errorCheck = passwordCheck(
errorCheck = passwordCheck({
password,
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
errorCheck
);
currentErrorCheck: errorCheck,
});
if (!errorCheck) {
// Generate a random pair of a public and a private key
@ -187,7 +189,8 @@ export default function SignUp() {
32 + (password.slice(0, 32).length - new Blob([password]).size),
"0"
)
);
) as { ciphertext: string; iv: string; tag: string };
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
client.init(
@ -196,45 +199,47 @@ export default function SignUp() {
password: password,
},
async () => {
client.createVerifier(async (err, result) => {
let response = await completeAccountInformationSignup({
email,
firstName,
lastName,
organizationName: firstName + "'s organization",
publicKey: PUBLIC_KEY,
ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
token: verificationToken,
});
client.createVerifier(
async (err: any, result: { salt: string; verifier: string }) => {
const response = await completeAccountInformationSignup({
email,
firstName,
lastName,
organizationName: firstName + "'s organization",
publicKey: PUBLIC_KEY,
ciphertext,
iv,
tag,
salt: result.salt,
verifier: result.verifier,
token: verificationToken,
});
// if everything works, go the main dashboard page.
if (!errorCheck && response.status == "200") {
response = await response.json();
// if everything works, go the main dashboard page.
if (response.status === 200) {
// response = await response.json();
localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem("encryptedPrivateKey", ciphertext);
localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag);
localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem("encryptedPrivateKey", ciphertext);
localStorage.setItem("iv", iv);
localStorage.setItem("tag", tag);
try {
await attemptLogin(
email,
password,
setErrorLogin,
router,
true,
false
);
incrementStep();
} catch (error) {
setIsLoading(false);
try {
await attemptLogin(
email,
password,
setErrorLogin,
router,
true,
false
);
incrementStep();
} catch (error) {
setIsLoading(false);
}
}
}
});
);
}
);
} else {
@ -296,6 +301,8 @@ export default function SignUp() {
</p>
<div className="hidden md:block">
<ReactCodeInput
name=""
inputMode="tel"
type="text"
fields={6}
onChange={setCode}
@ -305,6 +312,8 @@ export default function SignUp() {
</div>
<div className="block md:hidden">
<ReactCodeInput
name=""
inputMode="tel"
type="text"
fields={6}
onChange={setCode}
@ -364,15 +373,15 @@ export default function SignUp() {
<div className="mt-2 flex flex-col items-center justify-center w-full md:p-2 rounded-lg max-h-60">
<InputField
label="Password"
onChangeHandler={(password) => {
onChangeHandler={(password: string) => {
setPassword(password);
passwordCheck(
passwordCheck({
password,
setPasswordErrorLength,
setPasswordErrorNumber,
setPasswordErrorLowerCase,
false
);
currentErrorCheck: false,
});
}}
type="password"
value={password}
@ -496,7 +505,7 @@ export default function SignUp() {
setBackupKeyIssued,
});
const userWorkspaces = await getWorkspaces();
let userWorkspace = userWorkspaces[0]._id;
const userWorkspace = userWorkspaces[0]._id;
router.push("/home/" + userWorkspace);
}}
size="lg"

View File

@ -0,0 +1,16 @@
#!/bin/sh
ORIGINAL=$1
REPLACEMENT=$2
if [ "${ORIGINAL}" = "${REPLACEMENT}" ]; then
echo "Environment variable replacement is the same, skipping.."
exit 0
fi
echo "Replacing pre-baked value.."
find /app/public /app/.next -type f -name "*.js" |
while read file; do
sed -i "s|$ORIGINAL|$REPLACEMENT|g" "$file"
done

View File

@ -0,0 +1,8 @@
#!/bin/sh
VALUE=$1
find /app/public /app/.next -type f -name "*.js" |
while read file; do
sed -i "s|TELEMETRY_CAPTURING_ENABLED|$VALUE|g" "$file"
done

14
frontend/scripts/start.sh Normal file
View File

@ -0,0 +1,14 @@
#!/bin/sh
scripts/replace-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY" "$NEXT_PUBLIC_POSTHOG_API_KEY"
if [ "$INFISICAL_TELEMETRY_ENABLED" != "false" ]; then
echo "Telemetry is enabled"
scripts/set-telemetry.sh true
else
echo "Client opted out of telemetry"
scripts/set-telemetry.sh false
fi
node server.js

16
helm-charts/README.md Normal file
View File

@ -0,0 +1,16 @@
### helm repository Setup
Assuming you have helm already installed, it is straight-forward to add a Cloudsmith-based chart repository:
```
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'
helm repo update
```
### Installing a Helm Chart
```
helm install infisical-helm-charts/<name-of-helm-chart>
```
#### Available chart names
- infisical

View File

@ -4,7 +4,6 @@ metadata:
name: {{ .Release.Name }}-backend-deployment
labels:
app: backend
namespace: {{ .Values.namespace }}
spec:
replicas: {{ .Values.backend.replicaCount }}
selector:
@ -35,7 +34,6 @@ apiVersion: v1
kind: Service
metadata:
name: infisical-backend-service
namespace: {{ .Values.namespace }}
spec:
selector:
app: backend

View File

@ -4,7 +4,6 @@ metadata:
name: {{ .Release.Name }}-frontend-deployment
labels:
app: frontend
namespace: {{ .Values.namespace }}
spec:
replicas: {{ .Values.frontend.replicaCount }}
selector:
@ -26,7 +25,6 @@ apiVersion: v1
kind: Service
metadata:
name: infisical-frontend-service
namespace: {{ .Values.namespace }}
spec:
selector:
app: frontend

View File

@ -3,7 +3,6 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: infisical-ingress
namespace: {{ .Values.namespace }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}

View File

@ -2,7 +2,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-deployment
namespace: {{ .Values.namespace }}
labels:
app: mongodb
spec:
@ -30,7 +29,6 @@ apiVersion: v1
kind: Service
metadata:
name: mongodb-service
namespace: {{ .Values.namespace }}
spec:
selector:
app: mongodb

View File

@ -1,4 +0,0 @@
apiVersion: v1
kind: Namespace
metadata:
name: infisical

View File

@ -0,0 +1,10 @@
## Loop through each helm chart directoy and build each into helm package
for d in */ ; do
helm package $d
done
## Upload each packaged helm chart
for i in *.tgz; do
[ -f "$i" ] || break
cloudsmith push helm --republish infisical/helm-charts $i
done