1
0
mirror of https://github.com/Infisical/infisical.git synced 2025-03-20 22:32:28 +00:00

Compare commits

..

102 Commits

Author SHA1 Message Date
c086579260 Merge pull request from jon4hz/main
fix homebrew
2023-02-01 21:44:22 -08:00
3d14bc9a00 remove env name check 2023-02-01 20:31:25 -08:00
f2175b948c Merge pull request from nirga/main
chore: fix typo in quick start guide
2023-02-01 13:17:54 -08:00
6f3d102ecb chore: fix typo in quick start guide 2023-02-01 23:15:39 +02:00
54fa39f347 Fixed issues with breadcrumbs and redirects of forgot password 2023-02-01 12:22:41 -08:00
c99b207e9e ci: maybe fix brew 2023-02-01 14:28:12 +01:00
4886537a56 Revert "Revert "Merge pull request from jon4hz/main""
This reverts commit 1878bed10a1e06a8340d8b02385a8d0081394d61.
2023-02-01 14:19:49 +01:00
71cf54c28b add auto cli version to all-other-builds 2023-01-31 20:19:42 -08:00
1878bed10a Revert "Merge pull request from jon4hz/main"
This reverts commit 87fd5e33f11a354a622990fb58d185d8094f29c6, reversing
changes made to 2c4e066f6421c461e28129fedc14fb6fb6b2b1b9.
2023-01-31 20:17:15 -08:00
87fd5e33f1 Merge pull request from jon4hz/main
CI Improvements
2023-01-31 19:39:46 -08:00
ffda30bd65 ci: mark goreleaser snapshots as such 2023-02-01 03:54:22 +01:00
716795532e ci: bump goreleaser action 2023-02-01 03:38:18 +01:00
f9ff99748b ci: remove obsolete var 2023-02-01 03:37:07 +01:00
723fa153be ci: completion and manpages for homebrew 2023-02-01 03:36:26 +01:00
1871d1a842 fix: improve goreleaser 2023-02-01 03:35:54 +01:00
2c4e066f64 bring back auto cli version in CI 2023-01-31 17:34:50 -08:00
b371dad506 Increase cli version 2023-01-31 17:22:44 -08:00
a6d4431940 Auto add cli version from tag 2023-01-31 17:03:19 -08:00
871d80aad5 when login expired, do not ask to override login 2023-01-31 16:37:56 -08:00
6711979445 Disallow service token creation based on permission 2023-01-31 09:24:55 -08:00
cb080b356c increase cli version 2023-01-30 22:17:02 -08:00
9950c5e02d empty commit 2023-01-30 22:15:44 -08:00
22a11be4e0 Update host rules for permissioning 2023-01-30 21:38:09 -08:00
6e01c80282 Merge branch 'main' of https://github.com/Infisical/infisical 2023-01-30 21:14:41 -08:00
4e14f84df9 Allow editing personal permissions 2023-01-30 21:14:22 -08:00
55522404b4 Merge pull request from Infisical/dependabot/npm_and_yarn/backend/cookiejar-2.1.4
Bump cookiejar from 2.1.3 to 2.1.4 in /backend
2023-01-30 20:37:44 -08:00
4ef8c273f7 Wired access controls for environemnts to frontend 2023-01-30 20:36:04 -08:00
61c17ccc5e update getAllAccessibleEnvironmentsOfWorkspace controller 2023-01-30 19:39:45 -08:00
2832476c2b Add write permission status 2023-01-30 19:38:40 -08:00
c0fc74b62a Add write permission status 2023-01-30 19:22:52 -08:00
54caaffe3a Bump cookiejar from 2.1.3 to 2.1.4 in /backend
Bumps [cookiejar](https://github.com/bmeck/node-cookiejar) from 2.1.3 to 2.1.4.
- [Release notes](https://github.com/bmeck/node-cookiejar/releases)
- [Commits](https://github.com/bmeck/node-cookiejar/commits)

---
updated-dependencies:
- dependency-name: cookiejar
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-30 12:41:45 +00:00
55f0a491cb Release fly.io integrartion 2023-01-29 22:38:20 -08:00
a940fa210a Add deny api/get envs api 2023-01-29 21:12:41 -08:00
5162ba9b91 add basic auth model for Organization 2023-01-29 21:12:41 -08:00
3b6022de64 Merge branch 'main' of https://github.com/Infisical/infisical 2023-01-29 15:55:22 -08:00
bf743f5f72 Make the loading animation smaller 2023-01-29 15:55:01 -08:00
3e177539d5 Remove state from password controllers 2023-01-29 15:48:42 -08:00
5743dd3a8c Merge pull request from Neeraj138/subscription-check
Add check for subscriptions call before setting the current plan
2023-01-29 09:25:04 -08:00
9f8ad95a59 Revert "correct tags in docker image workflow"
This reverts commit 3ef2ac8a77b50c1fbac1fa2173acccbf1736a011.
2023-01-29 09:17:22 -08:00
3c05a4cebd Add check for subscriptions call before setting the current plan 2023-01-29 14:16:05 +05:30
bc955a9afd increase cli version 2023-01-28 22:32:23 -08:00
ec8d86e662 Merge pull request from akhilmhdh/feat/react-query
feat(ui): added new auth guard with react-query and axios
2023-01-29 12:21:08 +07:00
bc70bedb78 Fixed the bug with empty variables 2023-01-28 20:41:54 -08:00
7a4b77ce59 Update README.md 2023-01-28 14:31:29 -08:00
8600cee54c Merge pull request from sanyamjain04/tailwind-plugin
added prettier-plugin-tailwindcss
2023-01-28 14:14:51 -08:00
fe9573ea3c Merge pull request from asheliahut/patch-1
Include Id on project
2023-01-28 14:11:32 -08:00
61db6c54c2 Merge pull request from kimcore/main
Skip update check if github returns non-200
2023-01-28 14:08:35 -08:00
65093c73c5 Merge pull request from mocherfaoui/inf-nsc-pt
New secrets are now added to the top in the dashboard UI
2023-01-28 13:54:24 -08:00
9986521e41 Merge pull request from kimcore/readme-ko
Translate README.md to korean
2023-01-28 13:35:13 -08:00
655f015109 Merge branch 'main' of https://github.com/Infisical/infisical 2023-01-28 12:53:51 -08:00
3cea59ce5d Improved docs SEO 2023-01-28 12:53:44 -08:00
a184192452 Inform k8 self host about latest tags 2023-01-28 12:34:04 -08:00
2dbcab32d5 update gamma pull image policy 2023-01-28 12:03:53 -08:00
13aeeb4731 console.log in posthog 2023-01-28 11:22:16 -08:00
233a468127 Revert "add console.log for post"
This reverts commit dd960aa5f045f62a556e67f81bf172372401a465.
2023-01-28 11:22:16 -08:00
8a9e05b08f Revert "add test comment for docker build issue"
This reverts commit fdac590a023433113ae21295dbe1abf165fb5500.
2023-01-28 11:22:16 -08:00
3ef2ac8a77 correct tags in docker image workflow 2023-01-28 11:14:00 -08:00
fdac590a02 add test comment for docker build issue 2023-01-28 10:25:42 -08:00
dd960aa5f0 add console.log for post 2023-01-28 10:04:34 -08:00
0bd9a848c4 add back depot 2023-01-28 09:53:06 -08:00
1b86c58f91 remove depot from docker build 2023-01-28 09:24:58 -08:00
d5166d343d Remove depot docker 2023-01-28 09:17:54 -08:00
b315cf6022 Translate README.md to korean 2023-01-29 00:20:10 +09:00
37de32ec90 return proper error 2023-01-28 23:13:36 +09:00
6eb81802c3 Skip update check if github returns non-200 2023-01-28 23:06:37 +09:00
e6068a6f7f Merge pull request from samsbg/main
Adding Spanish translation to the README 🌎ES
2023-01-27 18:39:35 -08:00
c059c088d1 update k8 selfhost docs values.yaml file 2023-01-27 12:42:47 -08:00
b530847edc increase chart version 2023-01-27 12:34:46 -08:00
c87c2dadd7 add readinessProbe check for pods 2023-01-27 12:31:46 -08:00
7b1ff04436 add deployment annotations 2023-01-27 10:45:42 -08:00
83aa440b62 Remove mongo url from envs 2023-01-27 10:43:23 -08:00
a555ef836b remove default sensitive keys 2023-01-27 09:33:49 -08:00
528601e442 Merge pull request from Infisical/patch-empty-values
Allow empty values for secrets
2023-01-27 22:16:24 +07:00
13acb19e9f Allow empty values for secrets 2023-01-27 22:07:56 +07:00
079063157f added prettier-plugin-tailwindcss 2023-01-27 12:16:23 +05:30
e38933c0b3 Include Id on project
The project should have its id exposed.
2023-01-26 19:32:44 -08:00
d09b406c4e Merge pull request from kmlgkcy/turkish-translation
translation: Turkish
2023-01-26 16:46:00 -08:00
a5eba8e722 Updated the billing engine for Cloud 2023-01-26 16:32:51 -08:00
7acb4cc22a fix helm deploymentAnnotations 2023-01-26 14:43:53 -08:00
b95ab6c6a1 added deploymentAnnotations to helm chart 2023-01-26 14:17:51 -08:00
038445e13e change from cal.com to calendly 2023-01-26 11:30:36 -08:00
07e9dd5a39 add managed secrets to deployment in gamma 2023-01-26 00:39:08 -08:00
6ec520d358 update helm values for k8 self host 2023-01-26 00:30:54 -08:00
06bfd2429b Update gemma helm chart with auto reload 2023-01-26 00:17:07 -08:00
099c4836e6 update helm charts to be more flexible 2023-01-26 00:14:07 -08:00
ddf8ceb45d translation: Turkish 2023-01-26 10:46:47 +03:00
8a49e0817a add error to failed org creation 2023-01-25 21:58:53 -08:00
88908297f5 add error object to log 2023-01-25 21:30:32 -08:00
cf0e111c09 increase replica count for gamma 2023-01-25 20:12:41 -08:00
ae0ee727fa Make backend login stateless 2023-01-25 20:09:57 -08:00
be2945c445 Merge pull request from Infisical/stripe-adjustment
Update backend envars types and add STRIPE_PRODUCT_TEAM envar
2023-01-26 10:22:54 +07:00
237a10da1e Update backend envars types and add STRIPE_PRODUCT_TEAM envar 2023-01-26 10:20:42 +07:00
1baf14084d new secrets are added to the top 2023-01-25 19:55:48 +01:00
a6387e7552 feat(ui): added new auth guard with react-query and axios 2023-01-26 00:14:01 +05:30
a6f480d3f8 increase CLI 2023-01-24 19:59:45 -08:00
0413059fbe patch executeMultipleCommandWithEnvs when no /bin/zsh 2023-01-24 19:59:45 -08:00
65f049f6ac Merge pull request from franky47/patch-1
docs: Fix typo in encryption overview
2023-01-24 19:51:10 -08:00
62f886a3b3 docs: Fix typo in encryption overview 2023-01-25 04:31:04 +01:00
271ca148e3 Make support link clickable 2023-01-24 11:01:49 -08:00
8aa294309f remove icon from support link 2023-01-24 10:53:46 -08:00
ca3233110b add support link for 1 on 1 in docs 2023-01-24 10:52:09 -08:00
08c54a910f Adding Spanish translation to the README 2023-01-22 01:42:25 -06:00
159 changed files with 3123 additions and 434 deletions
.env.example
.github
.goreleaser.yamlREADME.md
backend
cli/packages
docker-compose.dev.ymldocker-compose.yml
docs
frontend
helm-charts/infisical
i18n

@ -64,7 +64,7 @@ POSTHOG_PROJECT_API_KEY=
STRIPE_SECRET_KEY=
STRIPE_PUBLISHABLE_KEY=
STRIPE_WEBHOOK_SECRET=
STRIPE_PRODUCT_CARD_AUTH=
STRIPE_PRODUCT_PRO=
STRIPE_PRODUCT_STARTER=
STRIPE_PRODUCT_TEAM=
STRIPE_PRODUCT_PRO=
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=

83
.github/values.yaml vendored

@ -1,36 +1,93 @@
#####
# INFISICAL K8 DEFAULT VALUES FILE
# PLEASE REPLACE VALUES/EDIT AS REQUIRED
#####
nameOverride: ""
frontend:
replicaCount: 1
name: frontend
podAnnotations: {}
deploymentAnnotations:
secrets.infisical.com/auto-reload: "true"
replicaCount: 2
image:
repository:
pullPolicy: Always
repository: infisical/frontend
pullPolicy: Always
tag: "latest"
kubeSecretRef: managed-secret-frontend
service:
# type of the frontend service
type: ClusterIP
# define the nodePort if service type is NodePort
# nodePort:
annotations: {}
backend:
replicaCount: 1
name: backend
podAnnotations: {}
deploymentAnnotations:
secrets.infisical.com/auto-reload: "true"
replicaCount: 2
image:
repository:
repository: infisical/backend
pullPolicy: Always
tag: "latest"
kubeSecretRef: managed-backend-secret
service:
annotations: {}
mongodb:
name: mongodb
podAnnotations: {}
image:
repository: mongo
pullPolicy: IfNotPresent
tag: "latest"
service:
annotations: {}
# By default the backend will be connected to a Mongo instance in the cluster.
# However, it is recommended to add a managed document DB connection string because the DB instance in the cluster does not have persistence yet ( data will be deleted on next deploy).
# Learn about connection string type here https://www.mongodb.com/docs/manual/reference/connection-string/
mongodbConnection: {}
# externalMongoDBConnectionString: <>
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
hostName: gamma.infisical.com
hostName: gamma.infisical.com # replace with your domain
frontend:
path: /
pathType: Prefix
backend:
path: /api
pathType: Prefix
tls:
- secretName: echo-tls
hosts:
- gamma.infisical.com
tls: []
backendEnvironmentVariables:
frontendEnvironmentVariables:
## Complete Ingress example
# ingress:
# enabled: true
# annotations:
# kubernetes.io/ingress.class: "nginx"
# cert-manager.io/issuer: letsencrypt-nginx
# hostName: k8.infisical.com
# frontend:
# path: /
# pathType: Prefix
# backend:
# path: /api
# pathType: Prefix
# tls:
# - secretName: letsencrypt-nginx
# hosts:
# - k8.infisical.com
###
### YOU MUST FILL IN ALL SECRETS BELOW
###
backendEnvironmentVariables: {}
frontendEnvironmentVariables: {}

@ -19,6 +19,7 @@ jobs:
with:
fetch-depth: 0
- run: git fetch --force --tags
- run: echo "Ref name ${{github.ref_name}}"
- uses: actions/setup-go@v3
with:
go-version: '>=1.19.3'
@ -33,11 +34,11 @@ jobs:
run: |
mkdir ../../osxcross
git clone https://github.com/plentico/osxcross-target.git ../../osxcross/target
- uses: goreleaser/goreleaser-action@v2
- uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: release --rm-dist
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }}
FURY_TOKEN: ${{ secrets.FURYPUSHTOKEN }}

@ -14,6 +14,9 @@ before:
builds:
- id: darwin-build
binary: infisical
ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
flags:
- -trimpath
env:
- CGO_ENABLED=1
- CC=/home/runner/work/osxcross/target/bin/o64-clang
@ -24,10 +27,14 @@ builds:
- goos: darwin
goarch: "386"
dir: ./cli
- id: all-other-builds
env:
- CGO_ENABLED=0
binary: infisical
ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }}
flags:
- -trimpath
goos:
- freebsd
- linux
@ -65,8 +72,10 @@ release:
checksum:
name_template: 'checksums.txt'
snapshot:
name_template: "{{ incpatch .Version }}"
name_template: "{{ incpatch .Version }}-devel"
changelog:
sort: asc
filters:
@ -80,6 +89,7 @@ changelog:
# - infisical
# dir: "{{ dir .ArtifactPath }}"
# cmd: curl -F package=@{{ .ArtifactName }} https://{{ .Env.FURY_TOKEN }}@push.fury.io/infisical/
brews:
- name: infisical
tap:
@ -91,6 +101,13 @@ brews:
folder: Formula
homepage: "https://infisical.com"
description: "The official Infisical CLI"
install: |-
bin.install "infisical"
bash_completion.install "completions/infisical.bash" => "infisical"
zsh_completion.install "completions/infisical.zsh" => "_infisical"
fish_completion.install "completions/infisical.fish"
man1.install "manpages/infisical.1.gz"
nfpms:
- id: infisical
package_name: infisical
@ -116,6 +133,7 @@ nfpms:
dst: /usr/share/zsh/site-functions/_infisical
- src: ./manpages/infisical.1.gz
dst: /usr/share/man/man1/infisical.1.gz
scoop:
bucket:
owner: Infisical
@ -126,6 +144,7 @@ scoop:
homepage: "https://infisical.com"
description: "The official Infisical CLI"
license: MIT
aurs:
-
name: infisical-bin

@ -25,7 +25,7 @@
<img src="https://img.shields.io/github/commit-activity/m/infisical/infisical" alt="git commit activity" />
</a>
<a href="https://cloudsmith.io/~infisical/repos/">
<img src="https://img.shields.io/badge/Downloads-14.6k-orange" alt="Cloudsmith downloads" />
<img src="https://img.shields.io/badge/Downloads-19.9k-orange" alt="Cloudsmith downloads" />
</a>
<a href="https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g">
<img src="https://img.shields.io/badge/chat-on%20Slack-blueviolet" alt="Slack community channel" />
@ -37,6 +37,12 @@
<img src="/img/infisical_github_repo.png" width="100%" alt="Dashboard" />
**Read this in other languages**: <kbd>[<img title="English" alt="English language" src="https://cdn.staticaly.com/gh/hjnilsson/country-flags/master/svg/us.svg" width="22">](i18n/README.en.md)</kbd>
<kbd>[<img title="Spanish" alt="Spanish language" src="https://cdn.staticaly.com/gh/hjnilsson/country-flags/master/svg/es.svg" width="22">](i18n/README.es.md)</kbd>
<kbd>[<img title="Korean" alt="Korean language" src="https://cdn.staticaly.com/gh/hjnilsson/country-flags/master/svg/kr.svg" width="22">](i18n/README.ko.md)</kbd>
<kbd>[<img title="Turkish" alt="Turkish language" src="https://cdn.staticaly.com/gh/hjnilsson/country-flags/master/svg/tr.svg" width="22">](i18n/README.tr.md)</kbd>
**[Infisical](https://infisical.com)** is an open source, E2EE tool to help teams manage and sync secrets and configs across their development workflow and infrastructure. It's designed to be simple and take minutes to get going.
- **[User-Friendly Dashboard](https://infisical.com/docs/getting-started/dashboard/project)** to manage your team's secrets and configs within projects
@ -144,7 +150,9 @@ We're currently setting the foundation and building [integrations](https://infis
</a>
</td>
<td align="left" valign="middle">
🔜 Fly.io
<a href="https://infisical.com/docs/integrations/cloud/flyio">
✔️ Fly.io
</a>
</td>
</tr>
<tr>
@ -157,7 +165,7 @@ We're currently setting the foundation and building [integrations](https://infis
</a>
</td>
<td align="left" valign="middle">
🔜 Railway
🔜 Railway (https://github.com/Infisical/infisical/issues/271)
</td>
</tr>
<tr>
@ -192,7 +200,7 @@ We're currently setting the foundation and building [integrations](https://infis
</a>
</td>
<td align="left" valign="middle">
🔜 Railway
🔜 Forge
</td>
</tr>
<tr>
@ -203,7 +211,9 @@ We're currently setting the foundation and building [integrations](https://infis
🔜 Supabase
</td>
<td align="left" valign="middle">
🔜 Render (https://github.com/Infisical/infisical/issues/132)
<a href="https://infisical.com/docs/integrations/cloud/render">
✔️ Render
</a>
</td>
</tr>
</tbody>
@ -337,7 +347,7 @@ Infisical officially launched as v.1.0 on November 21st, 2022. There are a lot o
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<a href="https://github.com/dangtony98"><img src="https://avatars.githubusercontent.com/u/25857006?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/akhilmhdh"><img src="https://avatars.githubusercontent.com/u/31166322?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/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/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?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/gmgale"><img src="https://avatars.githubusercontent.com/u/62303146?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/JoaoVictor6"><img src="https://avatars.githubusercontent.com/u/68869379?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mocherfaoui"><img src="https://avatars.githubusercontent.com/u/37941426?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jon4hz"><img src="https://avatars.githubusercontent.com/u/26183582?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/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Zamion101"><img src="https://avatars.githubusercontent.com/u/8071263?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Grraahaam"><img src="https://avatars.githubusercontent.com/u/72856427?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Gabriellopes232"><img src="https://avatars.githubusercontent.com/u/74881862?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/naorpeled"><img src="https://avatars.githubusercontent.com/u/6171622?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jonerrr"><img src="https://avatars.githubusercontent.com/u/73760377?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/cerrussell"><img src="https://avatars.githubusercontent.com/u/80227828?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/imakecodes"><img src="https://avatars.githubusercontent.com/u/35536648?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arthurzenika"><img src="https://avatars.githubusercontent.com/u/445200?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/wjhurley"><img src="https://avatars.githubusercontent.com/u/15939055?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/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?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/maidul98"><img src="https://avatars.githubusercontent.com/u/9300960?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/akhilmhdh"><img src="https://avatars.githubusercontent.com/u/31166322?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/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/gangjun06"><img src="https://avatars.githubusercontent.com/u/50910815?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/gmgale"><img src="https://avatars.githubusercontent.com/u/62303146?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/JoaoVictor6"><img src="https://avatars.githubusercontent.com/u/68869379?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/mocherfaoui"><img src="https://avatars.githubusercontent.com/u/37941426?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/cerrussell"><img src="https://avatars.githubusercontent.com/u/80227828?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jon4hz"><img src="https://avatars.githubusercontent.com/u/26183582?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/arjunyel"><img src="https://avatars.githubusercontent.com/u/11153289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/LemmyMwaura"><img src="https://avatars.githubusercontent.com/u/20738858?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Zamion101"><img src="https://avatars.githubusercontent.com/u/8071263?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Grraahaam"><img src="https://avatars.githubusercontent.com/u/72856427?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/Gabriellopes232"><img src="https://avatars.githubusercontent.com/u/74881862?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/naorpeled"><img src="https://avatars.githubusercontent.com/u/6171622?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/jonerrr"><img src="https://avatars.githubusercontent.com/u/73760377?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/kmlgkcy"><img src="https://avatars.githubusercontent.com/u/102428035?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/samsbg"><img src="https://avatars.githubusercontent.com/u/70488844?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/imakecodes"><img src="https://avatars.githubusercontent.com/u/35536648?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/caioluis"><img src="https://avatars.githubusercontent.com/u/30005368?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/adrianmarinwork"><img src="https://avatars.githubusercontent.com/u/118568289?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/arthurzenika"><img src="https://avatars.githubusercontent.com/u/445200?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/franky47"><img src="https://avatars.githubusercontent.com/u/1174092?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/wjhurley"><img src="https://avatars.githubusercontent.com/u/15939055?v=4" width="50" height="50" alt=""/></a> <a href="https://github.com/alexdanilowicz"><img src="https://avatars.githubusercontent.com/u/29822597?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/wanjohiryan"><img src="https://avatars.githubusercontent.com/u/71614375?v=4" width="50" height="50" alt=""/></a>
## 🌎 Translations

@ -3,8 +3,10 @@ export {};
declare global {
namespace NodeJS {
interface ProcessEnv {
PORT: string;
EMAIL_TOKEN_LIFETIME: string;
ENCRYPTION_KEY: string;
SALT_ROUNDS: string;
JWT_AUTH_LIFETIME: string;
JWT_AUTH_SECRET: string;
JWT_REFRESH_LIFETIME: string;
@ -19,23 +21,31 @@ declare global {
CLIENT_ID_HEROKU: string;
CLIENT_ID_VERCEL: string;
CLIENT_ID_NETLIFY: string;
CLIENT_ID_GITHUB: string;
CLIENT_SECRET_HEROKU: string;
CLIENT_SECRET_VERCEL: string;
CLIENT_SECRET_NETLIFY: string;
CLIENT_SECRET_GITHUB: string;
CLIENT_SLUG_VERCEL: string;
POSTHOG_HOST: string;
POSTHOG_PROJECT_API_KEY: string;
SENTRY_DSN: string;
SITE_URL: string;
SMTP_HOST: string;
SMTP_NAME: string;
SMTP_PASSWORD: string;
SMTP_SECURE: string;
SMTP_PORT: string;
SMTP_USERNAME: string;
STRIPE_PRODUCT_CARD_AUTH: string;
STRIPE_PRODUCT_PRO: string;
SMTP_PASSWORD: string;
SMTP_FROM_ADDRESS: string;
SMTP_FROM_NAME: string;
STRIPE_PRODUCT_STARTER: string;
STRIPE_PRODUCT_TEAM: string;
STRIPE_PRODUCT_PRO: string;
STRIPE_PUBLISHABLE_KEY: string;
STRIPE_SECRET_KEY: string;
STRIPE_WEBHOOK_SECRET: string;
TELEMETRY_ENABLED: string;
LICENSE_KEY: string;
}
}
}

@ -19,6 +19,7 @@
"axios": "^1.1.3",
"bcrypt": "^5.1.0",
"bigint-conversion": "^2.2.2",
"builder-pattern": "^2.2.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"crypto-js": "^4.1.1",
@ -32,6 +33,7 @@
"jsonwebtoken": "^9.0.0",
"jsrp": "^0.2.4",
"libsodium-wrappers": "^0.7.10",
"lodash": "^4.17.21",
"mongoose": "^6.7.2",
"nodemailer": "^6.8.0",
"posthog-node": "^2.2.2",
@ -58,6 +60,7 @@
"@types/express": "^4.17.14",
"@types/jest": "^29.2.4",
"@types/jsonwebtoken": "^8.5.9",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.3",
"@types/nodemailer": "^6.4.6",
"@types/supertest": "^2.0.12",
@ -3221,6 +3224,12 @@
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA=="
},
"node_modules/@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
"integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==",
"dev": true
},
"node_modules/@types/long": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
@ -4085,6 +4094,11 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"node_modules/builder-pattern": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/builder-pattern/-/builder-pattern-2.2.0.tgz",
"integrity": "sha512-cES3qdeBzA4QyJi7rV/l/kAhIFX6AKo3vK66ZPXLNpjcQWCS8sjLKscly8imlfW2YPTo/hquMRMnaWpZ80Kj+g=="
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@ -4434,9 +4448,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/cookiejar": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==",
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
"dev": true
},
"node_modules/core-util-is": {
@ -14641,6 +14655,12 @@
"resolved": "https://registry.npmjs.org/@types/libsodium-wrappers/-/libsodium-wrappers-0.7.10.tgz",
"integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA=="
},
"@types/lodash": {
"version": "4.14.191",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz",
"integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==",
"dev": true
},
"@types/long": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz",
@ -15269,6 +15289,11 @@
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
"dev": true
},
"builder-pattern": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/builder-pattern/-/builder-pattern-2.2.0.tgz",
"integrity": "sha512-cES3qdeBzA4QyJi7rV/l/kAhIFX6AKo3vK66ZPXLNpjcQWCS8sjLKscly8imlfW2YPTo/hquMRMnaWpZ80Kj+g=="
},
"bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
@ -15536,9 +15561,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"cookiejar": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.3.tgz",
"integrity": "sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ==",
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz",
"integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==",
"dev": true
},
"core-util-is": {

@ -36,6 +36,7 @@
"@types/express": "^4.17.14",
"@types/jest": "^29.2.4",
"@types/jsonwebtoken": "^8.5.9",
"@types/lodash": "^4.14.191",
"@types/node": "^18.11.3",
"@types/nodemailer": "^6.4.6",
"@types/supertest": "^2.0.12",
@ -85,6 +86,7 @@
"axios": "^1.1.3",
"bcrypt": "^5.1.0",
"bigint-conversion": "^2.2.2",
"builder-pattern": "^2.2.0",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"crypto-js": "^4.1.1",
@ -98,6 +100,7 @@
"jsonwebtoken": "^9.0.0",
"jsrp": "^0.2.4",
"libsodium-wrappers": "^0.7.10",
"lodash": "^4.17.21",
"mongoose": "^6.7.2",
"nodemailer": "^6.8.0",
"posthog-node": "^2.2.2",

@ -13,11 +13,11 @@ const MONGO_URL = process.env.MONGO_URL!;
const NODE_ENV = process.env.NODE_ENV! || 'production';
const VERBOSE_ERROR_OUTPUT = process.env.VERBOSE_ERROR_OUTPUT! === 'true' && true;
const LOKI_HOST = process.env.LOKI_HOST || undefined;
const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!;
const CLIENT_ID_HEROKU = process.env.CLIENT_ID_HEROKU!;
const CLIENT_ID_VERCEL = process.env.CLIENT_ID_VERCEL!;
const CLIENT_ID_NETLIFY = process.env.CLIENT_ID_NETLIFY!;
const CLIENT_ID_GITHUB = process.env.CLIENT_ID_GITHUB!;
const CLIENT_SECRET_HEROKU = process.env.CLIENT_SECRET_HEROKU!;
const CLIENT_SECRET_VERCEL = process.env.CLIENT_SECRET_VERCEL!;
const CLIENT_SECRET_NETLIFY = process.env.CLIENT_SECRET_NETLIFY!;
const CLIENT_SECRET_GITHUB = process.env.CLIENT_SECRET_GITHUB!;
@ -35,9 +35,9 @@ const SMTP_USERNAME = process.env.SMTP_USERNAME!;
const SMTP_PASSWORD = process.env.SMTP_PASSWORD!;
const SMTP_FROM_ADDRESS = process.env.SMTP_FROM_ADDRESS!;
const SMTP_FROM_NAME = process.env.SMTP_FROM_NAME! || 'Infisical';
const STRIPE_PRODUCT_CARD_AUTH = process.env.STRIPE_PRODUCT_CARD_AUTH!;
const STRIPE_PRODUCT_PRO = process.env.STRIPE_PRODUCT_PRO!;
const STRIPE_PRODUCT_STARTER = process.env.STRIPE_PRODUCT_STARTER!;
const STRIPE_PRODUCT_PRO = process.env.STRIPE_PRODUCT_PRO!;
const STRIPE_PRODUCT_TEAM = process.env.STRIPE_PRODUCT_TEAM!;
const STRIPE_PUBLISHABLE_KEY = process.env.STRIPE_PUBLISHABLE_KEY!;
const STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY!;
const STRIPE_WEBHOOK_SECRET = process.env.STRIPE_WEBHOOK_SECRET!;
@ -80,9 +80,9 @@ export {
SMTP_PASSWORD,
SMTP_FROM_ADDRESS,
SMTP_FROM_NAME,
STRIPE_PRODUCT_CARD_AUTH,
STRIPE_PRODUCT_PRO,
STRIPE_PRODUCT_STARTER,
STRIPE_PRODUCT_TEAM,
STRIPE_PRODUCT_PRO,
STRIPE_PUBLISHABLE_KEY,
STRIPE_SECRET_KEY,
STRIPE_WEBHOOK_SECRET,

@ -12,6 +12,8 @@ import {
JWT_AUTH_SECRET,
JWT_REFRESH_SECRET
} from '../../config';
import LoginSRPDetail from '../../models/LoginSRPDetail';
import { BadRequestError } from '../../utils/errors';
declare module 'jsonwebtoken' {
export interface UserIDJwtPayload extends jwt.JwtPayload {
@ -19,8 +21,6 @@ declare module 'jsonwebtoken' {
}
}
const clientPublicKeys: any = {};
/**
* Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol
* @param req
@ -46,13 +46,15 @@ export const login1 = async (req: Request, res: Response) => {
salt: user.salt,
verifier: user.verifier
},
() => {
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
clientPublicKeys[email] = {
clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
};
await LoginSRPDetail.findOneAndReplace({ email: email }, {
email: email,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt),
}, { upsert: true, returnNewDocument: false })
return res.status(200).send({
serverPublicKey,
@ -85,15 +87,21 @@ export const login2 = async (req: Request, res: Response) => {
if (!user) throw new Error('Failed to find user');
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email })
if (!loginSRPDetailFromDB) {
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: clientPublicKeys[email].serverBInt
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(clientPublicKeys[email].clientPublicKey);
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {

@ -1,6 +1,6 @@
import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import { Membership, MembershipOrg, User, Key } from '../../models';
import { Membership, MembershipOrg, User, Key, IMembership, Workspace } from '../../models';
import {
findMembership,
deleteMembership as deleteMember
@ -230,4 +230,4 @@ export const inviteUserToWorkspace = async (req: Request, res: Response) => {
invitee,
latestKey
});
};
};

@ -2,10 +2,7 @@ import { Request, Response } from 'express';
import * as Sentry from '@sentry/node';
import {
SITE_URL,
STRIPE_SECRET_KEY,
STRIPE_PRODUCT_STARTER,
STRIPE_PRODUCT_PRO,
STRIPE_PRODUCT_CARD_AUTH
STRIPE_SECRET_KEY
} from '../../config';
import Stripe from 'stripe';
@ -23,12 +20,6 @@ import { createOrganization as create } from '../../helpers/organization';
import { addMembershipsOrg } from '../../helpers/membershipOrg';
import { OWNER, ACCEPTED } from '../../variables';
const productToPriceMap = {
starter: STRIPE_PRODUCT_STARTER,
pro: STRIPE_PRODUCT_PRO,
cardAuth: STRIPE_PRODUCT_CARD_AUTH
};
export const getOrganizations = async (req: Request, res: Response) => {
let organizations;
try {
@ -340,7 +331,6 @@ export const createOrganizationPortalSession = async (
if (paymentMethods.data.length < 1) {
// case: no payment method on file
productToPriceMap['cardAuth'];
session = await stripe.checkout.sessions.create({
customer: req.membershipOrg.organization.customerId,
mode: 'setup',

@ -9,8 +9,8 @@ import { checkEmailVerification } from '../../helpers/signup';
import { createToken } from '../../helpers/auth';
import { sendMail } from '../../helpers/nodemailer';
import { JWT_SIGNUP_LIFETIME, JWT_SIGNUP_SECRET, SITE_URL } from '../../config';
const clientPublicKeys: any = {};
import LoginSRPDetail from '../../models/LoginSRPDetail';
import { BadRequestError } from '../../utils/errors';
/**
* Password reset step 1: Send email verification link to email [email]
@ -32,7 +32,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
error: 'Failed to send email verification for password reset'
});
}
const token = crypto.randomBytes(16).toString('hex');
await Token.findOneAndUpdate(
@ -44,7 +44,7 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
},
{ upsert: true, new: true }
);
await sendMail({
template: 'passwordReset.handlebars',
subjectLine: 'Infisical password reset',
@ -55,15 +55,15 @@ export const emailPasswordReset = async (req: Request, res: Response) => {
callback_url: SITE_URL + '/password-reset'
}
});
} catch (err) {
Sentry.setUser(null);
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to send email for account recovery'
});
});
}
return res.status(200).send({
message: `Sent an email for account recovery to ${email}`
});
@ -79,7 +79,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
let user, token;
try {
const { email, code } = req.body;
user = await User.findOne({ email }).select('+publicKey');
if (!user || !user?.publicKey) {
// case: user doesn't exist with email [email] or
@ -93,7 +93,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
email,
code
});
// generate temporary password-reset token
token = createToken({
payload: {
@ -107,7 +107,7 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => {
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed email verification for password reset'
});
});
}
return res.status(200).send({
@ -130,7 +130,7 @@ export const srp1 = async (req: Request, res: Response) => {
const user = await User.findOne({
email: req.user.email
}).select('+salt +verifier');
if (!user) throw new Error('Failed to find user');
const server = new jsrp.server();
@ -139,13 +139,15 @@ export const srp1 = async (req: Request, res: Response) => {
salt: user.salt,
verifier: user.verifier
},
() => {
async () => {
// generate server-side public key
const serverPublicKey = server.getPublicKey();
clientPublicKeys[req.user.email] = {
clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt)
};
await LoginSRPDetail.findOneAndReplace({ email: req.user.email }, {
email: req.user.email,
clientPublicKey: clientPublicKey,
serverBInt: bigintConversion.bigintToBuf(server.bInt),
}, { upsert: true, returnNewDocument: false })
return res.status(200).send({
serverPublicKey,
@ -180,17 +182,21 @@ export const changePassword = async (req: Request, res: Response) => {
if (!user) throw new Error('Failed to find user');
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email })
if (!loginSRPDetailFromDB) {
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: clientPublicKeys[req.user.email].serverBInt
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(
clientPublicKeys[req.user.email].clientPublicKey
);
server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey);
// compare server and client shared keys
if (server.checkClientProof(clientProof)) {
@ -249,16 +255,22 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => {
if (!user) throw new Error('Failed to find user');
const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email })
if (!loginSRPDetailFromDB) {
return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again"))
}
const server = new jsrp.server();
server.init(
{
salt: user.salt,
verifier: user.verifier,
b: clientPublicKeys[req.user.email].serverBInt
b: loginSRPDetailFromDB.serverBInt
},
async () => {
server.setClientPublicKey(
clientPublicKeys[req.user.email].clientPublicKey
loginSRPDetailFromDB.clientPublicKey
);
// compare server and client shared keys
@ -311,16 +323,16 @@ export const getBackupPrivateKey = async (req: Request, res: Response) => {
backupPrivateKey = await BackupPrivateKey.findOne({
user: req.user._id
}).select('+encryptedPrivateKey +iv +tag');
if (!backupPrivateKey) throw new Error('Failed to find backup private key');
} catch (err) {
Sentry.setUser({ email: req.user.email});
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get backup private key'
});
}
return res.status(200).send({
backupPrivateKey
});
@ -348,15 +360,15 @@ export const resetPassword = async (req: Request, res: Response) => {
{
new: true
}
);
);
} catch (err) {
Sentry.setUser({ email: req.user.email});
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
return res.status(400).send({
message: 'Failed to get backup private key'
});
});
}
return res.status(200).send({
message: 'Successfully reset password'
});

@ -6,8 +6,12 @@ import {
Workspace,
Integration,
ServiceTokenData,
Membership,
} from '../../models';
import { SecretVersion } from '../../ee/models';
import { BadRequestError } from '../../utils/errors';
import _ from 'lodash';
import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization';
/**
* Create new workspace environment named [environmentName] under workspace with id
@ -120,6 +124,15 @@ export const renameWorkspaceEnvironment = async (
{ workspace: workspaceId, environment: oldEnvironmentSlug },
{ environment: environmentSlug }
);
await Membership.updateMany(
{
workspace: workspaceId,
"deniedPermissions.environmentSlug": oldEnvironmentSlug
},
{ $set: { "deniedPermissions.$[element].environmentSlug": environmentSlug } },
{ arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] }
)
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
@ -188,6 +201,11 @@ export const deleteWorkspaceEnvironment = async (
workspace: workspaceId,
environment: environmentSlug,
});
await Membership.updateMany(
{ workspace: workspaceId },
{ $pull: { deniedPermissions: { environmentSlug: environmentSlug } } }
)
} catch (err) {
Sentry.setUser({ email: req.user.email });
Sentry.captureException(err);
@ -202,3 +220,42 @@ export const deleteWorkspaceEnvironment = async (
environment: environmentSlug,
});
};
export const getAllAccessibleEnvironmentsOfWorkspace = async (
req: Request,
res: Response
) => {
const { workspaceId } = req.params;
const workspacesUserIsMemberOf = await Membership.findOne({
workspace: workspaceId,
user: req.user
})
if (!workspacesUserIsMemberOf) {
throw BadRequestError()
}
const accessibleEnvironments: any = []
const deniedPermission = workspacesUserIsMemberOf.deniedPermissions
const relatedWorkspace = await Workspace.findById(workspaceId)
if (!relatedWorkspace) {
throw BadRequestError()
}
relatedWorkspace.environments.forEach(environment => {
const isReadBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: ABILITY_READ })
const isWriteBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: ABILITY_WRITE })
if (isReadBlocked) {
return
} else {
accessibleEnvironments.push({
name: environment.name,
slug: environment.slug,
isWriteDenied: isWriteBlocked
})
}
})
res.json({ accessibleEnvironments })
};

@ -1,7 +1,7 @@
import to from 'await-to-js';
import { Types } from 'mongoose';
import { Request, Response } from 'express';
import { ISecret, Secret } from '../../models';
import { ISecret, Membership, Secret, Workspace } from '../../models';
import {
SECRET_PERSONAL,
SECRET_SHARED,
@ -10,13 +10,14 @@ import {
ACTION_UPDATE_SECRETS,
ACTION_DELETE_SECRETS
} from '../../variables';
import { ValidationError } from '../../utils/errors';
import { UnauthorizedRequestError, ValidationError } from '../../utils/errors';
import { EventService } from '../../services';
import { eventPushSecrets } from '../../events';
import { EESecretService, EELogService } from '../../ee/services';
import { postHogClient } from '../../services';
import { BadRequestError } from '../../utils/errors';
import { getChannelFromUserAgent } from '../../utils/posthog';
import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization';
import { userHasWorkspaceAccess } from '../../ee/helpers/checkMembershipPermissions';
/**
* Create secret(s) for workspace with id [workspaceId] and environment [environment]
@ -76,9 +77,15 @@ export const createSecrets = async (req: Request, res: Response) => {
}
}
*/
const channel = getChannelFromUserAgent(req.headers['user-agent'])
const { workspaceId, environment } = req.body;
const hasAccess = await userHasWorkspaceAccess(req.user, workspaceId, environment, ABILITY_WRITE)
if (!hasAccess) {
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
}
let toAdd;
if (Array.isArray(req.body.secrets)) {
// case: create multiple secrets
@ -105,19 +112,21 @@ export const createSecrets = async (req: Request, res: Response) => {
secretValueCiphertext: string;
secretValueIV: string;
secretValueTag: string;
}) => ({
version: 1,
workspace: new Types.ObjectId(workspaceId),
type,
user: type === SECRET_PERSONAL ? req.user : undefined,
environment,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag
}))
}) => {
return ({
version: 1,
workspace: new Types.ObjectId(workspaceId),
type,
user: type === SECRET_PERSONAL ? req.user : undefined,
environment,
secretKeyCiphertext,
secretKeyIV,
secretKeyTag,
secretValueCiphertext,
secretValueIV,
secretValueTag
});
})
);
setTimeout(async () => {
@ -267,6 +276,14 @@ export const getSecrets = async (req: Request, res: Response) => {
userEmail = req.serviceTokenData.user.email;
}
// none service token case as service tokens are already scoped
if (!req.serviceTokenData) {
const hasAccess = await userHasWorkspaceAccess(userId, workspaceId, environment, ABILITY_READ)
if (!hasAccess) {
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
}
}
const [err, secrets] = await to(Secret.find(
{
workspace: workspaceId,
@ -369,7 +386,6 @@ export const updateSecrets = async (req: Request, res: Response) => {
*/
const channel = req.headers?.['user-agent']?.toLowerCase().includes('mozilla') ? 'web' : 'cli';
// TODO: move type
interface PatchSecret {
id: string;

@ -8,6 +8,8 @@ import {
import {
SALT_ROUNDS
} from '../../config';
import { userHasWorkspaceAccess } from '../../ee/helpers/checkMembershipPermissions';
import { ABILITY_READ } from '../../variables/organization';
/**
* Return service token data associated with service token on request
@ -37,6 +39,11 @@ export const createServiceTokenData = async (req: Request, res: Response) => {
expiresIn
} = req.body;
const hasAccess = await userHasWorkspaceAccess(req.user, workspaceId, environment, ABILITY_READ)
if (!hasAccess) {
throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" })
}
const secret = crypto.randomBytes(16).toString('hex');
const secretHash = await bcrypt.hash(secret, SALT_ROUNDS);
@ -100,4 +107,8 @@ export const deleteServiceTokenData = async (req: Request, res: Response) => {
return res.status(200).send({
serviceTokenData
});
}
}
function UnauthorizedRequestError(arg0: { message: string; }) {
throw new Error('Function not implemented.');
}

@ -3,11 +3,13 @@ import * as secretController from './secretController';
import * as secretSnapshotController from './secretSnapshotController';
import * as workspaceController from './workspaceController';
import * as actionController from './actionController';
import * as membershipController from './membershipController';
export {
stripeController,
secretController,
secretSnapshotController,
workspaceController,
actionController
actionController,
membershipController
}

@ -0,0 +1,63 @@
import { Request, Response } from "express";
import { Membership, Workspace } from "../../../models";
import { IMembershipPermission } from "../../../models/membership";
import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors";
import { ABILITY_READ, ABILITY_WRITE, ADMIN, MEMBER } from "../../../variables/organization";
import { Builder } from "builder-pattern"
import _ from "lodash";
export const denyMembershipPermissions = async (req: Request, res: Response) => {
const { membershipId } = req.params;
const { permissions } = req.body;
const sanitizedMembershipPermissions: IMembershipPermission[] = permissions.map((permission: IMembershipPermission) => {
if (!permission.ability || !permission.environmentSlug || ![ABILITY_READ, ABILITY_WRITE].includes(permission.ability)) {
throw BadRequestError({ message: "One or more required fields are missing from the request or have incorrect type" })
}
return Builder<IMembershipPermission>()
.environmentSlug(permission.environmentSlug)
.ability(permission.ability)
.build();
})
const sanitizedMembershipPermissionsUnique = _.uniqWith(sanitizedMembershipPermissions, _.isEqual)
const membershipToModify = await Membership.findById(membershipId)
if (!membershipToModify) {
throw BadRequestError({ message: "Unable to locate resource" })
}
// check if the user making the request is a admin of this project
if (![ADMIN, MEMBER].includes(membershipToModify.role)) {
throw UnauthorizedRequestError()
}
// check if the requested slugs are indeed a part of this related workspace
const relatedWorkspace = await Workspace.findById(membershipToModify.workspace)
if (!relatedWorkspace) {
throw BadRequestError({ message: "Something went wrong when locating the related workspace" })
}
const uniqueEnvironmentSlugs = new Set(_.uniq(_.map(relatedWorkspace.environments, 'slug')));
sanitizedMembershipPermissionsUnique.forEach(permission => {
if (!uniqueEnvironmentSlugs.has(permission.environmentSlug)) {
throw BadRequestError({ message: "Unknown environment slug reference" })
}
})
// update the permissions
const updatedMembershipWithPermissions = await Membership.findByIdAndUpdate(
{ _id: membershipToModify._id },
{ $set: { deniedPermissions: sanitizedMembershipPermissionsUnique } },
{ new: true }
)
if (!updatedMembershipWithPermissions) {
throw BadRequestError({ message: "The resource has been removed before it can be modified" })
}
res.send({
permissionsDenied: updatedMembershipWithPermissions.deniedPermissions
})
}

@ -0,0 +1,18 @@
import _ from "lodash";
import { Membership } from "../../models";
export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, environment: any, action: any) => {
const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId })
if (!membershipForWorkspace) {
return false
}
const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions;
const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: action });
if (isDisallowed) {
return false
}
return true
}

@ -1,5 +1,4 @@
import mongoose from 'mongoose';
import { ISecret, Secret } from '../models';
import { EESecretService } from '../ee/services';
import { getLogger } from '../utils/logger';
@ -16,6 +15,10 @@ const initDatabaseHelper = async ({
}) => {
try {
await mongoose.connect(mongoURL);
// allow empty strings to pass the required validator
mongoose.Schema.Types.String.checkRequired(v => typeof v === 'string');
getLogger("database").info("Database connection established");
await EESecretService.initSecretVersioning();

@ -3,6 +3,7 @@ import Stripe from 'stripe';
import {
STRIPE_SECRET_KEY,
STRIPE_PRODUCT_STARTER,
STRIPE_PRODUCT_TEAM,
STRIPE_PRODUCT_PRO
} from '../config';
const stripe = new Stripe(STRIPE_SECRET_KEY, {
@ -14,6 +15,7 @@ import { Organization, MembershipOrg } from '../models';
const productToPriceMap = {
starter: STRIPE_PRODUCT_STARTER,
team: STRIPE_PRODUCT_TEAM,
pro: STRIPE_PRODUCT_PRO
};
@ -55,7 +57,7 @@ const createOrganization = async ({
} catch (err) {
Sentry.setUser({ email });
Sentry.captureException(err);
throw new Error('Failed to create organization');
throw new Error(`Failed to create organization [err=${err}]`);
}
return organization;

@ -12,14 +12,17 @@ import {
import {
IAction
} from '../ee/models';
import {
SECRET_SHARED,
import {
SECRET_SHARED,
SECRET_PERSONAL,
ACTION_ADD_SECRETS,
ACTION_UPDATE_SECRETS,
ACTION_DELETE_SECRETS,
ACTION_READ_SECRETS
} from '../variables';
import _ from 'lodash';
import { ABILITY_WRITE } from '../variables/organization';
import { BadRequestError, UnauthorizedRequestError } from '../utils/errors';
/**
* Validate that user with id [userId] can modify secrets with ids [secretIds]
@ -34,7 +37,7 @@ const validateSecrets = async ({
}: {
userId: string;
secretIds: string[];
}) =>{
}) => {
let secrets;
try {
secrets = await Secret.find({
@ -42,20 +45,31 @@ const validateSecrets = async ({
$in: secretIds.map((secretId: string) => new Types.ObjectId(secretId))
}
});
const workspaceIdsSet = new Set((await Membership.find({
user: userId
}, 'workspace'))
.map((m) => m.workspace.toString()));
if (secrets.length != secretIds.length) {
throw BadRequestError({ message: 'Unable to validate some secrets' })
}
const userMemberships = await Membership.find({ user: userId })
const userMembershipById = _.keyBy(userMemberships, 'workspace');
const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString()));
// for each secret check if the secret belongs to a workspace the user is a member of
secrets.forEach((secret: ISecret) => {
if (!workspaceIdsSet.has(secret.workspace.toString())) {
throw new Error('Failed to validate secret');
if (workspaceIdsSet.has(secret.workspace.toString())) {
const deniedMembershipPermissions = userMembershipById[secret.workspace.toString()].deniedPermissions;
const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: secret.environment, ability: ABILITY_WRITE });
if (isDisallowed) {
throw UnauthorizedRequestError({ message: 'You do not have the required permissions to perform this action' });
}
} else {
throw BadRequestError({ message: 'You cannot edit secrets of a workspace you are not a member of' });
}
});
} catch (err) {
throw new Error('Failed to validate secrets');
throw BadRequestError({ message: 'Unable to validate secrets' })
}
return secrets;
@ -127,13 +141,13 @@ const v1PushSecrets = async ({
workspaceId,
environment
});
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
, {});
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
, {});
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
({ ...accumulator, [`${s.type}-${s.hashKey}`]: s })
, {});
, {});
// handle deleting secrets
const toDelete = oldSecrets
@ -150,12 +164,12 @@ const v1PushSecrets = async ({
secretIds: toDelete
});
}
const toUpdate = oldSecrets
.filter((s) => {
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment) {
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment) {
// case: filter secrets where value or comment changed
return true;
}
@ -165,7 +179,7 @@ const v1PushSecrets = async ({
return true;
}
}
return false;
});
@ -217,7 +231,7 @@ const v1PushSecrets = async ({
};
});
await Secret.bulkWrite(operations as any);
// (EE) add secret versions for updated secrets
await EESecretService.addSecretVersions({
secretVersions: toUpdate.map(({
@ -245,7 +259,7 @@ const v1PushSecrets = async ({
secretValueTag: newSecret.tagValue,
secretValueHash: newSecret.hashValue
})
})
})
});
// handle adding new secrets
@ -319,7 +333,7 @@ const v1PushSecrets = async ({
}))
});
}
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId
@ -344,7 +358,7 @@ const v1PushSecrets = async ({
* @param {String} obj.channel - channel (web/cli/auto)
* @param {String} obj.ipAddress - ip address of request to push secrets
*/
const v2PushSecrets = async ({
const v2PushSecrets = async ({
userId,
workspaceId,
environment,
@ -362,20 +376,20 @@ const v1PushSecrets = async ({
// TODO: clean up function and fix up types
try {
const actions: IAction[] = [];
// construct useful data structures
const oldSecrets = await getSecrets({
userId,
workspaceId,
environment
});
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) =>
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
, {});
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
, {});
const newSecretsObj: any = secrets.reduce((accumulator, s) =>
({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s })
, {});
, {});
// handle deleting secrets
const toDelete = oldSecrets
@ -391,7 +405,7 @@ const v1PushSecrets = async ({
await EESecretService.markDeletedSecretVersions({
secretIds: toDelete
});
const deleteAction = await EELogService.createActionSecret({
name: ACTION_DELETE_SECRETS,
userId,
@ -401,12 +415,12 @@ const v1PushSecrets = async ({
deleteAction && actions.push(deleteAction);
}
const toUpdate = oldSecrets
.filter((s) => {
if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) {
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash) {
if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash
|| s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash) {
// case: filter secrets where value or comment changed
return true;
}
@ -416,7 +430,7 @@ const v1PushSecrets = async ({
return true;
}
}
return false;
});
@ -469,7 +483,7 @@ const v1PushSecrets = async ({
};
});
await Secret.bulkWrite(operations as any);
// (EE) add secret versions for updated secrets
await EESecretService.addSecretVersions({
secretVersions: toUpdate.map((s) => {
@ -482,7 +496,7 @@ const v1PushSecrets = async ({
environment: s.environment,
isDeleted: false
})
})
})
});
const updateAction = await EELogService.createActionSecret({
@ -507,18 +521,19 @@ const v1PushSecrets = async ({
workspace: workspaceId,
type: toAdd[idx].type,
environment,
...( toAdd[idx].type === 'personal' ? { user: userId } : {})
...(toAdd[idx].type === 'personal' ? { user: userId } : {})
}))
);
// (EE) add secret versions for new secrets
EESecretService.addSecretVersions({
secretVersions: newSecrets.map((secretDocument) => {
secretVersions: newSecrets.map((secretDocument) => {
return {
...secretDocument.toObject(),
secret: secretDocument._id,
isDeleted: false
}})
}
})
});
const addAction = await EELogService.createActionSecret({
@ -529,7 +544,7 @@ const v1PushSecrets = async ({
});
addAction && actions.push(addAction);
}
// (EE) take a secret snapshot
await EESecretService.takeSecretSnapshot({
workspaceId
@ -560,7 +575,7 @@ const v1PushSecrets = async ({
* @param {String} obj.workspaceId - id of workspace to pull from
* @param {String} obj.environment - environment for secrets
*/
const getSecrets = async ({
const getSecrets = async ({
userId,
workspaceId,
environment
@ -570,7 +585,7 @@ const v1PushSecrets = async ({
environment: string;
}): Promise<ISecret[]> => {
let secrets: any; // TODO: FIX any
try {
// get shared workspace secrets
const sharedSecrets = await Secret.find({
@ -622,7 +637,7 @@ const pullSecrets = async ({
ipAddress: string;
}): Promise<ISecret[]> => {
let secrets: any;
try {
secrets = await getSecrets({
userId,

@ -66,7 +66,7 @@ const checkEmailVerification = async ({
email,
token: code
});
if (!token) throw new Error('Failed to find email verification token');
} catch (err) {
Sentry.setUser(null);
@ -116,7 +116,7 @@ const initializeDefaultOrg = async ({
roles: [ADMIN]
});
} catch (err) {
throw new Error('Failed to initialize default organization and workspace');
throw new Error(`Failed to initialize default organization and workspace [err=${err}]`);
}
};

@ -0,0 +1,23 @@
import mongoose, { Schema, model } from 'mongoose';
const LoginSRPDetailSchema = new Schema(
{
clientPublicKey: {
type: String,
required: true
},
email: {
type: String,
required: true,
unique: true
},
serverBInt: { type: mongoose.Schema.Types.Buffer },
expireAt: { type: Date }
}
);
const LoginSRPDetail = model('LoginSRPDetail', LoginSRPDetailSchema);
// LoginSRPDetailSchema.index({ "expireAt": 1 }, { expireAfterSeconds: 0 });
export default LoginSRPDetail;

@ -1,15 +1,21 @@
import { Schema, model, Types } from 'mongoose';
import { ADMIN, MEMBER } from '../variables';
export interface IMembershipPermission {
environmentSlug: string,
ability: string
}
export interface IMembership {
_id: Types.ObjectId;
user: Types.ObjectId;
inviteEmail?: string;
workspace: Types.ObjectId;
role: 'admin' | 'member';
deniedPermissions: IMembershipPermission[]
}
const membershipSchema = new Schema(
const membershipSchema = new Schema<IMembership>(
{
user: {
type: Schema.Types.ObjectId,
@ -23,6 +29,18 @@ const membershipSchema = new Schema(
ref: 'Workspace',
required: true
},
deniedPermissions: {
type: [
{
environmentSlug: String,
ability: {
type: String,
enum: ['read', 'write']
},
},
],
default: []
},
role: {
type: String,
enum: [ADMIN, MEMBER],

@ -3,14 +3,15 @@ const router = express.Router();
import { body, param } from 'express-validator';
import { requireAuth, validateRequest } from '../../middleware';
import { membershipController } from '../../controllers/v1';
import { membershipController as EEMembershipControllers } from '../../ee/controllers/v1';
// note: ALL DEPRECIATED (moved to api/v2/workspace/:workspaceId/memberships/:membershipId)
router.get( // used for old CLI (deprecate)
'/:workspaceId/connect',
requireAuth({
acceptedAuthModes: ['jwt']
}),
acceptedAuthModes: ['jwt']
}),
param('workspaceId').exists().trim(),
validateRequest,
membershipController.validateMembership
@ -19,8 +20,8 @@ router.get( // used for old CLI (deprecate)
router.delete(
'/:membershipId',
requireAuth({
acceptedAuthModes: ['jwt']
}),
acceptedAuthModes: ['jwt']
}),
param('membershipId').exists().trim(),
validateRequest,
membershipController.deleteMembership
@ -29,11 +30,22 @@ router.delete(
router.post(
'/:membershipId/change-role',
requireAuth({
acceptedAuthModes: ['jwt']
}),
acceptedAuthModes: ['jwt']
}),
body('role').exists().trim(),
validateRequest,
membershipController.changeMembershipRole
);
router.post(
'/:membershipId/deny-permissions',
requireAuth({
acceptedAuthModes: ['jwt']
}),
param('membershipId').isMongoId().exists().trim(),
body('permissions').isArray().exists(),
validateRequest,
EEMembershipControllers.denyMembershipPermissions
);
export default router;

@ -54,4 +54,17 @@ router.delete(
environmentController.deleteWorkspaceEnvironment
);
router.get(
'/:workspaceId/environments',
requireAuth({
acceptedAuthModes: ['jwt'],
}),
requireWorkspaceAuth({
acceptedRoles: [MEMBER, ADMIN],
}),
param('workspaceId').exists().trim(),
validateRequest,
environmentController.getAllAccessibleEnvironmentsOfWorkspace
);
export default router;

@ -32,7 +32,7 @@ router.post(
!secret.secretKeyCiphertext ||
!secret.secretKeyIV ||
!secret.secretKeyTag ||
!secret.secretValueCiphertext ||
(typeof secret.secretValueCiphertext !== 'string') ||
!secret.secretValueIV ||
!secret.secretValueTag
) {

@ -90,7 +90,7 @@ const INTEGRATION_OPTIONS = [
name: 'Fly.io',
slug: 'flyio',
image: 'Flyio.svg',
isAvailable: false,
isAvailable: true,
type: 'pat',
clientId: '',
docsLink: ''

@ -6,6 +6,10 @@ const MEMBER = 'member';
// membership statuses
const INVITED = 'invited';
// membership permissions ability
const ABILITY_READ = 'read';
const ABILITY_WRITE = 'write';
// -- organization
const ACCEPTED = 'accepted';
@ -14,5 +18,7 @@ export {
ADMIN,
MEMBER,
INVITED,
ACCEPTED
ACCEPTED,
ABILITY_READ,
ABILITY_WRITE
}

@ -5,6 +5,7 @@ import (
"github.com/Infisical/infisical-merge/packages/config"
"github.com/go-resty/resty/v2"
log "github.com/sirupsen/logrus"
)
const USER_AGENT = "cli"
@ -144,3 +145,24 @@ func CallGetAllWorkSpacesUserBelongsTo(httpClient *resty.Client) (GetWorkSpacesR
return workSpacesResponse, nil
}
func CallIsAuthenticated(httpClient *resty.Client) bool {
var workSpacesResponse GetWorkSpacesResponse
response, err := httpClient.
R().
SetResult(&workSpacesResponse).
SetHeader("User-Agent", USER_AGENT).
Post(fmt.Sprintf("%v/v1/auth/checkAuth", config.INFISICAL_URL))
log.Debugln(fmt.Errorf("CallIsAuthenticated: Unsuccessful response: [response=%v]", response))
if err != nil {
return false
}
if response.IsError() {
return false
}
return true
}

@ -33,13 +33,13 @@ var loginCmd = &cobra.Command{
PreRun: toggleDebug,
Run: func(cmd *cobra.Command, args []string) {
currentLoggedInUserDetails, err := util.GetCurrentLoggedInUserDetails()
if err != nil && strings.Contains(err.Error(), "The specified item could not be found in the keyring") { // if the key can't be found allow them to override
if err != nil && (strings.Contains(err.Error(), "The specified item could not be found in the keyring") || strings.Contains(err.Error(), "unable to get key from Keyring")) { // if the key can't be found allow them to override
log.Debug(err)
} else if err != nil {
util.HandleError(err)
}
if currentLoggedInUserDetails.IsUserLoggedIn {
if currentLoggedInUserDetails.IsUserLoggedIn && !currentLoggedInUserDetails.LoginExpired { // if you are logged in but not expired
shouldOverride, err := shouldOverrideLoginPrompt(currentLoggedInUserDetails.UserCredentials.Email)
if err != nil {
util.HandleError(err)

@ -58,9 +58,9 @@ var runCmd = &cobra.Command{
util.HandleError(err, "Unable to parse flag")
}
if !util.IsSecretEnvironmentValid(envName) {
util.PrintMessageAndExit("Invalid environment name passed. Environment names can only be prod, dev, test or staging")
}
// if !util.IsSecretEnvironmentValid(envName) {
// util.PrintMessageAndExit("Invalid environment name passed. Environment names can only be prod, dev, test or staging")
// }
secretOverriding, err := cmd.Flags().GetBool("secret-overriding")
if err != nil {
@ -166,7 +166,10 @@ func executeMultipleCommandWithEnvs(fullCommand string, secretsCount int, env []
if runtime.GOOS == "windows" {
shell = [2]string{"cmd", "/C"}
} else {
shell[0] = os.Getenv("SHELL")
currentShell := os.Getenv("SHELL")
if currentShell != "" {
shell[0] = currentShell
}
}
cmd := exec.Command(shell[0], shell[1], fullCommand)

@ -5,10 +5,11 @@ import (
"fmt"
"io/ioutil"
"net/http"
"errors"
)
func CheckForUpdate() {
latestVersion, err := getLatestTag("infisical", "infisical")
latestVersion, err := getLatestTag("Infisical", "infisical")
if err != nil {
// do nothing and continue
return
@ -24,6 +25,9 @@ func getLatestTag(repoOwner string, repoName string) (string, error) {
if err != nil {
return "", err
}
if resp.StatusCode != 200 {
return "", errors.New(fmt.Sprintf("GitHub API returned status code %d", resp.StatusCode))
}
defer resp.Body.Close()

@ -11,5 +11,8 @@ const (
KEYRING_SERVICE_NAME = "infisical"
PERSONAL_SECRET_TYPE_NAME = "personal"
SHARED_SECRET_TYPE_NAME = "shared"
CLI_VERSION = "v0.2.6"
)
var (
CLI_VERSION = "devel"
)

@ -5,7 +5,7 @@ import (
"fmt"
"github.com/99designs/keyring"
"github.com/Infisical/infisical-merge/packages/config"
"github.com/Infisical/infisical-merge/packages/api"
"github.com/Infisical/infisical-merge/packages/models"
"github.com/go-resty/resty/v2"
)
@ -87,17 +87,10 @@ func GetCurrentLoggedInUserDetails() (LoggedInUserDetails, error) {
SetAuthToken(userCreds.JTWToken).
SetHeader("Accept", "application/json")
response, err := httpClient.
R().
Post(fmt.Sprintf("%v/v1/auth/checkAuth", config.INFISICAL_URL))
if err != nil {
return LoggedInUserDetails{}, err
}
if response.StatusCode() > 299 {
isAuthenticated := api.CallIsAuthenticated(httpClient)
if !isAuthenticated {
return LoggedInUserDetails{
IsUserLoggedIn: true,
IsUserLoggedIn: true, // was logged in
LoginExpired: true,
UserCredentials: userCreds,
}, nil

@ -46,11 +46,7 @@ services:
context: ./frontend
dockerfile: Dockerfile.dev
volumes:
- ./frontend/src/pages:/app/src/pages
- ./frontend/src/components:/app/src/components
- ./frontend/src/ee:/app/src/ee
- ./frontend/src/locales:/app/src/locales
- ./frontend/src/styles:/app/src/styles
- ./frontend/src:/app/src/ # mounted whole src to avoid missing reload on new files
- ./frontend/public:/app/public
- ./frontend/next-i18next.config.js:/app/next-i18next.config.js
env_file: .env
@ -58,6 +54,7 @@ services:
- NEXT_PUBLIC_ENV=development
- INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
- NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_TEAM=${STRIPE_PRODUCT_TEAM}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
networks:
- infisical-dev

@ -40,6 +40,7 @@ services:
# - NEXT_PUBLIC_POSTHOG_API_KEY=${POSTHOG_PROJECT_API_KEY}
- INFISICAL_TELEMETRY_ENABLED=${TELEMETRY_ENABLED}
- NEXT_PUBLIC_STRIPE_PRODUCT_PRO=${STRIPE_PRODUCT_PRO}
- NEXT_PUBLIC_STRIPE_PRODUCT_TEAM=${STRIPE_PRODUCT_TEAM}
- NEXT_PUBLIC_STRIPE_PRODUCT_STARTER=${STRIPE_PRODUCT_STARTER}
networks:
- infisical

@ -1,5 +1,6 @@
---
title: "Commands"
description: "Infisical CLI command overview"
---
## Commands

@ -1,5 +1,6 @@
---
title: "infisical export"
description: "Export Infisical secrets from CLI into different file formats"
---
```bash

@ -1,5 +1,6 @@
---
title: "infisical init"
description: "Switch between Infisical projects within CLI"
---
```bash

@ -1,5 +1,6 @@
---
title: "infisical login"
description: "Login into Infisical from the CLI"
---
```bash

@ -1,5 +1,6 @@
---
title: "infisical run"
description: "The command that injects your secrets into local environment"
---
<Tabs>

@ -1,5 +1,6 @@
---
title: "infisical secrets"
description: "Perform CRUD operations with Infisical secrets"
---
```

@ -1,5 +1,6 @@
---
title: "infisical vault"
description: "Change the vault type in Infisical"
---
<Tabs>

@ -1,5 +1,6 @@
---
title: "FAQ"
description: "Frequently Asked Questions about Infisical"
---
Frequently asked questions about the CLI can be found on this page.

@ -1,5 +1,6 @@
---
title: 'Install'
description: "Infisical's CLI is one of the best way to manage environments and secrets. Install it here"
---
Prerequisite: Set up an account with [Infisical Cloud](https://app.infisical.com) or via a [self-hosted installation](/self-hosting/overview).

@ -1,5 +1,6 @@
---
title: "Infisical Token"
description: "How to use Infical service token within the CLI."
---
Prerequisite: [Infisical Token and How to Generate One](../../getting-started/dashboard/token).

@ -1,5 +1,6 @@
---
title: "Usage"
description: "How to manage you secrets with Infisical's CLI?"
---
Prerequisite: [Install the CLI](/cli/overview)

@ -1,6 +1,6 @@
---
title: "Code of Conduct"
description: ""
description: "What you should know before contributing to Infisical?"
---
## Our Pledge

@ -1,5 +1,6 @@
---
title: "Activity Logs"
description: "See which events are triggered within your Infisical project."
---
Activity logs record all actions going through Infisical including who performed which CRUD operations on environment variables and from what IP address. They help answer questions like:

@ -1,5 +1,6 @@
---
title: "Sign up"
description: "How to create an account in Infisical?"
---
## Self-hosted

@ -1,10 +1,11 @@
---
title: "Integrations"
description: "How to sync your secrets among various 3rd-party services with Infisical."
---
Integrations allow environment variables to be synced across your entire infrastructure from local development to CI/CD and production.
We're still early with integrations, but expect more soon.
We're still relatively early with integrations. 6+ integrations are already avaiable but expect more coming very soon.
<Card title="View integrations" icon="link" href="/integrations/overview">
View all available integrations and their guides

@ -1,5 +1,6 @@
---
title: "Organization"
description: "How Infisical structures its organizations."
---
An organization houses projects and members.

@ -1,5 +1,6 @@
---
title: "Point-in-Time Recovery"
description: "How to rollback secrets and configs to any commit with Infisical."
---
Point-in-time recovery allows environment variables to be rolled back to any point in time. It's powered by snapshots that get captured after mutations to environment variables.

@ -1,5 +1,6 @@
---
title: "Project"
description: "How Infisical organizes secrets into projects."
---
A project houses environment variables for an application.

@ -1,5 +1,6 @@
---
title: "Secret Versioning"
description: "Version secrets and configurations with Infisical"
---
Secret versioning records changes made to every secret.

@ -1,5 +1,6 @@
---
title: "Infisical Token"
description: "Use Infisical service token as one of the authentication methods."
---
An Infisical Token is needed to authenticate the CLI when there isn't an easy way to input your login credentials.

@ -1,5 +1,6 @@
---
title: "Features"
description: "A list of features that Infisical has to offer."
---
This is a non-exhaustive list of features that Infisical offers:
@ -30,9 +31,9 @@ We're building the future of secret management, one that's comprehensive and acc
| More hosting options | Ongoing |
| 1-Click Deploys | Ongoing |
| Account recovery: Backup key | Ongoing |
| Access logs | Ongoing |
| Account recovery: Member-assisted | Coming soon |
| Slack & MS teams integrations | Coming soon |
| Access logs | Coming soon |
| Version control for secrets | Coming soon |
| 2FA | Coming soon |
| Restricted IPs | Coming soon |

@ -1,5 +1,6 @@
---
title: "Introduction"
description: "What is Infisical?"
---
Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret manager that enables teams to easily manage and sync their environment variables.
@ -35,3 +36,8 @@ Start syncing environment variables with [Infisical Cloud](https://app.infisical
Explore integrations for Docker, AWS, Heroku, etc.
</Card>
</CardGroup>
<Card title="Set up a 1x1 with an Infisical Engineer" iconType="duotone" color="#ca8b04" href="https://calendly.com/maidull/30min">
Our team is happy to help you get started with Infisical. If you have any questions or want to learn how you can leverage Infisical within your infrastructure, **[set up a 1-on-1 with an Infisical engineer](https://cal.com/maidul/15min)**.
</Card>

@ -1,5 +1,6 @@
---
title: "Quickstart"
description: "Start managing your developer secrets and configs with Infisical in 10 minutes."
---
This example demonstrates how to store and inject environment variables from [Infisical Cloud](https://app.infisical.com) into your application.

@ -1,5 +1,6 @@
---
title: "GitHub Actions"
description: "How to automatically sync secrets from Infisical into your GitHub Actions."
---
<Warning>

@ -1,5 +1,6 @@
---
title: "Fly.io"
description: "How to automatically sync secrets from Infisical into your Fly.io project."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Heroku"
description: "How to automatically sync secrets from Infisical into your Heroku project."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Netlify"
description: "How to automatically sync secrets from Infisical into your Netlify project."
---
<Warning>

@ -1,5 +1,6 @@
---
title: "Render"
description: "How to automatically sync secrets from Infisical into your Render project."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Vercel"
description: "How to automatically sync secrets from Infisical into your Vercel project."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Django"
description: "How to use Infisical to inject environment variables and secrets into a Django app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: ".NET"
description: "How to use Infisical to inject environment variables and secrets into a .NET app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Express, Fastify, Koa"
description: "How to use Infisical to inject environment variables and secrets into an Express app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Fiber"
description: "How to use Infisical to inject environment variables and secrets into a Fiber app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Flask"
description: "How to use Infisical to inject environment variables and secrets into a Flask app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Gatsby"
description: "How to use Infisical to inject environment variables and secrets into a Gatsby app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Laravel"
description: "How to use Infisical to inject environment variables and secrets into a Laravel app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "NestJS"
description: "How to use Infisical to inject environment variables and secrets into a NestJS app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Next.js"
description: "How to use Infisical to inject environment variables and secrets into a Next.js app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Nuxt"
description: "How to use Infisical to inject environment variables and secrets into a Nuxt app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Ruby on Rails"
description: "How to use Infisical to inject environment variables and secrets into a Ruby on Rails app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "React"
description: "How to use Infisical to inject environment variables and secrets into a React app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Remix"
description: "How to use Infisical to inject environment variables and secrets into a Remix app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Vite"
description: "How to use Infisical to inject environment variables and secrets into a Vite app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Vue"
description: "How to use Infisical to inject environment variables and secrets into a Vue.js app."
---
Prerequisites:

@ -1,5 +1,6 @@
---
title: "Overview"
description: "How to use Infisical to inject secrets and configs into various 3-rd party services and frameworks."
---
Integrations allow environment variables to be synced from Infisical into your local development workflow, CI/CD pipelines, and production infrastructure.

@ -1,5 +1,6 @@
---
title: "Docker Compose"
description: "How to use Infisical to inject environment variables into container defined in your Docker Compose file."
---
The Docker Compose integration enables you to inject environment variables from Infisical into the containers defined in your compose file.

@ -1,5 +1,6 @@
---
title: "Docker"
description: "How to use Infisical to inject environment variables into a Docker container."
---
Infisical can be used in a Dockerfile to inject environment variables into a Docker container.
@ -43,7 +44,7 @@ Infisical can be used in a Dockerfile to inject environment variables into a Doc
CMD ["infisical", "run", "---", "npm run start"]
# example with multiple commands
CMD ["infisical", "run", "--command" "npm run start && ..."]
CMD ["infisical", "run", "--command", "npm run start && ..."]
```
View more options for the `run` command [here](../../cli/commands/run)

@ -1,5 +1,6 @@
---
title: 'Kubernetes'
description: "This page explains how to use Infisical to inject secrets into Kubernetes clusters."
---
The Infisical Secrets Operator is a custom Kubernetes controller that helps keep secrets in a cluster up to date by synchronizing them.

@ -1,5 +1,6 @@
---
title: "Data Model"
description: "Infisical's current Data Structure."
---
Infisical stores a range of data namely user, secrets, keys, organization, project, and membership data.

@ -1,5 +1,6 @@
---
title: "Mechanics"
description: "Quick explanation of how Infisical works."
---
## Signup

@ -1,12 +1,13 @@
---
title: "Overview"
description: "Infisical's security statement."
---
## Summary
Infisical uses end-to-end encryption (E2EE) whenever possible to securely store and share secrets. It uses secure remote password (SRP) to handle authentication and public-key cryptography for secret sharing and syncing; secrets are symmetrically encrypted at rest by keys decryptable only by members of the project.
Infisical uses AES256-GCM for symmetric encryption and x2519-xsalsa20-poly1305 for asymmetric encryption operations mentioned in this brief; key generation and asymmetric algorithms are implemented with the [TweetNaCl.js](https://tweetnacl.js.org/#/) library which has been well-audited and recommended for use by cybersecurity firm Cure53. Lastly, the secure remote password (SRP) implementation uses [jsrp](https://github.com/alax/jsrp) package for user authentication. As part of our commitment to user privacy and security, we aim to conduct formal security and compliance audits in the following year.
Infisical uses AES256-GCM for symmetric encryption and x25519-xsalsa20-poly1305 for asymmetric encryption operations mentioned in this brief; key generation and asymmetric algorithms are implemented with the [TweetNaCl.js](https://tweetnacl.js.org/#/) library which has been well-audited and recommended for use by cybersecurity firm Cure53. Lastly, the secure remote password (SRP) implementation uses [jsrp](https://github.com/alax/jsrp) package for user authentication. As part of our commitment to user privacy and security, we aim to conduct formal security and compliance audits in the following year.
## Scope

@ -1,6 +1,6 @@
---
title: "Email"
description: ""
description: "How to configure your email when self-hosting Infisical."
---
Infisical requires you to configure your own SMTP server for certain functionality like:

@ -1,6 +1,6 @@
---
title: "Environment Variables"
description: ""
description: "How to configure your environment variables when self-hosting Infisical."
---
Configuring Infisical requires setting some environment variables. There is a file called [`.env.example`](https://github.com/Infisical/infisical/blob/main/.env.example) at the root directory of our main repo that you can use to create a `.env` file before you start the server.

@ -1,6 +1,6 @@
---
title: "Kubernetes"
description: "Deploy with Kubernetes"
description: "How to deploy Infisical with Kubernetes"
---
<Info>
@ -26,32 +26,63 @@ Refer to the available [environment variables](../../self-hosting/configuration/
<Accordion title="values.yaml">
```yaml
#####
# INFISICAL K8 DEFAULT VALUES FIL
# INFISICAL K8 DEFAULT VALUES FILE
# PLEASE REPLACE VALUES/EDIT AS REQUIRED
#####
frontend:
replicaCount: 1
image:
repository:
pullPolicy: IfNotPresent
tag: "latest"
# kubeSecretRef: some-kube-secret-name
nameOverride: ""
frontend:
name: frontend
podAnnotations: {}
deploymentAnnotations: {}
replicaCount: 2
image:
repository: infisical/frontend
pullPolicy: Always
tag: "latest" # It it highly recommended to select a specific tag for prod deployment so it is easy to rollback: https://hub.docker.com/r/infisical/frontend/tags
# kubeSecretRef: some-kube-secret-name
service:
# type of the frontend service
type: ClusterIP
# define the nodePort if service type is NodePort
# nodePort:
annotations: {}
backend:
replicaCount: 1
name: backend
podAnnotations: {}
deploymentAnnotations: {}
replicaCount: 2
image:
repository:
pullPolicy: IfNotPresent
tag: "latest"
repository: infisical/backend
pullPolicy: Always
tag: "latest" # It it highly recommended to select a specific tag for prod deployment so it is easy to rollback: https://hub.docker.com/r/infisical/backend/tags
# kubeSecretRef: some-kube-secret-name
service:
annotations: {}
mongodb:
name: mongodb
podAnnotations: {}
image:
repository: mongo
pullPolicy: IfNotPresent
tag: "latest"
service:
annotations: {}
# By default the backend will be connected to a Mongo instance in the cluster.
# However, it is recommended to add a managed document DB connection string because the DB instance in the cluster does not have persistence yet ( data will be deleted on next deploy).
# Learn about connection string type here https://www.mongodb.com/docs/manual/reference/connection-string/
mongodbConnection: {}
# externalMongoDBConnectionString: <>
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: "nginx"
hostName: example.com
hostName: example.com # replace with your domain
frontend:
path: /
pathType: Prefix
@ -60,6 +91,7 @@ ingress:
pathType: Prefix
tls: []
## Complete Ingress example
# ingress:
# enabled: true
@ -93,15 +125,13 @@ backendEnvironmentVariables:
# Mail/SMTP
# Required to send emails
SMTP_HOST: MUST_REPLACE
SMTP_HOST: MUST_REPLACE
SMTP_NAME: MUST_REPLACE
SMTP_USERNAME: MUST_REPLACE
SMTP_PASSWORD: MUST_REPLACE
# Recommended to replace with Mongo Cloud URI as the DB instance in the cluster does not have persistence yet
MONGO_URL: mongodb://root:root@mongodb-service:27017/
frontendEnvironmentVariables: {}
```
</Accordion>

@ -1,6 +1,6 @@
---
title: "Linux VM"
description: "Deploy with Docker-Compose"
description: "How to deploy Infisical with Docker-Compose"
---
<Info>

@ -1,5 +1,6 @@
---
title: "Overview"
description: "Infisical is an open-source end-to-end encrypted secrets manager that developers can set up within 15 minutes."
---
<Info>

@ -2317,6 +2317,9 @@ components:
Project:
type: object
properties:
_id:
type: string
example: ''
name:
type: string
example: My Project

@ -28,6 +28,7 @@
"@reduxjs/toolkit": "^1.8.3",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.46.0",
"@tanstack/react-query": "^4.23.0",
"add": "^2.0.6",
"axios": "^0.27.2",
"axios-auth-refresh": "^3.3.3",
@ -96,6 +97,7 @@
"eslint-plugin-storybook": "^0.6.10",
"postcss": "^8.4.14",
"prettier": "^2.8.3",
"prettier-plugin-tailwindcss": "^0.2.2",
"storybook": "^7.0.0-beta.30",
"storybook-dark-mode": "^2.0.5",
"tailwindcss": "3.2",
@ -106,6 +108,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
@ -118,6 +121,7 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
@ -153,6 +157,7 @@
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
@ -161,6 +166,7 @@
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
@ -190,6 +196,7 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"dependencies": {
"ms": "2.1.2"
},
@ -205,12 +212,14 @@
"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=="
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": 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==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
@ -256,6 +265,7 @@
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
"integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.20.5",
"@babel/helper-validator-option": "^7.18.6",
@ -274,6 +284,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"dependencies": {
"yallist": "^3.0.2"
}
@ -282,6 +293,7 @@
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
@ -289,7 +301,8 @@
"node_modules/@babel/helper-compilation-targets/node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.20.12",
@ -448,6 +461,7 @@
"version": "7.20.11",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
"integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
@ -521,6 +535,7 @@
"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==",
"dev": true,
"dependencies": {
"@babel/types": "^7.20.2"
},
@ -571,6 +586,7 @@
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
@ -594,6 +610,7 @@
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz",
"integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==",
"dev": true,
"dependencies": {
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
@ -6630,6 +6647,41 @@
"tailwindcss": ">=3.0.0 || insiders"
}
},
"node_modules/@tanstack/query-core": {
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.22.4.tgz",
"integrity": "sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
}
},
"node_modules/@tanstack/react-query": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.23.0.tgz",
"integrity": "sha512-cfQsrecZQjYYueiow4WcK8ItokXJnv+b2OrK8Lf5kF7lM9uCo1ilyygFB8wo4MfxchUBVM6Cs8wq4Ed7fouwkA==",
"dependencies": {
"@tanstack/query-core": "4.22.4",
"use-sync-external-store": "^1.2.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0",
"react-native": "*"
},
"peerDependenciesMeta": {
"react-dom": {
"optional": true
},
"react-native": {
"optional": true
}
}
},
"node_modules/@testing-library/dom": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz",
@ -8945,6 +8997,7 @@
"version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -10627,7 +10680,8 @@
"node_modules/electron-to-chromium": {
"version": "1.4.284",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
"dev": true
},
"node_modules/emoji-regex": {
"version": "9.2.2",
@ -10923,6 +10977,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true,
"engines": {
"node": ">=6"
}
@ -12763,6 +12818,7 @@
"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==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
@ -14935,6 +14991,7 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
"bin": {
"json5": "lib/cli.js"
},
@ -16407,7 +16464,8 @@
"node_modules/node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
},
"node_modules/normalize-package-data": {
"version": "2.5.0",
@ -17391,6 +17449,76 @@
"node": ">=6.0.0"
}
},
"node_modules/prettier-plugin-tailwindcss": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz",
"integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==",
"dev": true,
"engines": {
"node": ">=12.17.0"
},
"peerDependencies": {
"@prettier/plugin-php": "*",
"@prettier/plugin-pug": "*",
"@shopify/prettier-plugin-liquid": "*",
"@shufo/prettier-plugin-blade": "*",
"@trivago/prettier-plugin-sort-imports": "*",
"prettier": ">=2.2.0",
"prettier-plugin-astro": "*",
"prettier-plugin-css-order": "*",
"prettier-plugin-import-sort": "*",
"prettier-plugin-jsdoc": "*",
"prettier-plugin-organize-attributes": "*",
"prettier-plugin-organize-imports": "*",
"prettier-plugin-style-order": "*",
"prettier-plugin-svelte": "*",
"prettier-plugin-twig-melody": "*"
},
"peerDependenciesMeta": {
"@prettier/plugin-php": {
"optional": true
},
"@prettier/plugin-pug": {
"optional": true
},
"@shopify/prettier-plugin-liquid": {
"optional": true
},
"@shufo/prettier-plugin-blade": {
"optional": true
},
"@trivago/prettier-plugin-sort-imports": {
"optional": true
},
"prettier-plugin-astro": {
"optional": true
},
"prettier-plugin-css-order": {
"optional": true
},
"prettier-plugin-import-sort": {
"optional": true
},
"prettier-plugin-jsdoc": {
"optional": true
},
"prettier-plugin-organize-attributes": {
"optional": true
},
"prettier-plugin-organize-imports": {
"optional": true
},
"prettier-plugin-style-order": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"prettier-plugin-twig-melody": {
"optional": true
}
}
},
"node_modules/pretty-error": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
@ -21276,7 +21404,7 @@
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
"devOptional": true,
"dev": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -21602,6 +21730,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
"dev": true,
"funding": [
{
"type": "opencollective",
@ -22358,6 +22487,7 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
"integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==",
"dev": true,
"requires": {
"@jridgewell/gen-mapping": "^0.1.0",
"@jridgewell/trace-mapping": "^0.3.9"
@ -22367,6 +22497,7 @@
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
"integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==",
"dev": true,
"requires": {
"@jridgewell/set-array": "^1.0.0",
"@jridgewell/sourcemap-codec": "^1.4.10"
@ -22394,12 +22525,14 @@
"@babel/compat-data": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz",
"integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g=="
"integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==",
"dev": true
},
"@babel/core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz",
"integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==",
"dev": true,
"requires": {
"@ampproject/remapping": "^2.1.0",
"@babel/code-frame": "^7.18.6",
@ -22422,6 +22555,7 @@
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
"dev": true,
"requires": {
"ms": "2.1.2"
}
@ -22429,12 +22563,14 @@
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
}
}
},
@ -22470,6 +22606,7 @@
"version": "7.20.7",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz",
"integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==",
"dev": true,
"requires": {
"@babel/compat-data": "^7.20.5",
"@babel/helper-validator-option": "^7.18.6",
@ -22482,6 +22619,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"requires": {
"yallist": "^3.0.2"
}
@ -22489,12 +22627,14 @@
"semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true
},
"yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true
}
}
},
@ -22613,6 +22753,7 @@
"version": "7.20.11",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz",
"integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==",
"dev": true,
"requires": {
"@babel/helper-environment-visitor": "^7.18.9",
"@babel/helper-module-imports": "^7.18.6",
@ -22668,6 +22809,7 @@
"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==",
"dev": true,
"requires": {
"@babel/types": "^7.20.2"
}
@ -22702,7 +22844,8 @@
"@babel/helper-validator-option": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz",
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw=="
"integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==",
"dev": true
},
"@babel/helper-wrap-function": {
"version": "7.20.5",
@ -22720,6 +22863,7 @@
"version": "7.20.6",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz",
"integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==",
"dev": true,
"requires": {
"@babel/template": "^7.18.10",
"@babel/traverse": "^7.20.5",
@ -23917,8 +24061,7 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz",
"integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==",
"dev": true,
"requires": {}
"dev": true
},
"@emotion/utils": {
"version": "1.2.0",
@ -24223,8 +24366,7 @@
"@headlessui/react": {
"version": "1.6.6",
"resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.6.6.tgz",
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q==",
"requires": {}
"integrity": "sha512-MFJtmj9Xh/hhBMhLccGbBoSk+sk61BlP6sJe4uQcVMtXZhCgGqd2GyIQzzmsdPdTEWGSF434CBi8mnhR6um46Q=="
},
"@humanwhocodes/config-array": {
"version": "0.11.8",
@ -26887,6 +27029,20 @@
"postcss-selector-parser": "6.0.10"
}
},
"@tanstack/query-core": {
"version": "4.22.4",
"resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.22.4.tgz",
"integrity": "sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw=="
},
"@tanstack/react-query": {
"version": "4.23.0",
"resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.23.0.tgz",
"integrity": "sha512-cfQsrecZQjYYueiow4WcK8ItokXJnv+b2OrK8Lf5kF7lM9uCo1ilyygFB8wo4MfxchUBVM6Cs8wq4Ed7fouwkA==",
"requires": {
"@tanstack/query-core": "4.22.4",
"use-sync-external-store": "^1.2.0"
}
},
"@testing-library/dom": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.20.0.tgz",
@ -27860,8 +28016,7 @@
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
"requires": {}
"dev": true
},
"acorn-node": {
"version": "1.8.2",
@ -27995,8 +28150,7 @@
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true,
"requires": {}
"dev": true
},
"ansi-align": {
"version": "3.0.1",
@ -28290,8 +28444,7 @@
"axios-auth-refresh": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/axios-auth-refresh/-/axios-auth-refresh-3.3.3.tgz",
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg==",
"requires": {}
"integrity": "sha512-2IbDhJ/h6ddNBBnnzn1VFK/qx17pE9aVqiafB8rx5LVHsJ1HtFpUGkbXY7PzTG+8P9HJWcyA3fNZl9BikSuilg=="
},
"axobject-query": {
"version": "3.1.1",
@ -28306,8 +28459,7 @@
"version": "7.0.0-bridge.0",
"resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz",
"integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==",
"dev": true,
"requires": {}
"dev": true
},
"babel-loader": {
"version": "9.1.2",
@ -28686,6 +28838,7 @@
"version": "4.21.4",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz",
"integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==",
"dev": true,
"requires": {
"caniuse-lite": "^1.0.30001400",
"electron-to-chromium": "^1.4.251",
@ -29515,8 +29668,7 @@
"cva": {
"version": "npm:class-variance-authority@0.4.0",
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.4.0.tgz",
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ==",
"requires": {}
"integrity": "sha512-74enNN8O9ZNieycac/y8FxqgyzZhZbxmCitAtAeUrLPlxjSd5zA7LfpprmxEcOmQBnaGs5hYhiSGnJ0mqrtBLQ=="
},
"damerau-levenshtein": {
"version": "1.0.8",
@ -29969,7 +30121,8 @@
"electron-to-chromium": {
"version": "1.4.284",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA=="
"integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==",
"dev": true
},
"emoji-regex": {
"version": "9.2.2",
@ -30215,7 +30368,8 @@
"escalade": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw=="
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
"dev": true
},
"escape-html": {
"version": "1.0.3",
@ -30478,8 +30632,7 @@
"version": "8.6.0",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz",
"integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==",
"dev": true,
"requires": {}
"dev": true
},
"eslint-import-resolver-node": {
"version": "0.3.7",
@ -30737,15 +30890,13 @@
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz",
"integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==",
"dev": true,
"requires": {}
"dev": true
},
"eslint-plugin-simple-import-sort": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz",
"integrity": "sha512-bXgJQ+lqhtQBCuWY/FUWdB27j4+lqcvXv5rUARkzbeWLwea+S5eBZEQrhnO+WgX3ZoJHVj0cn943iyXwByHHQw==",
"dev": true,
"requires": {}
"dev": true
},
"eslint-plugin-storybook": {
"version": "0.6.10",
@ -31609,7 +31760,8 @@
"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=="
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true
},
"get-caller-file": {
"version": "2.0.5",
@ -32173,8 +32325,7 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true,
"requires": {}
"dev": true
},
"ieee754": {
"version": "1.2.1",
@ -33188,7 +33339,8 @@
"json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true
},
"jsonfile": {
"version": "6.1.0",
@ -33486,8 +33638,7 @@
"version": "7.1.8",
"resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.8.tgz",
"integrity": "sha512-rRSa1aFmFnpDRFAhv5vIkWM4nPaoB9vnzIjuIKa1wGupfn2hdCNeaQHKpu4/muoc8n8J7yowjTP2oncA4/Rbgg==",
"dev": true,
"requires": {}
"dev": true
},
"md5.js": {
"version": "1.3.5",
@ -34193,7 +34344,8 @@
"node-releases": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz",
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg=="
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"dev": true
},
"normalize-package-data": {
"version": "2.5.0",
@ -34783,8 +34935,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
"dev": true,
"requires": {}
"dev": true
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
@ -34889,6 +35040,12 @@
"fast-diff": "^1.1.2"
}
},
"prettier-plugin-tailwindcss": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz",
"integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==",
"dev": true
},
"pretty-error": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
@ -35280,8 +35437,7 @@
"version": "5.6.1",
"resolved": "https://registry.npmjs.org/react-colorful/-/react-colorful-5.6.1.tgz",
"integrity": "sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==",
"dev": true,
"requires": {}
"dev": true
},
"react-docgen": {
"version": "5.4.3",
@ -35313,8 +35469,7 @@
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.2.2.tgz",
"integrity": "sha512-tvg2ZtOpOi6QDwsb3GZhOjDkkX0h8Z2gipvTg6OVMUyoYoURhEiRNePT8NZItTVCDh39JJHnLdfCOkzoLbFnTg==",
"dev": true,
"requires": {}
"dev": true
},
"react-dom": {
"version": "17.0.2",
@ -35379,8 +35534,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/react-inspector/-/react-inspector-6.0.1.tgz",
"integrity": "sha512-cxKSeFTf7jpSSVddm66sKdolG90qURAX3g1roTeaN6x0YEbtWc8JpmFN9+yIqLNH2uEkYerWLtJZIXRIFuBKrg==",
"dev": true,
"requires": {}
"dev": true
},
"react-is": {
"version": "16.13.1",
@ -35495,8 +35649,7 @@
"react-table": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/react-table/-/react-table-7.8.0.tgz",
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA==",
"requires": {}
"integrity": "sha512-hNaz4ygkZO4bESeFfnfOft73iBUj8K5oKi1EcSHPAibEydfsX2MyU6Z8KCr3mv3C9Kqqh71U+DhZkFvibbnPbA=="
},
"read-cache": {
"version": "1.0.0",
@ -35652,8 +35805,7 @@
"redux-thunk": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz",
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==",
"requires": {}
"integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q=="
},
"regenerate": {
"version": "1.4.2",
@ -37106,8 +37258,7 @@
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz",
"integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==",
"dev": true,
"requires": {}
"dev": true
},
"style-to-object": {
"version": "0.3.0",
@ -37137,8 +37288,7 @@
"styled-jsx": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz",
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==",
"requires": {}
"integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA=="
},
"stylis": {
"version": "4.0.13",
@ -37778,7 +37928,7 @@
"version": "4.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz",
"integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==",
"devOptional": true
"dev": true
},
"uc.micro": {
"version": "1.0.6",
@ -38014,6 +38164,7 @@
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz",
"integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==",
"dev": true,
"requires": {
"escalade": "^3.1.1",
"picocolors": "^1.0.0"
@ -38051,14 +38202,12 @@
"use-isomorphic-layout-effect": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
"integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
"requires": {}
"integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA=="
},
"use-memo-one": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/use-memo-one/-/use-memo-one-1.1.3.tgz",
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==",
"requires": {}
"integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ=="
},
"use-sidecar": {
"version": "1.1.2",
@ -38072,8 +38221,7 @@
"use-sync-external-store": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
"requires": {}
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA=="
},
"util": {
"version": "0.12.5",
@ -38264,8 +38412,7 @@
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz",
"integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==",
"dev": true,
"requires": {}
"dev": true
},
"eslint-scope": {
"version": "5.1.1",
@ -38491,8 +38638,7 @@
"version": "8.12.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz",
"integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==",
"dev": true,
"requires": {}
"dev": true
},
"xtend": {
"version": "4.0.2",

@ -35,6 +35,7 @@
"@reduxjs/toolkit": "^1.8.3",
"@stripe/react-stripe-js": "^1.10.0",
"@stripe/stripe-js": "^1.46.0",
"@tanstack/react-query": "^4.23.0",
"add": "^2.0.6",
"axios": "^0.27.2",
"axios-auth-refresh": "^3.3.3",
@ -103,6 +104,7 @@
"eslint-plugin-storybook": "^0.6.10",
"postcss": "^8.4.14",
"prettier": "^2.8.3",
"prettier-plugin-tailwindcss": "^0.2.2",
"storybook": "^7.0.0-beta.30",
"storybook-dark-mode": "^2.0.5",
"tailwindcss": "3.2",

@ -30,8 +30,25 @@ const reverseContextNetlifyMapping: Mapping = {
"Production": "production"
}
const plansDev: Mapping = {
"starter": "prod_Mb4ATFT5QAHoPM",
"team": "prod_NEpD2WMXUS2eDn",
"professional": "prod_Mb4CetZ2jE7jdl",
"enterprise": "licence_key_required"
}
const plansProd: Mapping = {
"starter": "prod_Mb8oR5XNwyFTul",
"team": "prod_NEp7fAB3UJWK6A",
"professional": "prod_Mb8pUIpA0OUi5N",
"enterprise": "licence_key_required"
}
const plans = plansProd || plansDev;
export {
contextNetlifyMapping,
envMapping,
plans,
reverseContextNetlifyMapping,
reverseEnvMapping}

@ -1,4 +1,4 @@
{
"title": "Project Members",
"description": "This page shows the members of the selected project."
"description": "This page shows the members of the selected project, and allows you to modify their permissions."
}

@ -0,0 +1,11 @@
{
"title": "Aktivite Günlükleri",
"subtitle": "Bu Infisical projesi için Olay Geçmişi.",
"event": {
"readSecrets": "Sırlar Görüntülendi",
"updateSecrets": "Sırlar Güncellendi",
"addSecrets": "Sırlar Eklendi",
"deleteSecrets": "Sırlar Silindi"
},
"ip-address": "IP Addresi"
}

Some files were not shown because too many files have changed in this diff Show More