This commit is contained in:
Tuan Dang
2022-12-08 23:27:08 -05:00
59 changed files with 1951 additions and 726 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 106 KiB

@@ -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
@@ -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
+64 -11
View File
@@ -3,35 +3,88 @@ name: Push to Docker Hub
on: [workflow_dispatch] on: [workflow_dispatch]
jobs: jobs:
docker:
backend-image:
name: Build backend image
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout
uses: actions/checkout@v2
- -
name: Set up QEMU name: ☁️ Checkout source
uses: actions/checkout@v3
-
name: 🔧 Set up QEMU
uses: docker/setup-qemu-action@v2 uses: docker/setup-qemu-action@v2
- -
name: Set up Docker Buildx name: 🔧 Set up Docker Buildx
uses: docker/setup-buildx-action@v2 uses: docker/setup-buildx-action@v2
- -
name: Login to Docker Hub name: 🐋 Login to Docker Hub
uses: docker/login-action@v2 uses: docker/login-action@v2
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} 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 uses: docker/build-push-action@v3
with: with:
push: true push: true
context: backend 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: Build and push frontend name: ☁️ Checkout source
uses: actions/checkout@v3
-
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 uses: docker/build-push-action@v3
with: with:
push: true push: true
file: frontend/Dockerfile.dev
context: frontend 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 }}
+20 -12
View File
@@ -48,11 +48,17 @@
And more. And more.
## Get started ## 🚀 Get started
To quickly get started, visit our [get started guide](https://infisical.com/docs/getting-started/introduction). 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>. 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. 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). 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:[email protected]?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:[email protected]?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) - [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 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) - [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) - [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. - [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. - [ ] 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. 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 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) ![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! :) 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> </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. 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. 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 [//]: contributor-faces
@@ -277,4 +285,4 @@ Looking to report a security vulnerability? Please don't post about it in GitHub
<!-- prettier-ignore-start --> <!-- prettier-ignore-start -->
<!-- markdownlint-disable --> <!-- 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>
+165 -47
View File
@@ -10,7 +10,7 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"@sentry/node": "^7.14.0", "@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.14.0", "@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"axios": "^1.1.3", "axios": "^1.1.3",
"bigint-conversion": "^2.2.2", "bigint-conversion": "^2.2.2",
@@ -19,13 +19,13 @@
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"express-rate-limit": "^6.5.1", "express-rate-limit": "^6.7.0",
"express-validator": "^6.14.2", "express-validator": "^6.14.2",
"handlebars": "^4.7.7", "handlebars": "^4.7.7",
"helmet": "^5.1.1", "helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4", "jsrp": "^0.2.4",
"mongoose": "^6.7.1", "mongoose": "^6.7.2",
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"posthog-node": "^2.1.0", "posthog-node": "^2.1.0",
"query-string": "^7.1.1", "query-string": "^7.1.1",
@@ -33,7 +33,7 @@
"stripe": "^10.7.0", "stripe": "^10.7.0",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1", "tweetnacl-util": "^0.15.1",
"typescript": "^4.8.4" "typescript": "^4.9.3"
}, },
"devDependencies": { "devDependencies": {
"@posthog/plugin-scaffold": "^1.3.4", "@posthog/plugin-scaffold": "^1.3.4",
@@ -2608,13 +2608,13 @@
} }
}, },
"node_modules/@sentry/node": { "node_modules/@sentry/node": {
"version": "7.17.4", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.17.4.tgz", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
"integrity": "sha512-cR+Gsir9c/tzFWxvk4zXkMQy6tNRHEYixHrb88XIjZVYDqDS9l2/bKs5nJusdmaUeLtmPp5Et2o7RJyS7gvKTQ==", "integrity": "sha512-yG7Tx32WqOkEHVotFLrumCcT9qlaSDTkFNZ+yLSvZXx74ifsE781DzBA9W7K7bBdYO3op+p2YdsOKzf3nPpAyQ==",
"dependencies": { "dependencies": {
"@sentry/core": "7.17.4", "@sentry/core": "7.19.0",
"@sentry/types": "7.17.4", "@sentry/types": "7.19.0",
"@sentry/utils": "7.17.4", "@sentry/utils": "7.19.0",
"cookie": "^0.4.1", "cookie": "^0.4.1",
"https-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3", "lru_map": "^0.3.3",
@@ -2624,14 +2624,80 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/@sentry/tracing": { "node_modules/@sentry/node/node_modules/@sentry/core": {
"version": "7.17.4", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.17.4.tgz", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.19.0.tgz",
"integrity": "sha512-9Fz6DI16ddnd970mlB5MiCNRSmSXp4SVZ1Yv3L22oS3kQeNxjBTE+htYNwJzSPrQp9aL/LqTYwlnrCy24u9XQA==", "integrity": "sha512-YF9cTBcAnO4R44092BJi5Wa2/EO02xn2ziCtmNgAVTN2LD31a/YVGxGBt/FDr4Y6yeuVehaqijVVvtpSmXrGJw==",
"dependencies": { "dependencies": {
"@sentry/core": "7.17.4", "@sentry/types": "7.19.0",
"@sentry/types": "7.17.4", "@sentry/utils": "7.19.0",
"@sentry/utils": "7.17.4", "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" "tslib": "^1.9.3"
}, },
"engines": { "engines": {
@@ -4517,9 +4583,9 @@
} }
}, },
"node_modules/express-rate-limit": { "node_modules/express-rate-limit": {
"version": "6.6.0", "version": "6.7.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==", "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"engines": { "engines": {
"node": ">= 12.9.0" "node": ">= 12.9.0"
}, },
@@ -6452,9 +6518,9 @@
} }
}, },
"node_modules/mongoose": { "node_modules/mongoose": {
"version": "6.7.1", "version": "6.7.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.1.tgz", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.2.tgz",
"integrity": "sha512-qbagtqSyvIhUz4EWzXC00EA0DJHFrQwlzTlNGX5DjiESoJiPKqkEga1k9hviFKRFgBna+OlW54mkdi+0+AqxCw==", "integrity": "sha512-lrP2V5U1qhaf+z33fiIn7aYAZZ1fVDly+TkFRjTujNBF/FIHESATj2RbgAOSlWqv32fsZXkXejXzeVfjbv35Ow==",
"dependencies": { "dependencies": {
"bson": "^4.7.0", "bson": "^4.7.0",
"kareem": "2.4.1", "kareem": "2.4.1",
@@ -10508,9 +10574,9 @@
} }
}, },
"node_modules/typescript": { "node_modules/typescript": {
"version": "4.8.4", "version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -13058,28 +13124,80 @@
} }
}, },
"@sentry/node": { "@sentry/node": {
"version": "7.17.4", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.17.4.tgz", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.19.0.tgz",
"integrity": "sha512-cR+Gsir9c/tzFWxvk4zXkMQy6tNRHEYixHrb88XIjZVYDqDS9l2/bKs5nJusdmaUeLtmPp5Et2o7RJyS7gvKTQ==", "integrity": "sha512-yG7Tx32WqOkEHVotFLrumCcT9qlaSDTkFNZ+yLSvZXx74ifsE781DzBA9W7K7bBdYO3op+p2YdsOKzf3nPpAyQ==",
"requires": { "requires": {
"@sentry/core": "7.17.4", "@sentry/core": "7.19.0",
"@sentry/types": "7.17.4", "@sentry/types": "7.19.0",
"@sentry/utils": "7.17.4", "@sentry/utils": "7.19.0",
"cookie": "^0.4.1", "cookie": "^0.4.1",
"https-proxy-agent": "^5.0.0", "https-proxy-agent": "^5.0.0",
"lru_map": "^0.3.3", "lru_map": "^0.3.3",
"tslib": "^1.9.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": { "@sentry/tracing": {
"version": "7.17.4", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.17.4.tgz", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.19.0.tgz",
"integrity": "sha512-9Fz6DI16ddnd970mlB5MiCNRSmSXp4SVZ1Yv3L22oS3kQeNxjBTE+htYNwJzSPrQp9aL/LqTYwlnrCy24u9XQA==", "integrity": "sha512-SWY17M3TsgBePaGowUcSqBwaT0TJQzuNexVnLojuU0k6F57L9hubvP9zaoosoCfARXQ/3NypAFWnlJyf570rFQ==",
"requires": { "requires": {
"@sentry/core": "7.17.4", "@sentry/core": "7.19.0",
"@sentry/types": "7.17.4", "@sentry/types": "7.19.0",
"@sentry/utils": "7.17.4", "@sentry/utils": "7.19.0",
"tslib": "^1.9.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/types": { "@sentry/types": {
@@ -14523,9 +14641,9 @@
} }
}, },
"express-rate-limit": { "express-rate-limit": {
"version": "6.6.0", "version": "6.7.0",
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.6.0.tgz", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz",
"integrity": "sha512-HFN2+4ZGdkQOS8Qli4z6knmJFnw6lZed67o6b7RGplWeb1Z0s8VXaj3dUgPIdm9hrhZXTRpCTHXA0/2Eqex0vA==", "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==",
"requires": {} "requires": {}
}, },
"express-validator": { "express-validator": {
@@ -15964,9 +16082,9 @@
} }
}, },
"mongoose": { "mongoose": {
"version": "6.7.1", "version": "6.7.2",
"resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.1.tgz", "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.7.2.tgz",
"integrity": "sha512-qbagtqSyvIhUz4EWzXC00EA0DJHFrQwlzTlNGX5DjiESoJiPKqkEga1k9hviFKRFgBna+OlW54mkdi+0+AqxCw==", "integrity": "sha512-lrP2V5U1qhaf+z33fiIn7aYAZZ1fVDly+TkFRjTujNBF/FIHESATj2RbgAOSlWqv32fsZXkXejXzeVfjbv35Ow==",
"requires": { "requires": {
"bson": "^4.7.0", "bson": "^4.7.0",
"kareem": "2.4.1", "kareem": "2.4.1",
@@ -18825,9 +18943,9 @@
} }
}, },
"typescript": { "typescript": {
"version": "4.8.4", "version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==" "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA=="
}, },
"uglify-js": { "uglify-js": {
"version": "3.17.4", "version": "3.17.4",
+4 -4
View File
@@ -1,7 +1,7 @@
{ {
"dependencies": { "dependencies": {
"@sentry/node": "^7.14.0", "@sentry/node": "^7.14.0",
"@sentry/tracing": "^7.14.0", "@sentry/tracing": "^7.19.0",
"@types/crypto-js": "^4.1.1", "@types/crypto-js": "^4.1.1",
"axios": "^1.1.3", "axios": "^1.1.3",
"bigint-conversion": "^2.2.2", "bigint-conversion": "^2.2.2",
@@ -10,13 +10,13 @@
"crypto-js": "^4.1.1", "crypto-js": "^4.1.1",
"dotenv": "^16.0.1", "dotenv": "^16.0.1",
"express": "^4.18.1", "express": "^4.18.1",
"express-rate-limit": "^6.5.1", "express-rate-limit": "^6.7.0",
"express-validator": "^6.14.2", "express-validator": "^6.14.2",
"handlebars": "^4.7.7", "handlebars": "^4.7.7",
"helmet": "^5.1.1", "helmet": "^5.1.1",
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"jsrp": "^0.2.4", "jsrp": "^0.2.4",
"mongoose": "^6.7.1", "mongoose": "^6.7.2",
"nodemailer": "^6.8.0", "nodemailer": "^6.8.0",
"posthog-node": "^2.1.0", "posthog-node": "^2.1.0",
"query-string": "^7.1.1", "query-string": "^7.1.1",
@@ -24,7 +24,7 @@
"stripe": "^10.7.0", "stripe": "^10.7.0",
"tweetnacl": "^1.0.3", "tweetnacl": "^1.0.3",
"tweetnacl-util": "^0.15.1", "tweetnacl-util": "^0.15.1",
"typescript": "^4.8.4" "typescript": "^4.9.3"
}, },
"name": "infisical-api", "name": "infisical-api",
"version": "1.0.0", "version": "1.0.0",
+1 -1
View File
@@ -106,7 +106,7 @@ const initializeDefaultOrg = async ({
// initialize a default workspace inside the new organization // initialize a default workspace inside the new organization
const workspace = await createWorkspace({ const workspace = await createWorkspace({
name: `${user.firstName}'s Project`, name: `Example Project`,
organizationId: organization._id.toString() organizationId: organization._id.toString()
}); });
+140
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)
}
+1 -1
View File
@@ -36,7 +36,7 @@ var initCmd = &cobra.Command{
return return
} }
if util.WorkspaceConfigFileExists() { if util.WorkspaceConfigFileExistsInCurrentPath() {
shouldOverride, err := shouldOverrideWorkspacePrompt() shouldOverride, err := shouldOverrideWorkspacePrompt()
if err != nil { if err != nil {
log.Errorln("Unable to parse your answer") log.Errorln("Unable to parse your answer")
+1 -1
View File
@@ -114,7 +114,7 @@ func init() {
func askForLoginCredentials() (email string, password string, err error) { func askForLoginCredentials() (email string, password string, err error) {
validateEmail := func(input string) 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("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$", input)
if err != nil || !matched { if err != nil || !matched {
return errors.New("this doesn't look like an email address") return errors.New("this doesn't look like an email address")
} }
+1 -1
View File
@@ -15,7 +15,7 @@ var rootCmd = &cobra.Command{
Short: "Infisical CLI is used to inject environment variables into any process", 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.`, 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}, CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
Version: "0.1.6", Version: "0.1.8",
} }
// Execute adds all child commands to the root command and sets flags appropriately. // Execute adds all child commands to the root command and sets flags appropriately.
+9 -42
View File
@@ -47,53 +47,17 @@ var runCmd = &cobra.Command{
return return
} }
var envsFromApi []models.SingleEnvironmentVariable secrets, err := util.GetAllEnvironmentVariables(projectId, envName)
infisicalToken := os.Getenv(util.INFISICAL_TOKEN_NAME)
if infisicalToken == "" {
hasUserLoggedInbefore, loggedInUserEmail, err := util.IsUserLoggedIn()
if err != nil { if err != nil {
log.Info("Unexpected issue occurred while checking login status. To see more details, add flag --debug")
log.Debugln(err) log.Debugln(err)
return 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
}
}
if shouldExpandSecrets { if shouldExpandSecrets {
substitutions := util.SubstituteSecrets(envsFromApi) secretsWithSubstitutions := util.SubstituteSecrets(secrets)
execCmd(args[0], args[1:], substitutions) execCmd(args[0], args[1:], secretsWithSubstitutions)
} else { } else {
execCmd(args[0], args[1:], envsFromApi) execCmd(args[0], args[1:], secrets)
} }
}, },
@@ -108,9 +72,12 @@ func init() {
// Credit: inspired by AWS Valut // Credit: inspired by AWS Valut
func execCmd(command string, args []string, envs []models.SingleEnvironmentVariable) error { func execCmd(command string, args []string, envs []models.SingleEnvironmentVariable) error {
log.Infof("\x1b[%dm%s\x1b[0m", 32, "\u2713 Injected Infisical secrets into your application process successfully") numberOfSecretsInjected := fmt.Sprintf("\u2713 Injected %v Infisical secrets into your application process successfully", len(envs))
log.Debugln("Secrets to inject:", envs)
log.Infof("\x1b[%dm%s\x1b[0m", 32, numberOfSecretsInjected)
log.Debugf("executing command: %s %s \n", command, strings.Join(args, " ")) log.Debugf("executing command: %s %s \n", command, strings.Join(args, " "))
log.Debugln("Secrets injected:", envs)
cmd := exec.Command(command, args...) cmd := exec.Command(command, args...)
cmd.Stdin = os.Stdin cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
+4 -1
View File
@@ -5,10 +5,13 @@ import log "github.com/sirupsen/logrus"
// Custom error type so that we can give helpful messages in CLI // Custom error type so that we can give helpful messages in CLI
type Error struct { type Error struct {
Err error Err error
DebugMessage string
FriendlyMessage string FriendlyMessage string
} }
func (e *Error) printFriendlyMessage() { func (e *Error) printFriendlyMessage() {
log.Infoln(e.FriendlyMessage) log.Infoln(e.FriendlyMessage)
} }
func (e *Error) printDebuError() {
log.Debugln(e.Err)
}
+63 -1
View File
@@ -56,7 +56,7 @@ func ConfigFileExists() bool {
} }
} }
func WorkspaceConfigFileExists() bool { func WorkspaceConfigFileExistsInCurrentPath() bool {
if _, err := os.Stat(INFISICAL_WORKSPACE_CONFIG_FILE_NAME); err == nil { if _, err := os.Stat(INFISICAL_WORKSPACE_CONFIG_FILE_NAME); err == nil {
return true return true
} else { } else {
@@ -90,3 +90,65 @@ func GetFullConfigFilePath() (fullPathToFile string, fullPathToDirectory string,
fullDirPath := fmt.Sprintf("%s/%s", homeDir, CONFIG_FOLDER_NAME) fullDirPath := fmt.Sprintf("%s/%s", homeDir, CONFIG_FOLDER_NAME)
return fullPath, fullDirPath, err return fullPath, fullDirPath, err
} }
// Given a path to a workspace config, unmarshal workspace config
func GetWorkspaceConfigByPath(path string) (workspaceConfig models.WorkspaceConfigFile, err error) {
workspaceConfigFileAsBytes, err := os.ReadFile(path)
if err != nil {
return models.WorkspaceConfigFile{}, fmt.Errorf("GetWorkspaceConfigByPath: Unable to read workspace config file because [%s]", err)
}
var workspaceConfigFile models.WorkspaceConfigFile
err = json.Unmarshal(workspaceConfigFileAsBytes, &workspaceConfigFile)
if err != nil {
return models.WorkspaceConfigFile{}, fmt.Errorf("GetWorkspaceConfigByPath: Unable to unmarshal workspace config file because [%s]", err)
}
return workspaceConfigFile, nil
}
// Will get the list of .infisical.json files that are located
// within the root of each sub folder from where the CLI is ran from
func GetAllWorkSpaceConfigsStartingFromCurrentPath() (workspaces []models.WorkspaceConfigFile, err error) {
currentDir, err := os.Getwd()
if err != nil {
return nil, fmt.Errorf("GetAllProjectConfigs: unable to get the current directory because [%s]", err)
}
files, err := os.ReadDir(currentDir)
if err != nil {
return nil, fmt.Errorf("GetAllProjectConfigs: unable to read the contents of the current directory because [%s]", err)
}
listOfWorkSpaceConfigs := []models.WorkspaceConfigFile{}
for _, file := range files {
if !file.IsDir() && file.Name() == INFISICAL_WORKSPACE_CONFIG_FILE_NAME {
pathToWorkspaceConfigFile := currentDir + "/" + INFISICAL_WORKSPACE_CONFIG_FILE_NAME
workspaceConfig, err := GetWorkspaceConfigByPath(pathToWorkspaceConfigFile)
if err != nil {
return nil, fmt.Errorf("GetAllProjectConfigs: Unable to get config file because [%s]", err)
}
listOfWorkSpaceConfigs = append(listOfWorkSpaceConfigs, workspaceConfig)
} else if file.IsDir() {
pathToSubFolder := currentDir + "/" + file.Name()
pathToMaybeWorkspaceConfigFile := pathToSubFolder + "/" + INFISICAL_WORKSPACE_CONFIG_FILE_NAME
_, err := os.Stat(pathToMaybeWorkspaceConfigFile)
if err != nil {
continue // workspace config file doesn't exist
}
workspaceConfig, err := GetWorkspaceConfigByPath(pathToMaybeWorkspaceConfigFile)
if err != nil {
return nil, fmt.Errorf("GetAllProjectConfigs: Unable to get config file because [%s]", err)
}
listOfWorkSpaceConfigs = append(listOfWorkSpaceConfigs, workspaceConfig)
}
}
return listOfWorkSpaceConfigs, nil
}
-3
View File
@@ -3,12 +3,9 @@ package util
import ( import (
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
log "github.com/sirupsen/logrus"
) )
func DecryptSymmetric(key []byte, encryptedPrivateKey []byte, tag []byte, IV []byte) ([]byte, error) { func DecryptSymmetric(key []byte, encryptedPrivateKey []byte, tag []byte, IV []byte) ([]byte, error) {
log.Debugln("Key:", key, "encryptedPrivateKey", encryptedPrivateKey, "tag", tag, "IV", IV)
block, err := aes.NewCipher(key) block, err := aes.NewCipher(key)
if err != nil { if err != nil {
return nil, err return nil, err
+81 -18
View File
@@ -4,6 +4,7 @@ import (
"encoding/base64" "encoding/base64"
"errors" "errors"
"fmt" "fmt"
"os"
"regexp" "regexp"
"strings" "strings"
@@ -13,19 +14,7 @@ import (
"golang.org/x/crypto/nacl/box" "golang.org/x/crypto/nacl/box"
) )
func GetSecretsFromAPIUsingCurrentLoggedInUser(envName string, userCreds models.UserCredentials) ([]models.SingleEnvironmentVariable, error) { func getSecretsByWorkspaceIdAndEnvName(httpClient resty.Client, envName string, workspace models.WorkspaceConfigFile, userCreds models.UserCredentials) (listOfSecrets []models.SingleEnvironmentVariable, err error) {
log.Debugln("envName", envName, "userCreds", userCreds)
// check if user has configured a workspace
workspace, err := GetWorkSpaceFromFile()
if err != nil {
return nil, fmt.Errorf("Unable to read workspace file:", err)
}
// create http client
httpClient := resty.New().
SetAuthToken(userCreds.JTWToken).
SetHeader("Accept", "application/json")
var pullSecretsRequestResponse models.PullSecretsResponse var pullSecretsRequestResponse models.PullSecretsResponse
response, err := httpClient. response, err := httpClient.
R(). R().
@@ -34,14 +23,11 @@ func GetSecretsFromAPIUsingCurrentLoggedInUser(envName string, userCreds models.
SetResult(&pullSecretsRequestResponse). SetResult(&pullSecretsRequestResponse).
Get(fmt.Sprintf("%v/v1/secret/%v", INFISICAL_URL, workspace.WorkspaceId)) // need to change workspace id Get(fmt.Sprintf("%v/v1/secret/%v", INFISICAL_URL, workspace.WorkspaceId)) // need to change workspace id
log.Debugln("Response from get secrets:", response)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if response.StatusCode() > 299 { if response.StatusCode() > 299 {
log.Debugln(response)
return nil, fmt.Errorf(response.Status()) return nil, fmt.Errorf(response.Status())
} }
@@ -66,7 +52,7 @@ func GetSecretsFromAPIUsingCurrentLoggedInUser(envName string, userCreds models.
return nil, err return nil, err
} }
log.Debugln("workspaceKey", workspaceKey, "nonce", nonce, "senderPublicKey", senderPublicKey, "currentUsersPrivateKey", currentUsersPrivateKey) // log.Debugln("workspaceKey", workspaceKey, "nonce", nonce, "senderPublicKey", senderPublicKey, "currentUsersPrivateKey", currentUsersPrivateKey)
workspaceKeyInBytes, _ := box.Open(nil, workspaceKey, (*[24]byte)(nonce), (*[32]byte)(senderPublicKey), (*[32]byte)(currentUsersPrivateKey)) workspaceKeyInBytes, _ := box.Open(nil, workspaceKey, (*[24]byte)(nonce), (*[32]byte)(senderPublicKey), (*[32]byte)(currentUsersPrivateKey))
var listOfEnv []models.SingleEnvironmentVariable var listOfEnv []models.SingleEnvironmentVariable
@@ -100,6 +86,32 @@ func GetSecretsFromAPIUsingCurrentLoggedInUser(envName string, userCreds models.
return listOfEnv, nil return listOfEnv, nil
} }
func GetSecretsFromAPIUsingCurrentLoggedInUser(envName string, userCreds models.UserCredentials) ([]models.SingleEnvironmentVariable, error) {
log.Debugln("GetSecretsFromAPIUsingCurrentLoggedInUser", "envName", envName, "userCreds", userCreds)
// check if user has configured a workspace
workspaces, err := GetAllWorkSpaceConfigsStartingFromCurrentPath()
if err != nil {
return nil, fmt.Errorf("Unable to read workspace file(s):", err)
}
// create http client
httpClient := resty.New().
SetAuthToken(userCreds.JTWToken).
SetHeader("Accept", "application/json")
secrets := []models.SingleEnvironmentVariable{}
for _, workspace := range workspaces {
secretsFromAPI, err := getSecretsByWorkspaceIdAndEnvName(*httpClient, envName, workspace, userCreds)
if err != nil {
return nil, fmt.Errorf("GetSecretsFromAPIUsingCurrentLoggedInUser: Unable to get secrets by workspace id and env name")
}
secrets = append(secrets, secretsFromAPI...)
}
return secrets, nil
}
func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string) ([]models.SingleEnvironmentVariable, error) { func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string, projectId string) ([]models.SingleEnvironmentVariable, error) {
if infisicalToken == "" || projectId == "" || envName == "" { if infisicalToken == "" || projectId == "" || envName == "" {
return nil, errors.New("infisical token, project id and or environment name cannot be empty") return nil, errors.New("infisical token, project id and or environment name cannot be empty")
@@ -126,7 +138,6 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string,
} }
if response.StatusCode() > 299 { if response.StatusCode() > 299 {
log.Debugln(response)
return nil, fmt.Errorf(response.Status()) return nil, fmt.Errorf(response.Status())
} }
@@ -184,6 +195,58 @@ func GetSecretsFromAPIUsingInfisicalToken(infisicalToken string, envName string,
return listOfEnv, nil 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
}
workspaceConfigs, err := GetAllWorkSpaceConfigsStartingFromCurrentPath()
if err != nil {
return nil, fmt.Errorf("unable to check if you have a %s file in your current directory", INFISICAL_WORKSPACE_CONFIG_FILE_NAME)
}
if len(workspaceConfigs) == 0 {
log.Infoln("Your local project is not connected to a Infisical 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) { func GetWorkSpacesFromAPI(userCreds models.UserCredentials) (workspaces []models.Workspace, err error) {
// create http client // create http client
httpClient := resty.New(). httpClient := resty.New().
+2 -6
View File
@@ -23,7 +23,6 @@ services:
build: build:
context: ./backend context: ./backend
dockerfile: Dockerfile dockerfile: Dockerfile
image: infisical/backend
volumes: volumes:
- ./backend/src:/app/src - ./backend/src:/app/src
- ./backend/nodemon.json:/app/nodemon.json - ./backend/nodemon.json:/app/nodemon.json
@@ -43,7 +42,6 @@ services:
build: build:
context: ./frontend context: ./frontend
dockerfile: Dockerfile.dev dockerfile: Dockerfile.dev
image: infisical/frontend
volumes: volumes:
- ./frontend/pages:/app/pages - ./frontend/pages:/app/pages
- ./frontend/public:/app/public - ./frontend/public:/app/public
@@ -52,12 +50,8 @@ services:
env_file: .env env_file: .env
environment: environment:
- NEXT_PUBLIC_ENV=development - 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_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER} - NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
- NEXT_PUBLIC_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
networks: networks:
- infisical-dev - infisical-dev
@@ -78,6 +72,8 @@ services:
container_name: infisical-dev-mongo-express container_name: infisical-dev-mongo-express
image: mongo-express image: mongo-express
restart: always restart: always
depends_on:
- mongo
env_file: .env env_file: .env
environment: environment:
- ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_USERNAME} - ME_CONFIG_MONGODB_ADMINUSERNAME=${MONGO_USERNAME}
+2 -13
View File
@@ -17,14 +17,10 @@ services:
- infisical - infisical
backend: backend:
platform: linux/amd64
container_name: infisical-backend container_name: infisical-backend
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- mongo - mongo
build:
context: ./backend
dockerfile: Dockerfile
image: infisical/backend image: infisical/backend
command: npm run start command: npm run start
env_file: .env env_file: .env
@@ -34,24 +30,17 @@ services:
- infisical - infisical
frontend: frontend:
platform: linux/amd64
container_name: infisical-frontend container_name: infisical-frontend
restart: unless-stopped restart: unless-stopped
depends_on: depends_on:
- backend - backend
build:
context: ./frontend
dockerfile: Dockerfile.prod
image: infisical/frontend image: infisical/frontend
env_file: .env env_file: .env
environment: environment:
- NEXT_PUBLIC_ENV=production # - NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
- NEXT_PUBLIC_WEBSITE_URL=${SITE_URL} - INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
- 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_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER} - NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
- NEXT_PUBLIC_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
networks: networks:
- infisical - infisical
+33
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` | Only required if injecting via the [service token method](../token). If you are not using service token, the project id will be automatically retrieved from the `.infisical.json` located at the root of your local project. | `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
```
+1 -1
View File
@@ -1,5 +1,5 @@
--- ---
title: "Overview" title: "Install"
--- ---
Prerequisite: Set up an account with [Infisical Cloud](https://app.infisical.com) or via a [self-hosted installation](/self-hosting/overview). Prerequisite: Set up an account with [Infisical Cloud](https://app.infisical.com) or via a [self-hosted installation](/self-hosting/overview).
+6 -3
View File
@@ -4,13 +4,16 @@ title: "Infisical Token"
An Infisical Token is needed to authenticate the CLI when there isn't an easy way to input your login credentials. An Infisical Token is needed to authenticate the CLI when there isn't an easy way to input your login credentials.
It's useful for the [Docker](/integrations/platforms/docker) and [Docker Compose](/integrations/platforms/docker-compose) integrations. It's useful for your CI/CD environments and integrations such as [Docker](/integrations/platforms/docker) and [Docker Compose](/integrations/platforms/docker-compose).
To generate the the token, head over to your project settings as shown below.
It's possible to generate the token in the settings of a project.
![token add](../../images/project-token-add.png) ![token add](../../images/project-token-add.png)
<Note> <Note>
The token grants read-only access to a particular environment and project for The token grants read-only access to a particular environment and project for
a specified amount of time. a specified amount of time. Once the token is expired, the CLI using it will no longer be able to make
requests with it.
</Note> </Note>
@@ -4,14 +4,14 @@ title: "Docker Compose"
The Docker Compose integration enables you to inject environment variables from Infisical into the containers defined in your compose file. The Docker Compose integration enables you to inject environment variables from Infisical into the containers defined in your compose file.
## Add the CLI to your Dockerfile(s) ## Add the CLI to your Dockerfile(s) start command
Follow steps 1 through 3 on our [guide to configure Infisical CLI](../integrations/platforms/docker) in your Dockerfile. Follow the [guide to configure Infisical CLI](./docker) in your your Dockerfile first.
## Generate Infisical Token ## Generate Infisical Token
In order for Infisical CLI to authenticate and retrieve your project's secrets without exposing your login credentials, you must generate a Infisical Token. In order for Infisical CLI to authenticate and retrieve your project's secrets without exposing your login credentials, you must generate a Infisical Token.
To learn how, visit [Infisical Token](../getting-started/cli/infisical-token). Once you have generated the token, keep it handy. To learn how, visit [Infisical Token](../../getting-started/dashboard/token). Once you have generated the token, keep it handy.
<Info> <Info>
If you have multiple services and they do not use the same secrets, you will If you have multiple services and they do not use the same secrets, you will
+5 -5
View File
@@ -87,12 +87,12 @@
"cli/overview", "cli/overview",
"cli/usage", "cli/usage",
{ {
"group": "Reference", "group": "Commands",
"pages": [ "pages": [
"cli/reference/commands", "cli/commands/login",
"cli/reference/login", "cli/commands/init",
"cli/reference/init", "cli/commands/run",
"cli/reference/run" "cli/commands/export"
] ]
} }
] ]
+3 -3
View File
@@ -12,7 +12,7 @@ Configuring Infisical requires setting some environment variables. There is a fi
| `PRIVATE_KEY` | ❗️ NaCl-generated server secret key | `None` | | `PRIVATE_KEY` | ❗️ NaCl-generated server secret key | `None` |
| `PUBLIC_KEY` | ❗️ NaCl-generated server public key | `None` | | `PUBLIC_KEY` | ❗️ NaCl-generated server public key | `None` |
| `ENCRYPTION_KEY` | ❗️ Strong hex encryption key | `None` | | `ENCRYPTION_KEY` | ❗️ Strong hex encryption key | `None` |
| `JWT_SIGNUP_SECRET` | ❗️JWT token secret | `None` | | `JWT_SIGNUP_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_REFRESH_SECRET` | ❗️ JWT token secret | `None` | | `JWT_REFRESH_SECRET` | ❗️ JWT token secret | `None` |
| `JWT_AUTH_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_SIGNUP_LIFETIME` | JWT token lifetime expressed in seconds or a string describing a time span (e.g. 60, "2 days", "10h", "7d") | `15m` |
@@ -23,8 +23,8 @@ Configuring Infisical requires setting some environment variables. There is a fi
| `MONGO_USERNAME` | MongoDB username if using container | `None` | | `MONGO_USERNAME` | MongoDB username if using container | `None` |
| `MONGO_PASSWORD` | MongoDB password 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` | | `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_HOST` | Hostname to connect to for establishing SMTP connections | `smtp.gmail.com` |
| `SMTP_NAME` | Hostname to connect to for establishing SMTP connections (e.g. `Team`) | `None` | | `SMTP_NAME` | Name label to be used in From field (e.g. `Team`) | `None` |
| `SMTP_USERNAME` | ❗️ Credential to connect to host (e.g. `[email protected]`) | `None` | | `SMTP_USERNAME` | ❗️ Credential to connect to host (e.g. `[email protected]`) | `None` |
| `SMTP_PASSWORD` | ❗️ Credential to connect to host | `None` | | `SMTP_PASSWORD` | ❗️ Credential to connect to host | `None` |
| `TELEMETRY_ENABLED` | `true` or `false`. [More](../overview). | `true` | | `TELEMETRY_ENABLED` | `true` or `false`. [More](../overview). | `true` |
+64
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"]
+1 -2
View File
@@ -4,12 +4,11 @@ import {
ENV, ENV,
POSTHOG_API_KEY, POSTHOG_API_KEY,
POSTHOG_HOST, POSTHOG_HOST,
TELEMETRY_ENABLED,
} from "../utilities/config"; } from "../utilities/config";
export const initPostHog = () => { export const initPostHog = () => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
if (ENV == "production" && TELEMETRY_ENABLED) { if (ENV == "production" && TELEMETRY_CAPTURING_ENABLED) { // eslint-disable-line
posthog.init(POSTHOG_API_KEY, { posthog.init(POSTHOG_API_KEY, {
api_host: POSTHOG_HOST, api_host: POSTHOG_HOST,
}); });
@@ -1,19 +1,27 @@
import React from "react"; import React, { useState } from "react";
import { useState } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { import { faCircle, faEye, faEyeSlash } from "@fortawesome/free-solid-svg-icons";
faCircle,
faCircleExclamation,
faE,
faEye,
faEyeSlash,
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import guidGenerator from "../utilities/randomId"; 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 [passwordVisible, setPasswordVisible] = useState(false);
const router = useRouter(); const router = useRouter();
@@ -67,7 +75,7 @@ const InputField = (props) => {
> >
<input <input
onChange={(e) => props.onChangeHandler(e.target.value)} onChange={(e) => props.onChangeHandler(e.target.value)}
type={passwordVisible == false ? props.type : "text"} type={passwordVisible === false ? props.type : "text"}
placeholder={props.placeholder} placeholder={props.placeholder}
value={props.value} value={props.value}
required={props.isRequired} required={props.isRequired}
@@ -1,3 +1,4 @@
/* eslint-disable no-unexpected-multiline */
/* eslint-disable react-hooks/exhaustive-deps */ /* eslint-disable react-hooks/exhaustive-deps */
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import Link from "next/link"; import Link from "next/link";
@@ -22,6 +23,7 @@ import getWorkspaces from "~/pages/api/workspace/getWorkspaces";
import uploadKeys from "~/pages/api/workspace/uploadKeys"; import uploadKeys from "~/pages/api/workspace/uploadKeys";
import NavBarDashboard from "../navigation/NavBarDashboard"; import NavBarDashboard from "../navigation/NavBarDashboard";
import { tempLocalStorage } from "../utilities/checks/tempLocalStorage";
import { import {
decryptAssymmetric, decryptAssymmetric,
encryptAssymmetric, encryptAssymmetric,
@@ -30,13 +32,17 @@ import Button from "./buttons/Button";
import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog"; import AddWorkspaceDialog from "./dialog/AddWorkspaceDialog";
import Listbox from "./Listbox"; import Listbox from "./Listbox";
export default function Layout({ children }) { interface LayoutProps {
children: React.ReactNode;
}
export default function Layout({ children }: LayoutProps) {
const router = useRouter(); const router = useRouter();
const [workspaceList, setWorkspaceList] = useState([]); const [workspaceList, setWorkspaceList] = useState([]);
const [workspaceMapping, setWorkspaceMapping] = useState([{ 1: 2 }]); const [workspaceMapping, setWorkspaceMapping] = useState([{ 1: 2 }]);
const [workspaceSelected, setWorkspaceSelected] = useState("∞"); const [workspaceSelected, setWorkspaceSelected] = useState("∞");
let [newWorkspaceName, setNewWorkspaceName] = useState(""); const [newWorkspaceName, setNewWorkspaceName] = useState("");
let [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [error, setError] = useState(false); const [error, setError] = useState(false);
@@ -44,40 +50,43 @@ export default function Layout({ children }) {
setIsOpen(false); setIsOpen(false);
} }
function openModal() {
setIsOpen(true);
}
// TODO: what to do about the fact that 2ids can have the same name // 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. * When a user creates a new workspace, redirect them to the page of the new workspace.
* @param {*} workspaceName * @param {*} workspaceName
*/ */
async function submitModal(workspaceName, addAllUsers) { async function submitModal(workspaceName: string, addAllUsers: boolean) {
setLoading(true); setLoading(true);
// timeout code.
setTimeout(() => setLoading(false), 1500); setTimeout(() => setLoading(false), 1500);
try {
const workspaces = await getWorkspaces(); const workspaces = await getWorkspaces();
const currentWorkspaces = workspaces.map((workspace) => workspace.name); const currentWorkspaces = workspaces.map((workspace) => workspace.name);
if (!currentWorkspaces.includes(workspaceName)) { if (!currentWorkspaces.includes(workspaceName)) {
const newWorkspace = await createWorkspace({ const newWorkspace = await createWorkspace({
workspaceName, workspaceName,
organizationId: localStorage.getItem("orgData.id") organizationId: tempLocalStorage("orgData.id"),
}); });
let newWorkspaceId; const newWorkspaceId = newWorkspace._id;
try {
newWorkspaceId = newWorkspace._id;
} catch (error) {
console.log(error);
}
if (addAllUsers) { if (addAllUsers) {
let orgUsers = await getOrganizationUsers({ const orgUsers = await getOrganizationUsers({
orgId: localStorage.getItem("orgData.id"), orgId: tempLocalStorage("orgData.id"),
}); });
orgUsers.map(async (user) => { orgUsers.map(async (user: any) => {
if (user.status == "accepted") { if (user.status == "accepted") {
let result = await addUserToWorkspace( const result = await addUserToWorkspace(
user.user.email, user.user.email,
newWorkspaceId newWorkspaceId
); );
if (result?.invitee && result?.latestKey) { if (result?.invitee && result?.latestKey) {
const PRIVATE_KEY = localStorage.getItem("PRIVATE_KEY"); const PRIVATE_KEY = tempLocalStorage("PRIVATE_KEY");
// assymmetrically decrypt symmetric key with local private key // assymmetrically decrypt symmetric key with local private key
const key = decryptAssymmetric({ const key = decryptAssymmetric({
@@ -91,9 +100,14 @@ export default function Layout({ children }) {
plaintext: key, plaintext: key,
publicKey: result.invitee.publicKey, publicKey: result.invitee.publicKey,
privateKey: PRIVATE_KEY, privateKey: PRIVATE_KEY,
}); }) as { ciphertext: string; nonce: string };
uploadKeys(newWorkspaceId, result.invitee._id, ciphertext, nonce); uploadKeys(
newWorkspaceId,
result.invitee._id,
ciphertext,
nonce
);
} }
} }
}); });
@@ -102,53 +116,55 @@ export default function Layout({ children }) {
setIsOpen(false); setIsOpen(false);
setNewWorkspaceName(""); setNewWorkspaceName("");
} else { } else {
setError("A project with this name already exists."); console.error("A project with this name already exists.");
setError(true);
setLoading(false); setLoading(false);
} }
} catch (err) {
console.error(err);
setError(true);
setLoading(false);
} }
function openModal() {
setIsOpen(true);
} }
const menuItems = [ const menuItems = [
{ {
href: href:
"/dashboard/" + workspaceMapping[workspaceSelected] + "?Development", "/dashboard/" +
workspaceMapping[workspaceSelected as any] +
"?Development",
title: "Secrets", title: "Secrets",
emoji: <FontAwesomeIcon icon={faKey} />, emoji: <FontAwesomeIcon icon={faKey} />,
}, },
{ {
href: "/users/" + workspaceMapping[workspaceSelected], href: "/users/" + workspaceMapping[workspaceSelected as any],
title: "Members", title: "Members",
emoji: <FontAwesomeIcon icon={faUser} />, emoji: <FontAwesomeIcon icon={faUser} />,
}, },
{ {
href: "/integrations/" + workspaceMapping[workspaceSelected], href: "/integrations/" + workspaceMapping[workspaceSelected as any],
title: "Integrations", title: "Integrations",
emoji: <FontAwesomeIcon icon={faPlug} />, emoji: <FontAwesomeIcon icon={faPlug} />,
}, },
{ {
href: "/settings/project/" + workspaceMapping[workspaceSelected], href: "/settings/project/" + workspaceMapping[workspaceSelected as any],
title: "Project Settings", title: "Project Settings",
emoji: <FontAwesomeIcon icon={faGear} />, emoji: <FontAwesomeIcon icon={faGear} />,
}, },
]; ];
useEffect(async () => { useEffect(() => {
// Put a user in a workspace if they're not in one yet // Put a user in a workspace if they're not in one yet
if ( const putUserInWorkSpace = async () => {
localStorage.getItem("orgData.id") == null || if (tempLocalStorage("orgData.id") === "") {
localStorage.getItem("orgData.id") == ""
) {
const userOrgs = await getOrganizations(); const userOrgs = await getOrganizations();
localStorage.setItem("orgData.id", userOrgs[0]._id); localStorage.setItem("orgData.id", userOrgs[0]._id);
} }
let orgUserProjects = await getOrganizationUserProjects({ const orgUserProjects = await getOrganizationUserProjects({
orgId: localStorage.getItem("orgData.id"), orgId: tempLocalStorage("orgData.id"),
}); });
let userWorkspaces = orgUserProjects; const userWorkspaces = orgUserProjects;
if ( if (
userWorkspaces.length == 0 && userWorkspaces.length == 0 &&
router.asPath != "/noprojects" && router.asPath != "/noprojects" &&
@@ -157,45 +173,63 @@ export default function Layout({ children }) {
router.push("/noprojects"); router.push("/noprojects");
} else if (router.asPath != "/noprojects") { } else if (router.asPath != "/noprojects") {
const intendedWorkspaceId = router.asPath const intendedWorkspaceId = router.asPath
.split("/")[router.asPath.split("/").length - 1].split("?")[0]; .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 a user is not a member of a workspace they are trying to access, just push them to one of theirs
if ( if (
intendedWorkspaceId != "heroku" && intendedWorkspaceId != "heroku" &&
!userWorkspaces !userWorkspaces
.map((workspace) => workspace._id) .map((workspace: { _id: string }) => workspace._id)
.includes(intendedWorkspaceId) .includes(intendedWorkspaceId)
) { ) {
router.push("/dashboard/" + userWorkspaces[0]._id + "?Development"); router.push("/dashboard/" + userWorkspaces[0]._id + "?Development");
} else { } else {
setWorkspaceList(userWorkspaces.map((workspace) => workspace.name)); setWorkspaceList(
userWorkspaces.map((workspace: any) => workspace.name)
);
setWorkspaceMapping( setWorkspaceMapping(
Object.fromEntries( Object.fromEntries(
userWorkspaces.map((workspace) => [workspace.name, workspace._id]) userWorkspaces.map((workspace: any) => [
) workspace.name,
workspace._id,
])
) as any
); );
setWorkspaceSelected( setWorkspaceSelected(
Object.fromEntries( Object.fromEntries(
userWorkspaces.map((workspace) => [workspace._id, workspace.name]) userWorkspaces.map((workspace: any) => [
workspace._id,
workspace.name,
])
)[ )[
router.asPath router.asPath
.split("/")[router.asPath.split("/").length - 1].split("?")[0]] .split("/")
[router.asPath.split("/").length - 1].split("?")[0]
]
); );
} }
} }
};
putUserInWorkSpace();
}, []); }, []);
useEffect(() => { useEffect(() => {
try { try {
if ( if (
workspaceMapping[workspaceSelected] && workspaceMapping[Number(workspaceSelected)] &&
workspaceMapping[workspaceSelected] !== `${workspaceMapping[Number(workspaceSelected)]}` !==
router.asPath 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( localStorage.setItem(
"projectData.id", "projectData.id",
workspaceMapping[workspaceSelected] `${workspaceMapping[Number(workspaceSelected)]}`
); );
} }
} catch (error) { } catch (error) {
@@ -212,18 +246,18 @@ export default function Layout({ children }) {
<nav className="flex flex-col justify-between items-between h-full"> <nav className="flex flex-col justify-between items-between h-full">
{/* <div className="py-6"></div> */} {/* <div className="py-6"></div> */}
<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"> <div className="text-gray-400 self-start ml-1 mb-1 text-xs font-semibold tracking-wide">
PROJECT PROJECT
</div> </div>
{workspaceList.length > 0 ? ( {workspaceList.length > 0 ? (
<Listbox <Listbox
selected={workspaceSelected} selected={workspaceSelected}
onChange={setWorkspaceSelected} onChange={setWorkspaceSelected as any}
data={workspaceList} data={workspaceList}
buttonAction={openModal} buttonAction={openModal}
text="" text=""
workspaceMapping={workspaceMapping} // workspaceMapping={workspaceMapping as any}
/> />
) : ( ) : (
<Button <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`} 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> <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} {title}
</div> </div>
) : router.asPath == "/noprojects" ? ( ) : router.asPath == "/noprojects" ? (
<div className={`flex p-2.5 text-white text-sm rounded`}> <div
<p className="w-10 flex items-center justify-center text-lg">{emoji}</p> className={`flex p-2.5 text-white text-sm rounded`}
>
<p className="w-10 flex items-center justify-center text-lg">
{emoji}
</p>
{title} {title}
</div> </div>
) : ( ) : (
@@ -262,7 +302,9 @@ export default function Layout({ children }) {
<div <div
className={`flex p-2.5 text-white text-sm rounded cursor-pointer hover:bg-primary-50/5`} 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} {title}
</div> </div>
</Link> </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`} 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> <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 Infisical Guide
</div> </div>
) : ( ) : (
<Link href={`/home/` + workspaceMapping[workspaceSelected]}> <Link
href={`/home/` + workspaceMapping[workspaceSelected as any]}
>
<div <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`} 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 Infisical Guide
</div> </div>
</Link> </Link>
@@ -305,7 +353,7 @@ export default function Layout({ children }) {
<main className="flex-1 bg-bunker-800">{children}</main> <main className="flex-1 bg-bunker-800">{children}</main>
</div> </div>
</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 <FontAwesomeIcon
icon={faMobile} icon={faMobile}
className="text-gray-300 text-7xl mb-8" className="text-gray-300 text-7xl mb-8"
+10 -11
View File
@@ -8,14 +8,13 @@ import {
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Listbox, Transition } from "@headlessui/react"; import { Listbox, Transition } from "@headlessui/react";
interface ListBoxProps {
type ListBoxProps = { selected: string;
selected: string, onChange: () => void;
onChange: () => void, data: string[];
data: string[], text: string;
text: string, buttonAction: () => void;
buttonAction: () => void, isFull?: boolean;
width: string,
} }
/** /**
@@ -35,14 +34,14 @@ export default function ListBox({
data, data,
text, text,
buttonAction, buttonAction,
width, isFull,
} : ListBoxProps): JSX.Element { }: ListBoxProps): JSX.Element {
return ( return (
<Listbox value={selected} onChange={onChange}> <Listbox value={selected} onChange={onChange}>
<div className="relative"> <div className="relative">
<Listbox.Button <Listbox.Button
className={`text-gray-400 relative ${ 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`} } 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"> <div className="flex flex-row">
+1 -1
View File
@@ -12,7 +12,7 @@ type ButtonProps = {
text: string; text: string;
onButtonPressed: () => void; onButtonPressed: () => void;
loading?: boolean; loading?: boolean;
color: string; color?: string;
size: string; size: string;
icon?: IconProp; icon?: IconProp;
active?: boolean; active?: boolean;
@@ -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;
@@ -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;
@@ -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;
@@ -3,7 +3,7 @@ import token from "~/pages/api/auth/Token";
export default class SecurityClient { export default class SecurityClient {
static #token = ""; static #token = "";
contructor() {} constructor() {}
static setToken(token) { static setToken(token) {
this.#token = token; this.#token = token;
+27 -67
View File
@@ -4,10 +4,10 @@ import login2 from "~/pages/api/auth/Login2";
import getOrganizations from "~/pages/api/organization/getOrgs"; import getOrganizations from "~/pages/api/organization/getOrgs";
import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects"; import getOrganizationUserProjects from "~/pages/api/organization/GetOrgUserProjects";
import { initPostHog } from "../analytics/posthog";
import pushKeys from "./secrets/pushKeys"; import pushKeys from "./secrets/pushKeys";
import { ENV } from "./config"; import { saveTokenToLocalStorage } from "./saveTokenToLocalStorage";
import SecurityClient from "./SecurityClient"; import SecurityClient from "./SecurityClient";
import Telemetry from "./telemetry/Telemetry";
const nacl = require("tweetnacl"); const nacl = require("tweetnacl");
nacl.util = require("tweetnacl-util"); nacl.util = require("tweetnacl-util");
@@ -32,7 +32,8 @@ const attemptLogin = async (
isLogin isLogin
) => { ) => {
try { try {
let userWorkspace, userOrg; const telemetry = new Telemetry().getInstance();
client.init( client.init(
{ {
username: email, username: email,
@@ -41,66 +42,38 @@ const attemptLogin = async (
async () => { async () => {
const clientPublicKey = client.getPublicKey(); const clientPublicKey = client.getPublicKey();
let serverPublicKey, salt; const { serverPublicKey, salt } = await login1(email, clientPublicKey);
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);
}
let response;
try { try {
client.setSalt(salt); client.setSalt(salt);
client.setServerPublicKey(serverPublicKey); client.setServerPublicKey(serverPublicKey);
const clientProof = client.getProof(); // called M1 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. // if everything works, go the main dashboard page.
try { const { token, publicKey, encryptedPrivateKey, iv, tag } =
if (response.status == "200") { await login2(email, clientProof);
response = await response.json(); SecurityClient.setToken(token);
SecurityClient.setToken(response["token"]);
const publicKey = response["publicKey"];
const encryptedPrivateKey = response["encryptedPrivateKey"];
const iv = response["iv"];
const tag = response["tag"];
const PRIVATE_KEY = Aes256Gcm.decrypt( const privateKey = Aes256Gcm.decrypt(
encryptedPrivateKey, encryptedPrivateKey,
iv, iv,
tag, tag,
password password
.slice(0, 32) .slice(0, 32)
.padStart( .padStart(
32 + 32 + (password.slice(0, 32).length - new Blob([password]).size),
(password.slice(0, 32).length - new Blob([password]).size),
"0" "0"
) )
); );
try { saveTokenToLocalStorage({
localStorage.setItem("publicKey", publicKey); token,
localStorage.setItem("encryptedPrivateKey", encryptedPrivateKey); publicKey,
localStorage.setItem("iv", iv); encryptedPrivateKey,
localStorage.setItem("tag", tag); iv,
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); tag,
} catch (err) { privateKey,
setErrorLogin(true); });
console.error(
"Unable to send the tokens in local storage:" + err.message
);
}
} else {
setErrorLogin(true);
}
const userOrgs = await getOrganizations(); const userOrgs = await getOrganizations();
const userOrgsData = userOrgs.map((org) => org._id); 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 user is logging in for the first time, add the example keys
if (isSignUp) { if (isSignUp) {
await pushKeys( await pushKeys({
{ obj: {
DATABASE_URL: [ DATABASE_URL: [
"mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net", "mongodb+srv://${DB_USERNAME}:${DB_PASSWORD}@mongodb.net",
"personal", "personal",
], ],
DB_USERNAME: [ DB_USERNAME: ["user1234", "personal"],
"user1234", DB_PASSWORD: ["ah8jak3hk8dhiu4dw7whxwe1l", "personal"],
"personal",
],
DB_PASSWORD: [
"ah8jak3hk8dhiu4dw7whxwe1l",
"personal",
],
TWILIO_AUTH_TOKEN: [ TWILIO_AUTH_TOKEN: [
"hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG", "hgSIwDAKvz8PJfkj6xkzYqzGmAP3HLuG",
"shared", "shared",
@@ -155,20 +122,13 @@ const attemptLogin = async (
WEBSITE_URL: ["http://localhost:3000", "shared"], WEBSITE_URL: ["http://localhost:3000", "shared"],
STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"], STRIPE_SECRET_KEY: ["sk_test_7348oyho4hfq398HIUOH78", "shared"],
}, },
projectToLogin, workspaceId: projectToLogin,
"Development" env: "Development",
); });
} }
try {
if (email) { if (email) {
if (ENV == "production") { telemetry.identify(email);
const posthog = initPostHog(); telemetry.capture("User Logged In");
posthog.identify(email);
posthog.capture("User Logged In");
}
}
} catch (error) {
console.log("posthog", error);
} }
if (isLogin) { if (isLogin) {
@@ -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. * 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, password,
setPasswordErrorLength, setPasswordErrorLength,
setPasswordErrorNumber, setPasswordErrorNumber,
setPasswordErrorLowerCase, setPasswordErrorLowerCase,
currentErrorCheck currentErrorCheck,
) => { }: PasswordCheckProps) => {
let errorCheck = currentErrorCheck; let errorCheck = currentErrorCheck;
if (!password || password.length < 14) { if (!password || password.length < 14) {
setPasswordErrorLength(true); setPasswordErrorLength(true);
@@ -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;
};
@@ -4,8 +4,6 @@ const POSTHOG_HOST =
process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com"; process.env.NEXT_PUBLIC_POSTHOG_HOST! || "https://app.posthog.com";
const STRIPE_PRODUCT_PRO = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_PRO!; const STRIPE_PRODUCT_PRO = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_PRO!;
const STRIPE_PRODUCT_STARTER = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_STARTER!; const STRIPE_PRODUCT_STARTER = process.env.NEXT_PUBLIC_STRIPE_PRODUCT_STARTER!;
const TELEMETRY_ENABLED =
process.env.NEXT_PUBLIC_TELEMETRY_ENABLED! !== "false";
export { export {
ENV, ENV,
@@ -13,5 +11,4 @@ export {
POSTHOG_HOST, POSTHOG_HOST,
STRIPE_PRODUCT_PRO, STRIPE_PRODUCT_PRO,
STRIPE_PRODUCT_STARTER, STRIPE_PRODUCT_STARTER,
TELEMETRY_ENABLED,
}; };
@@ -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
);
}
}
};
@@ -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;
+427 -143
View File
@@ -50,13 +50,13 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/typography": "^0.5.4", "@tailwindcss/typography": "^0.5.4",
"@types/node": "18.11.9", "@types/node": "18.11.9",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.7",
"eslint": "^8.29.0", "eslint": "^8.29.0",
"eslint-config-next": "^13.0.5", "eslint-config-next": "^13.0.5",
"eslint-import-resolver-typescript": "^3.5.2", "eslint-import-resolver-typescript": "^3.5.2",
"eslint-plugin-prettier": "^4.2.1",
"eslint-plugin-simple-import-sort": "^8.0.0", "eslint-plugin-simple-import-sort": "^8.0.0",
"postcss": "^8.4.14", "postcss": "^8.4.14",
"prettier": "2.7.1", "prettier": "2.7.1",
@@ -64,6 +64,32 @@
"typescript": "^4.9.3" "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": { "node_modules/@babel/code-frame": {
"version": "7.18.6", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
@@ -75,12 +101,83 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/generator": { "node_modules/@babel/compat-data": {
"version": "7.19.0", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "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": { "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", "@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1" "jsesc": "^2.5.1"
}, },
@@ -99,6 +196,33 @@
"node": ">=6.9.0" "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": { "node_modules/@babel/helper-environment-visitor": {
"version": "7.18.9", "version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "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": ">=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": { "node_modules/@babel/helper-plugin-utils": {
"version": "7.19.0", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", "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": ">=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": { "node_modules/@babel/helper-split-export-declaration": {
"version": "7.18.6", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "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": { "node_modules/@babel/helper-string-parser": {
"version": "7.18.10", "version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==", "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@babel/helper-validator-identifier": { "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", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==", "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": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
} }
@@ -190,9 +368,9 @@
} }
}, },
"node_modules/@babel/parser": { "node_modules/@babel/parser": {
"version": "7.19.1", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==", "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==",
"bin": { "bin": {
"parser": "bin/babel-parser.js" "parser": "bin/babel-parser.js"
}, },
@@ -252,18 +430,18 @@
} }
}, },
"node_modules/@babel/traverse": { "node_modules/@babel/traverse": {
"version": "7.19.1", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==", "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.18.6", "@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-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0", "@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.19.1", "@babel/parser": "^7.20.5",
"@babel/types": "^7.19.0", "@babel/types": "^7.20.5",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@@ -293,12 +471,12 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
}, },
"node_modules/@babel/types": { "node_modules/@babel/types": {
"version": "7.19.0", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.18.10", "@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
}, },
"engines": { "engines": {
@@ -1143,9 +1321,9 @@
"optional": true "optional": true
}, },
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "18.0.15", "version": "18.0.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==", "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
"dependencies": { "dependencies": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -1882,7 +2060,6 @@
"version": "4.21.3", "version": "4.21.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
"integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -2472,8 +2649,7 @@
"node_modules/electron-to-chromium": { "node_modules/electron-to-chromium": {
"version": "1.4.206", "version": "1.4.206",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz",
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==", "integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA=="
"dev": true
}, },
"node_modules/emoji-regex": { "node_modules/emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
@@ -2595,7 +2771,6 @@
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": { "engines": {
"node": ">=6" "node": ">=6"
} }
@@ -2901,27 +3076,6 @@
"semver": "bin/semver.js" "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": { "node_modules/eslint-plugin-react": {
"version": "7.31.11", "version": "7.31.11",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz", "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==", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true "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": { "node_modules/fast-glob": {
"version": "3.2.11", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@@ -3523,6 +3671,15 @@
"url": "https://github.com/sponsors/ljharb" "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": { "node_modules/get-intrinsic": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
@@ -4253,6 +4410,18 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true "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": { "node_modules/jsonp": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
@@ -5153,8 +5322,7 @@
"node_modules/node-releases": { "node_modules/node-releases": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
"dev": true
}, },
"node_modules/normalize-path": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
@@ -5624,18 +5792,6 @@
"url": "https://github.com/prettier/prettier?sponsor=1" "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": { "node_modules/process-nextick-args": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -7042,7 +7198,6 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
"integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
"dev": true,
"funding": [ "funding": [
{ {
"type": "opencollective", "type": "opencollective",
@@ -7248,6 +7403,28 @@
} }
}, },
"dependencies": { "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": { "@babel/code-frame": {
"version": "7.18.6", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
@@ -7256,12 +7433,64 @@
"@babel/highlight": "^7.18.6" "@babel/highlight": "^7.18.6"
} }
}, },
"@babel/generator": { "@babel/compat-data": {
"version": "7.19.0", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.19.0.tgz", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-S1ahxf1gZ2dpoiFgA+ohK9DIpz50bJ0CWs7Zlzb54Z4sG8qmdIrGrVqmy1sAtTVRb+9CU6U8VqT9L0Zj7hxHVg==", "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": { "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", "@jridgewell/gen-mapping": "^0.3.2",
"jsesc": "^2.5.1" "jsesc": "^2.5.1"
} }
@@ -7274,6 +7503,26 @@
"@babel/types": "^7.18.6" "@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": { "@babel/helper-environment-visitor": {
"version": "7.18.9", "version": "7.18.9",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", "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/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": { "@babel/helper-plugin-utils": {
"version": "7.19.0", "version": "7.19.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.19.0.tgz",
"integrity": "sha512-40Ryx7I8mT+0gaNxm8JGTZFUITNqdLAgdg0hXzeVZxVD6nFsdhQvip6v8dqkRHzsz1VFpFAaOCHNn0vKBL7Czw==" "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": { "@babel/helper-split-export-declaration": {
"version": "7.18.6", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", "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": { "@babel/helper-string-parser": {
"version": "7.18.10", "version": "7.19.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.18.10.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz",
"integrity": "sha512-XtIfWmeNY3i4t7t4D2t02q50HvqHybPqW2ki1kosnvWCwuCMeo81Jf0gwr85jy/neUdg5XDdeFE/80DXiO+njw==" "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw=="
}, },
"@babel/helper-validator-identifier": { "@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", "version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.18.6.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-MmetCkz9ej86nJQV+sFCxoGGrUbU3q02kgLciwkrt9QqEB7cP39oKEY0PakknEO0Gu20SskMRi+AYZ3b1TpN9g==" "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": { "@babel/highlight": {
"version": "7.18.6", "version": "7.18.6",
@@ -7338,9 +7629,9 @@
} }
}, },
"@babel/parser": { "@babel/parser": {
"version": "7.19.1", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz",
"integrity": "sha512-h7RCSorm1DdTVGJf3P2Mhj3kdnkmF/EiysUkzS2TdgAYqyjFdMQJbVuXOBej2SBJaXan/lIVtT6KkGbyyq753A==" "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA=="
}, },
"@babel/plugin-syntax-jsx": { "@babel/plugin-syntax-jsx": {
"version": "7.18.6", "version": "7.18.6",
@@ -7379,18 +7670,18 @@
} }
}, },
"@babel/traverse": { "@babel/traverse": {
"version": "7.19.1", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.19.1.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz",
"integrity": "sha512-0j/ZfZMxKukDaag2PtOPDbwuELqIar6lLskVPPJDjXMXjfLb1Obo/1yjxIGqqAJrmfaTIY3z2wFLAQ7qSkLsuA==", "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==",
"requires": { "requires": {
"@babel/code-frame": "^7.18.6", "@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-environment-visitor": "^7.18.9",
"@babel/helper-function-name": "^7.19.0", "@babel/helper-function-name": "^7.19.0",
"@babel/helper-hoist-variables": "^7.18.6", "@babel/helper-hoist-variables": "^7.18.6",
"@babel/helper-split-export-declaration": "^7.18.6", "@babel/helper-split-export-declaration": "^7.18.6",
"@babel/parser": "^7.19.1", "@babel/parser": "^7.20.5",
"@babel/types": "^7.19.0", "@babel/types": "^7.20.5",
"debug": "^4.1.0", "debug": "^4.1.0",
"globals": "^11.1.0" "globals": "^11.1.0"
}, },
@@ -7411,12 +7702,12 @@
} }
}, },
"@babel/types": { "@babel/types": {
"version": "7.19.0", "version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.19.0.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz",
"integrity": "sha512-YuGopBq3ke25BVSiS6fgF49Ul9gH1x70Bcr6bqRLjWCkcX8Hre1/5+z+IiWOIerRMSSEfGZVB9z9kyq7wVs9YA==", "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==",
"requires": { "requires": {
"@babel/helper-string-parser": "^7.18.10", "@babel/helper-string-parser": "^7.19.4",
"@babel/helper-validator-identifier": "^7.18.6", "@babel/helper-validator-identifier": "^7.19.1",
"to-fast-properties": "^2.0.0" "to-fast-properties": "^2.0.0"
} }
}, },
@@ -7666,7 +7957,8 @@
"@headlessui/react": { "@headlessui/react": {
"version": "1.6.6", "version": "1.6.6",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz", "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": { "@humanwhocodes/config-array": {
"version": "0.11.7", "version": "0.11.7",
@@ -8007,9 +8299,9 @@
"optional": true "optional": true
}, },
"@types/react": { "@types/react": {
"version": "18.0.15", "version": "18.0.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.15.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz",
"integrity": "sha512-iz3BtLuIYH1uWdsv6wXYdhozhqj20oD4/Hk2DNXIn1kFsmp9x8d9QB6FnPhfkbhd2PgEONt9Q1x/ebkwjfFLow==", "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==",
"requires": { "requires": {
"@types/prop-types": "*", "@types/prop-types": "*",
"@types/scheduler": "*", "@types/scheduler": "*",
@@ -8247,7 +8539,8 @@
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true "dev": true,
"requires": {}
}, },
"acorn-node": { "acorn-node": {
"version": "1.8.2", "version": "1.8.2",
@@ -8450,7 +8743,8 @@
"axios-auth-refresh": { "axios-auth-refresh": {
"version": "3.3.3", "version": "3.3.3",
"resolved": "https://registry.npmjs.org/axios-auth-refresh/-/axios-auth-refresh-3.3.3.tgz", "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": { "axobject-query": {
"version": "2.2.0", "version": "2.2.0",
@@ -8531,7 +8825,6 @@
"version": "4.21.3", "version": "4.21.3",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.3.tgz",
"integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==", "integrity": "sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==",
"dev": true,
"requires": { "requires": {
"caniuse-lite": "^1.0.30001370", "caniuse-lite": "^1.0.30001370",
"electron-to-chromium": "^1.4.202", "electron-to-chromium": "^1.4.202",
@@ -8980,8 +9273,7 @@
"electron-to-chromium": { "electron-to-chromium": {
"version": "1.4.206", "version": "1.4.206",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.206.tgz",
"integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA==", "integrity": "sha512-h+Fadt1gIaQ06JaIiyqPsBjJ08fV5Q7md+V8bUvQW/9OvXfL2LRICTz2EcnnCP7QzrFTS6/27MRV6Bl9Yn97zA=="
"dev": true
}, },
"emoji-regex": { "emoji-regex": {
"version": "9.2.2", "version": "9.2.2",
@@ -9082,8 +9374,7 @@
"escalade": { "escalade": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
"dev": true
}, },
"escape-string-regexp": { "escape-string-regexp": {
"version": "1.0.5", "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": { "eslint-plugin-react": {
"version": "7.31.11", "version": "7.31.11",
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.31.11.tgz",
@@ -9464,13 +9746,15 @@
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
"dev": true "dev": true,
"requires": {}
}, },
"eslint-plugin-simple-import-sort": { "eslint-plugin-simple-import-sort": {
"version": "8.0.0", "version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz", "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==", "integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
"dev": true "dev": true,
"requires": {}
}, },
"eslint-scope": { "eslint-scope": {
"version": "7.1.1", "version": "7.1.1",
@@ -9583,12 +9867,6 @@
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true "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": { "fast-glob": {
"version": "3.2.11", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz",
@@ -9755,6 +10033,12 @@
"integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
"dev": true "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": { "get-intrinsic": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz",
@@ -10269,6 +10553,12 @@
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
"dev": true "dev": true
}, },
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"peer": true
},
"jsonp": { "jsonp": {
"version": "0.2.1", "version": "0.2.1",
"resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz",
@@ -10854,8 +11144,7 @@
"node-releases": { "node-releases": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==", "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
"dev": true
}, },
"normalize-path": { "normalize-path": {
"version": "3.0.0", "version": "3.0.0",
@@ -11161,15 +11450,6 @@
"integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==",
"dev": true "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": { "process-nextick-args": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -11441,7 +11721,8 @@
"react-table": { "react-table": {
"version": "7.8.0", "version": "7.8.0",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz", "resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==" "integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==",
"requires": {}
}, },
"read-cache": { "read-cache": {
"version": "1.0.0", "version": "1.0.0",
@@ -11482,7 +11763,8 @@
"redux-thunk": { "redux-thunk": {
"version": "2.4.1", "version": "2.4.1",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", "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": { "regenerator-runtime": {
"version": "0.13.11", "version": "0.13.11",
@@ -11834,7 +12116,8 @@
"styled-jsx": { "styled-jsx": {
"version": "5.0.7", "version": "5.0.7",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==" "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
"requires": {}
}, },
"stylis": { "stylis": {
"version": "4.0.13", "version": "4.0.13",
@@ -12179,7 +12462,6 @@
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.5.tgz",
"integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==", "integrity": "sha512-dteFFpCyvuDdr9S/ff1ISkKt/9YZxKjI9WlRR99c180GaztJtRa/fn18FdxGVKVsnPY7/a/FDN68mcvUmP4U7Q==",
"dev": true,
"requires": { "requires": {
"escalade": "^3.1.1", "escalade": "^3.1.1",
"picocolors": "^1.0.0" "picocolors": "^1.0.0"
@@ -12197,12 +12479,14 @@
"use-memo-one": { "use-memo-one": {
"version": "1.1.3", "version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz", "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": { "use-sync-external-store": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz", "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": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
+1
View File
@@ -53,6 +53,7 @@
"devDependencies": { "devDependencies": {
"@tailwindcss/typography": "^0.5.4", "@tailwindcss/typography": "^0.5.4",
"@types/node": "18.11.9", "@types/node": "18.11.9",
"@types/react": "^18.0.26",
"@typescript-eslint/eslint-plugin": "^5.45.0", "@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0", "@typescript-eslint/parser": "^5.45.0",
"autoprefixer": "^10.4.7", "autoprefixer": "^10.4.7",
+7 -8
View File
@@ -2,11 +2,11 @@ import { useEffect } from "react";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
import { config } from "@fortawesome/fontawesome-svg-core"; 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 RouteGuard from "~/components/RouteGuard";
import { publicPaths } from "~/const"; import { publicPaths } from "~/const";
import { ENV } from "~/utilities/config"; import Telemetry from "~/utilities/telemetry/Telemetry";
import "@fortawesome/fontawesome-svg-core/styles.css"; import "@fortawesome/fontawesome-svg-core/styles.css";
import "../styles/globals.css"; import "../styles/globals.css";
@@ -15,17 +15,14 @@ config.autoAddCss = false;
const App = ({ Component, pageProps, ...appProps }) => { const App = ({ Component, pageProps, ...appProps }) => {
const router = useRouter(); const router = useRouter();
const posthog = initPostHog();
useEffect(() => { useEffect(() => {
// Init for auto capturing // Init for auto capturing
const posthog = initPostHog(); const telemetry = new Telemetry().getInstance();
const handleRouteChange = () => { const handleRouteChange = () => {
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
if (ENV == "production") { telemetry.capture("$pageview");
posthog.capture("$pageview");
}
} }
}; };
@@ -46,9 +43,11 @@ const App = ({ Component, pageProps, ...appProps }) => {
return ( return (
<RouteGuard> <RouteGuard>
<NotificationProvider>
<Layout> <Layout>
<Component {...pageProps} /> <Component {...pageProps} />
</Layout> </Layout>
</NotificationProvider>
</RouteGuard> </RouteGuard>
); );
}; };
-20
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;
+32
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;
-28
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;
+36
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;
@@ -6,7 +6,7 @@ import SecurityClient from "~/utilities/SecurityClient";
* @param {*} res * @param {*} res
* @returns * @returns
*/ */
const getOrganizationUserProjects = (req, res) => { const getOrganizationUserProjects = (req) => {
return SecurityClient.fetchCall( return SecurityClient.fetchCall(
"/api/v1/organization/" + req.orgId + "/my-workspaces", "/api/v1/organization/" + req.orgId + "/my-workspaces",
{ {
+11 -3
View File
@@ -1,5 +1,12 @@
import SecurityClient from "~/utilities/SecurityClient"; 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 * This route lets us get the workspaces of a certain user
* @returns * @returns
@@ -12,10 +19,11 @@ const getWorkspaces = () => {
}, },
}).then(async (res) => { }).then(async (res) => {
if (res?.status == 200) { if (res?.status == 200) {
return (await res.json()).workspaces; const data = (await res.json()) as unknown as { workspaces: Workspace[] };
} else { return data.workspaces;
console.log("Failed to get projects");
} }
throw new Error("Failed to get projects");
}); });
}; };
+42 -12
View File
@@ -26,6 +26,7 @@ import { Menu, Transition } from "@headlessui/react";
import Button from "~/components/basic/buttons/Button"; import Button from "~/components/basic/buttons/Button";
import ListBox from "~/components/basic/Listbox"; import ListBox from "~/components/basic/Listbox";
import BottonRightPopup from "~/components/basic/popups/BottomRightPopup"; import BottonRightPopup from "~/components/basic/popups/BottomRightPopup";
import { useNotificationContext } from "~/components/context/Notifications/NotificationProvider";
import DashboardInputField from "~/components/dashboard/DashboardInputField"; import DashboardInputField from "~/components/dashboard/DashboardInputField";
import DropZone from "~/components/dashboard/DropZone"; import DropZone from "~/components/dashboard/DropZone";
import NavHeader from "~/components/navigation/NavHeader"; import NavHeader from "~/components/navigation/NavHeader";
@@ -60,7 +61,7 @@ const KeyPair = ({
modifyValue, modifyValue,
modifyVisibility, modifyVisibility,
isBlurred, isBlurred,
duplicates duplicates,
}) => { }) => {
const [randomStringLength, setRandomStringLength] = useState(32); const [randomStringLength, setRandomStringLength] = useState(32);
@@ -227,6 +228,8 @@ export default function Dashboard() {
const [checkDocsPopUpVisible, setCheckDocsPopUpVisible] = useState(false); const [checkDocsPopUpVisible, setCheckDocsPopUpVisible] = useState(false);
const [hasUserEverPushed, setHasUserEverPushed] = useState(false); const [hasUserEverPushed, setHasUserEverPushed] = useState(false);
const { createNotification } = useNotificationContext();
// #TODO: fix save message for changing reroutes // #TODO: fix save message for changing reroutes
// const beforeRouteHandler = (url) => { // const beforeRouteHandler = (url) => {
// const warningText = // const warningText =
@@ -370,17 +373,33 @@ export default function Dashboard() {
); );
// Checking if any of the secret keys start with a number - if so, don't do anything // 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 nameErrors = !Object.keys(obj)
const duplicatesExist = data?.map(item => item[2]).filter((item, index) => index !== data?.map(item => item[2]).indexOf(item)).length > 0; .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) { if (nameErrors) {
console.log("Solve all name errors first!"); return createNotification({
} else if (duplicatesExist) { text: "Solve all name errors first!",
console.log("Remove the duplicated entries first!"); type: "error",
} else { });
// Once "Save changes is clicked", disable that button }
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); setButtonReady(false);
pushKeys({obj, workspaceId: router.query.id, env}); pushKeys({ obj, workspaceId: router.query.id, env });
/** /**
* Check which integrations are active for this project and environment * Check which integrations are active for this project and environment
@@ -410,7 +429,6 @@ export default function Dashboard() {
setCheckDocsPopUpVisible(true); setCheckDocsPopUpVisible(true);
await registerUserAction({ action: "first_time_secrets_pushed" }); await registerUserAction({ action: "first_time_secrets_pushed" });
} }
}
}; };
const addData = (newData) => { const addData = (newData) => {
@@ -649,7 +667,13 @@ export default function Dashboard() {
modifyKey={listenChangeKey} modifyKey={listenChangeKey}
modifyVisibility={listenChangeVisibility} modifyVisibility={listenChangeVisibility}
isBlurred={blurred} 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> </div>
@@ -697,7 +721,13 @@ export default function Dashboard() {
modifyKey={listenChangeKey} modifyKey={listenChangeKey}
modifyVisibility={listenChangeVisibility} modifyVisibility={listenChangeVisibility}
isBlurred={blurred} 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> </div>
@@ -1,4 +1,5 @@
import React, { useEffect, useRef, useState } from "react"; import React, { useEffect, useRef, useState } from "react";
import ReactCodeInput from "react-code-input";
import dynamic from "next/dynamic"; import dynamic from "next/dynamic";
import Head from "next/head"; import Head from "next/head";
import Image from "next/image"; import Image from "next/image";
@@ -20,7 +21,7 @@ import completeAccountInformationSignup from "./api/auth/CompleteAccountInformat
import sendVerificationEmail from "./api/auth/SendVerificationEmail"; import sendVerificationEmail from "./api/auth/SendVerificationEmail";
import getWorkspaces from "./api/workspace/getWorkspaces"; 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 nacl = require("tweetnacl");
const jsrp = require("jsrp"); const jsrp = require("jsrp");
nacl.util = require("tweetnacl-util"); nacl.util = require("tweetnacl-util");
@@ -42,7 +43,7 @@ const props = {
border: "1px solid gray", border: "1px solid gray",
textAlign: "center", textAlign: "center",
}, },
}; } as const;
const propsPhone = { const propsPhone = {
inputStyle: { inputStyle: {
fontFamily: "monospace", fontFamily: "monospace",
@@ -58,7 +59,7 @@ const propsPhone = {
border: "1px solid gray", border: "1px solid gray",
textAlign: "center", textAlign: "center",
}, },
}; } as const;
export default function SignUp() { export default function SignUp() {
const [email, setEmail] = useState(""); const [email, setEmail] = useState("");
@@ -85,15 +86,16 @@ export default function SignUp() {
const [verificationToken, setVerificationToken] = useState(); const [verificationToken, setVerificationToken] = useState();
const [backupKeyIssued, setBackupKeyIssued] = useState(false); const [backupKeyIssued, setBackupKeyIssued] = useState(false);
useEffect(async () => { useEffect(() => {
let userWorkspace; const tryAuth = async () => {
try { try {
const userWorkspaces = await getWorkspaces(); const userWorkspaces = await getWorkspaces();
userWorkspace = userWorkspaces[0]._id; router.push("/dashboard/" + userWorkspaces[0]._id);
router.push("/dashboard/" + userWorkspace);
} catch (error) { } catch (error) {
console.log("Error - Not logged in yet"); console.log("Error - Not logged in yet");
} }
};
tryAuth();
}, []); }, []);
/** /**
@@ -108,7 +110,7 @@ export default function SignUp() {
} else if (step == 2) { } else if (step == 2) {
// Checking if the code matches the email. // Checking if the code matches the email.
const response = await checkEmailVerificationCode(email, code); const response = await checkEmailVerificationCode(email, code);
if (response.status == "200" || code == "111222") { if (response.status === 200 || code == "111222") {
setVerificationToken((await response.json()).token); setVerificationToken((await response.json()).token);
setStep(3); setStep(3);
} else { } else {
@@ -123,7 +125,7 @@ export default function SignUp() {
* Verifies if the entered email "looks" correct * Verifies if the entered email "looks" correct
*/ */
const emailCheck = () => { const emailCheck = () => {
var emailCheckBool = false; let emailCheckBool = false;
if (!email) { if (!email) {
setEmailError(true); setEmailError(true);
setEmailErrorMessage("Please enter your email."); 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. // Verifies if the imformation that the users entered (name, workspace) is there, and if the password matched the criteria.
const signupErrorCheck = async () => { const signupErrorCheck = async () => {
setIsLoading(true); setIsLoading(true);
var errorCheck = false; let errorCheck = false;
if (!firstName) { if (!firstName) {
setFirstNameError(true); setFirstNameError(true);
errorCheck = true; errorCheck = true;
@@ -163,13 +165,13 @@ export default function SignUp() {
} else { } else {
setLastNameError(false); setLastNameError(false);
} }
errorCheck = passwordCheck( errorCheck = passwordCheck({
password, password,
setPasswordErrorLength, setPasswordErrorLength,
setPasswordErrorNumber, setPasswordErrorNumber,
setPasswordErrorLowerCase, setPasswordErrorLowerCase,
errorCheck currentErrorCheck: errorCheck,
); });
if (!errorCheck) { if (!errorCheck) {
// Generate a random pair of a public and a private key // 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), 32 + (password.slice(0, 32).length - new Blob([password]).size),
"0" "0"
) )
); ) as { ciphertext: string; iv: string; tag: string };
localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY); localStorage.setItem("PRIVATE_KEY", PRIVATE_KEY);
client.init( client.init(
@@ -196,8 +199,9 @@ export default function SignUp() {
password: password, password: password,
}, },
async () => { async () => {
client.createVerifier(async (err, result) => { client.createVerifier(
let response = await completeAccountInformationSignup({ async (err: any, result: { salt: string; verifier: string }) => {
const response = await completeAccountInformationSignup({
email, email,
firstName, firstName,
lastName, lastName,
@@ -212,8 +216,8 @@ export default function SignUp() {
}); });
// if everything works, go the main dashboard page. // if everything works, go the main dashboard page.
if (!errorCheck && response.status == "200") { if (response.status === 200) {
response = await response.json(); // response = await response.json();
localStorage.setItem("publicKey", PUBLIC_KEY); localStorage.setItem("publicKey", PUBLIC_KEY);
localStorage.setItem("encryptedPrivateKey", ciphertext); localStorage.setItem("encryptedPrivateKey", ciphertext);
@@ -234,7 +238,8 @@ export default function SignUp() {
setIsLoading(false); setIsLoading(false);
} }
} }
}); }
);
} }
); );
} else { } else {
@@ -296,6 +301,8 @@ export default function SignUp() {
</p> </p>
<div className="hidden md:block"> <div className="hidden md:block">
<ReactCodeInput <ReactCodeInput
name=""
inputMode="tel"
type="text" type="text"
fields={6} fields={6}
onChange={setCode} onChange={setCode}
@@ -305,6 +312,8 @@ export default function SignUp() {
</div> </div>
<div className="block md:hidden"> <div className="block md:hidden">
<ReactCodeInput <ReactCodeInput
name=""
inputMode="tel"
type="text" type="text"
fields={6} fields={6}
onChange={setCode} 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"> <div className="mt-2 flex flex-col items-center justify-center w-full md:p-2 rounded-lg max-h-60">
<InputField <InputField
label="Password" label="Password"
onChangeHandler={(password) => { onChangeHandler={(password: string) => {
setPassword(password); setPassword(password);
passwordCheck( passwordCheck({
password, password,
setPasswordErrorLength, setPasswordErrorLength,
setPasswordErrorNumber, setPasswordErrorNumber,
setPasswordErrorLowerCase, setPasswordErrorLowerCase,
false currentErrorCheck: false,
); });
}} }}
type="password" type="password"
value={password} value={password}
@@ -496,7 +505,7 @@ export default function SignUp() {
setBackupKeyIssued, setBackupKeyIssued,
}); });
const userWorkspaces = await getWorkspaces(); const userWorkspaces = await getWorkspaces();
let userWorkspace = userWorkspaces[0]._id; const userWorkspace = userWorkspaces[0]._id;
router.push("/home/" + userWorkspace); router.push("/home/" + userWorkspace);
}} }}
size="lg" size="lg"
+16
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
+8
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
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