diff --git a/.env.example b/.env.example index 1926bcef63..d3ec397dea 100644 --- a/.env.example +++ b/.env.example @@ -47,11 +47,13 @@ CLIENT_ID_VERCEL= CLIENT_ID_NETLIFY= CLIENT_ID_GITHUB= CLIENT_ID_GITLAB= +CLIENT_ID_BITBUCKET= CLIENT_SECRET_HEROKU= CLIENT_SECRET_VERCEL= CLIENT_SECRET_NETLIFY= CLIENT_SECRET_GITHUB= CLIENT_SECRET_GITLAB= +CLIENT_SECRET_BITBUCKET= CLIENT_SLUG_VERCEL= # Sentry (optional) for monitoring errors diff --git a/.goreleaser.yaml b/.goreleaser.yaml index e30c6b7639..50115e58f4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -108,6 +108,22 @@ brews: zsh_completion.install "completions/infisical.zsh" => "_infisical" fish_completion.install "completions/infisical.fish" man1.install "manpages/infisical.1.gz" + - name: 'infisical@{{.Version}}' + tap: + owner: Infisical + name: homebrew-get-cli + commit_author: + name: "Infisical" + email: ai@infisical.com + 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 diff --git a/.husky/pre-commit b/.husky/pre-commit index e235e5d799..4f18d25215 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,3 @@ - #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" diff --git a/README.md b/README.md index b0b964d375..f995319709 100644 --- a/README.md +++ b/README.md @@ -54,17 +54,17 @@ We're on a mission to make secret management more accessible to everyone, not ju ## Features -- **[User-friendly dashboard](https://infisical.com/docs/documentation/platform/project)** to manage secrets across projects and environments (e.g. development, production, etc.) +- **[User-friendly dashboard](https://infisical.com/docs/documentation/platform/project)** to manage secrets across projects and environments (e.g. development, production, etc.) - **[Client SDKs](https://infisical.com/docs/sdks/overview)** to fetch secrets for your apps and infrastructure on demand -- **[Infisical CLI](https://infisical.com/docs/cli/overview)** to fetch and inject secrets into any framework in local development -- **[Native integrations](https://infisical.com/docs/integrations/overview)** with platforms like GitHub, Vercel, Netlify, and more +- **[Infisical CLI](https://infisical.com/docs/cli/overview)** to fetch and inject secrets into any framework in local development +- **[Native integrations](https://infisical.com/docs/integrations/overview)** with platforms like GitHub, Vercel, Netlify, and more - [**Automatic Kubernetes deployment secret reloads**](https://infisical.com/docs/documentation/getting-started/kubernetes) -- **[Complete control over your data](https://infisical.com/docs/self-hosting/overview)** - host it yourself on any infrastructure -- **[Secret versioning](https://infisical.com/docs/documentation/platform/secret-versioning)** and **[Point-in-Time Recovery]()** to version every secret and project state -- **[Audit logs](https://infisical.com/docs/documentation/platform/audit-logs)** to record every action taken in a project -- **Role-based Access Controls** per environment -- [**Simple on-premise deployments** to AWS, Digital Ocean, and more](https://infisical.com/docs/self-hosting/overview) -- [**Secret Scanning and Leak Prevention**](https://infisical.com/docs/cli/scanning-overview) +- **[Complete control over your data](https://infisical.com/docs/self-hosting/overview)** - host it yourself on any infrastructure +- **[Secret versioning](https://infisical.com/docs/documentation/platform/secret-versioning)** and **[Point-in-Time Recovery]()** to version every secret and project state +- **[Audit logs](https://infisical.com/docs/documentation/platform/audit-logs)** to record every action taken in a project +- **Role-based Access Controls** per environment +- [**Simple on-premise deployments** to AWS, Digital Ocean, and more](https://infisical.com/docs/self-hosting/overview) +- [**Secret Scanning and Leak Prevention**](https://infisical.com/docs/cli/scanning-overview) And much more. @@ -72,8 +72,8 @@ And much more. Check out the [Quickstart Guides](https://infisical.com/docs/getting-started/introduction) -| Use Infisical Cloud | Deploy Infisical on premise | -| --- | ----------- | +| Use Infisical Cloud | Deploy Infisical on premise | +| ------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | The fastest and most reliable way to
get started with Infisical is signing up
for free to [Infisical Cloud](https://app.infisical.com/login). | Deploy to DO
View all [deployment options](https://infisical.com/docs/self-hosting/overview) | ### Run Infisical locally @@ -83,7 +83,7 @@ To set up and run Infisical locally, make sure you have Git and Docker installed Linux/macOS: ```console -git clone https://github.com/Infisical/infisical && cd "$(basename $_ .git)" && cp .env.example .env && docker-compose -f docker-compose.yml up +git clone https://github.com/Infisical/infisical && cd "$(basename $_ .git)" && cp .env.example .env && docker-compose -f docker-compose.yml up ``` Windows Command Prompt: @@ -94,8 +94,9 @@ git clone https://github.com/Infisical/infisical && cd infisical && copy .env.ex Create an account at `http://localhost:80` -### Scan and prevent secret leaks -On top managing secrets with Infisical, you can also [scan for over 140+ secret types]() in your files, directories and git repositories. +### Scan and prevent secret leaks + +On top managing secrets with Infisical, you can also [scan for over 140+ secret types]() in your files, directories and git repositories. To scan your full git history, run: @@ -103,20 +104,19 @@ To scan your full git history, run: infisical scan --verbose ``` -Install pre commit hook to scan each commit before you push to your repository +Install pre commit hook to scan each commit before you push to your repository ``` infisical scan install --pre-commit-hook ``` -Lean about Infisical's code scanning feature [here](https://infisical.com/docs/cli/scanning-overview) - +Lean about Infisical's code scanning feature [here](https://infisical.com/docs/cli/scanning-overview) ## Open-source vs. paid -This repo available under the [MIT expat license](https://github.com/Infisical/infisical/blob/main/LICENSE), with the exception of the `ee` directory which will contain premium enterprise features requiring a Infisical license. +This repo available under the [MIT expat license](https://github.com/Infisical/infisical/blob/main/LICENSE), with the exception of the `ee` directory which will contain premium enterprise features requiring a Infisical license. -If you are interested in managed Infisical Cloud of self-hosted Enterprise Offering, take a look at [our webiste](https://infisical.com/) or [book a meeting with us](https://cal.com/vmatsiiako/infisical-demo): +If you are interested in managed Infisical Cloud of self-hosted Enterprise Offering, take a look at [our webiste](https://infisical.com/) or [book a meeting with us](https://cal.com/vmatsiiako/infisical-demo): Schedule a meeting @@ -134,8 +134,8 @@ Whether it's big or small, we love contributions. Check out our guide to see how Not sure where to get started? You can: -- [Book a free, non-pressure pairing session / code walkthrough with one of our teammates](https://cal.com/tony-infisical/30-min-meeting-contributing)! -- Join our Slack, and ask us any questions there. +- [Book a free, non-pressure pairing session / code walkthrough with one of our teammates](https://cal.com/tony-infisical/30-min-meeting-contributing)! +- Join our Slack, and ask us any questions there. ## Resources @@ -156,4 +156,26 @@ Not sure where to get started? You can: - + + + + + + + + + + + + + + + + + + + + + + + diff --git a/backend/.eslintrc b/backend/.eslintrc index d236087c1b..6aa49ee313 100644 --- a/backend/.eslintrc +++ b/backend/.eslintrc @@ -10,6 +10,8 @@ "plugin:@typescript-eslint/recommended" ], "rules": { + "no-empty-function": "off", + "@typescript-eslint/no-empty-function": "off", "no-console": 2, "quotes": [ "error", @@ -24,7 +26,6 @@ ], "@typescript-eslint/no-unused-vars": "off", "unused-imports/no-unused-imports": "error", - "@typescript-eslint/no-empty-function": "off", "unused-imports/no-unused-vars": [ "warn", { diff --git a/backend/package-lock.json b/backend/package-lock.json index 488a6819f1..5e99239385 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.319.0", "@godaddy/terminus": "^4.12.0", + "@node-saml/passport-saml": "^4.0.4", "@octokit/rest": "^19.0.5", "@sentry/node": "^7.49.0", "@sentry/tracing": "^7.48.0", @@ -755,47 +756,47 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-compilation-targets": "^7.22.1", - "@babel/helper-module-transforms": "^7.22.1", - "@babel/helpers": "^7.22.0", - "@babel/parser": "^7.22.0", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -821,12 +822,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", "dev": true, "dependencies": { - "@babel/types": "^7.22.3", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -836,16 +837,16 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", + "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.22.0", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "engines": { "node": ">=6.9.0" @@ -864,151 +865,151 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "dependencies": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "dependencies": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", "dev": true, "dependencies": { - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.3" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -1088,9 +1089,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.3.tgz", - "integrity": "sha512-vrukxyW/ep8UD1UDzOYpTKQ6abgjFoeG6L+4ar9+c5TN9QnlqiOi6QK7LSR5ewm/ERyGkT/Ai6VboNrxhbr9Uw==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1160,12 +1161,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1262,12 +1263,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -1277,9 +1278,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", - "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -1288,33 +1289,33 @@ } }, "node_modules/@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.1.tgz", - "integrity": "sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==", + "version": "7.22.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", + "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.22.0", - "@babel/types": "^7.22.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.7", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1332,13 +1333,13 @@ } }, "node_modules/@babel/types": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.3.tgz", - "integrity": "sha512-P3na3xIQHTKY4L0YOG7pM8M8uoUIB910WQaSiiMCZUC2Cy8XFEQONGABFnHWBa2gpGKODTAJcNhi5Zk0sLRrzg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1416,14 +1417,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -1439,18 +1440,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@godaddy/terminus": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.0.tgz", - "integrity": "sha512-zbl6gKxPAnAoAAGCyRN1kOMHTXgiW3C09w8McLKZWSSHQlsiRZlMZzBwSv1aK9PaRU25w80cnOlt3ow+uQwR1Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.1.tgz", + "integrity": "sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==", "dependencies": { "stoppable": "^1.1.0" } @@ -1461,9 +1462,9 @@ "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -1611,16 +1612,16 @@ } }, "node_modules/@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", + "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -1628,16 +1629,16 @@ } }, "node_modules/@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", + "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/reporters": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", @@ -1645,20 +1646,20 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", + "jest-config": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-resolve-dependencies": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", + "jest-watcher": "^29.6.1", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -1675,37 +1676,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", + "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", "dev": true, "dependencies": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.6.1", + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", + "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -1715,49 +1716,49 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", + "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", + "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", + "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -1769,9 +1770,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -1789,45 +1790,25 @@ } } }, - "node_modules/@jest/reporters/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" }, @@ -1836,13 +1817,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", + "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -1851,14 +1832,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", + "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "slash": "^3.0.0" }, "engines": { @@ -1866,22 +1847,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", + "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -1892,12 +1873,12 @@ } }, "node_modules/@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -1968,9 +1949,9 @@ "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" }, "node_modules/@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "dependencies": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -2192,6 +2173,43 @@ "node": ">= 10" } }, + "node_modules/@node-saml/node-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.4.tgz", + "integrity": "sha512-oybUBWBYVsHGckQxzyzlpRM4E2iuW3I2Ok/J9SwlotdmjvmZxSo6Ub74D9wltG8C9daJZYI57uy+1UK4FtcGXA==", + "dependencies": { + "@types/debug": "^4.1.7", + "@types/passport": "^1.0.11", + "@types/xml-crypto": "^1.4.2", + "@types/xml-encryption": "^1.2.1", + "@types/xml2js": "^0.4.11", + "@xmldom/xmldom": "^0.8.6", + "debug": "^4.3.4", + "xml-crypto": "^3.0.1", + "xml-encryption": "^3.0.2", + "xml2js": "^0.5.0", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/@node-saml/passport-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", + "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", + "dependencies": { + "@node-saml/node-saml": "^4.0.4", + "@types/express": "^4.17.14", + "@types/passport": "^1.0.11", + "@types/passport-strategy": "^0.2.35", + "passport": "^0.6.0", + "passport-strategy": "^1.0.0" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -2302,12 +2320,9 @@ } }, "node_modules/@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "dependencies": { - "@octokit/types": "^9.0.0" - }, + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==", "engines": { "node": ">= 14" } @@ -2325,9 +2340,9 @@ } }, "node_modules/@octokit/core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", - "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -2342,9 +2357,9 @@ } }, "node_modules/@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "dependencies": { "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", @@ -2391,9 +2406,9 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "17.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", - "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" }, "node_modules/@octokit/plugin-enterprise-compatibility": { "version": "1.3.0", @@ -2451,12 +2466,11 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", - "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", "dependencies": { - "@octokit/types": "^9.2.3", - "deprecation": "^2.3.1" + "@octokit/types": "^10.0.0" }, "engines": { "node": ">= 14" @@ -2465,6 +2479,14 @@ "@octokit/core": ">=3" } }, + "node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", + "dependencies": { + "@octokit/openapi-types": "^18.0.0" + } + }, "node_modules/@octokit/plugin-retry": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz", @@ -2488,9 +2510,9 @@ } }, "node_modules/@octokit/request": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", - "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -2517,9 +2539,9 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "version": "19.0.13", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "dependencies": { "@octokit/core": "^4.2.1", "@octokit/plugin-paginate-rest": "^6.1.2", @@ -2536,11 +2558,11 @@ "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" }, "node_modules/@octokit/types": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", - "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", "dependencies": { - "@octokit/openapi-types": "^17.2.0" + "@octokit/openapi-types": "^18.0.0" } }, "node_modules/@octokit/webhooks": { @@ -2693,49 +2715,6 @@ "node": ">=6" } }, - "node_modules/@probot/pino/node_modules/colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "node_modules/@probot/pino/node_modules/jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/@probot/pino/node_modules/pino-pretty": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", - "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", - "dependencies": { - "@hapi/bourne": "^2.0.0", - "args": "^5.0.1", - "colorette": "^1.3.0", - "dateformat": "^4.5.1", - "fast-safe-stringify": "^2.0.7", - "jmespath": "^0.15.0", - "joycon": "^3.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "rfdc": "^1.3.0", - "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "bin": { - "pino-pretty": "bin.js" - } - }, - "node_modules/@probot/pino/node_modules/pino-pretty/node_modules/split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "dependencies": { - "readable-stream": "^3.0.0" - } - }, "node_modules/@probot/pino/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -2796,42 +2775,32 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "node_modules/@sentry-internal/tracing": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.53.1.tgz", - "integrity": "sha512-a4H4rvVdz0XDGgNfRqc7zg6rMt2P1P05xBmgfIfztYy94Vciw1QMdboNiT7einr8ra8wogdEaK4Pe2AzYAPBJQ==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.3.tgz", + "integrity": "sha512-/RkBj/0zQKGsW/UYg6hufrLHHguncLfu4610FCPWpVp0K5Yu5ou8/Aw8D76G3ZxD2TiuSNGwX0o7TYN371ZqTQ==", "dependencies": { - "@sentry/core": "7.53.1", - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", - "tslib": "^1.9.3" + "@sentry/core": "7.59.3", + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry-internal/tracing/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sentry/core": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.53.1.tgz", - "integrity": "sha512-DAH8IJNORJJ7kQLqsZuhMkN6cwJjXzFuuUoZor7IIDHIHjtl51W+2F3Stg3+I3ZoKDfJfUNKqhipk2WZjG0FBg==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.3.tgz", + "integrity": "sha512-cGBOwT9gziIn50fnlBH1WGQlGcHi7wrbvOCyrex4MxKnn1LSBYWBhwU0ymj8DI/9MyPrGDNGkrgpV0WJWBSClg==", "dependencies": { - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", - "tslib": "^1.9.3" + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/core/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sentry/hub": { "version": "6.19.7", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-6.19.7.tgz", @@ -2897,68 +2866,58 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@sentry/node": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.53.1.tgz", - "integrity": "sha512-B4ax8sRd54xj4ad+4eY2EOKNt0Mh1NjuLW1zUKS8HW3h0bmuaDFzGuhEVvEY5H4SaV6tZKj1c0dvnMnyUbYkhA==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.59.3.tgz", + "integrity": "sha512-5dG90YzmKjuy5TK04qDuc9LBxnGfqsZw8Oh9giwOBfQVCaFp7R14AXyQ1F8k3iUF+4sGeTvoqi9I/GKAItVmlA==", "dependencies": { - "@sentry-internal/tracing": "7.53.1", - "@sentry/core": "7.53.1", - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", + "@sentry-internal/tracing": "7.59.3", + "@sentry/core": "7.59.3", + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", - "tslib": "^1.9.3" + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/node/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sentry/tracing": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.53.1.tgz", - "integrity": "sha512-1lpys/e19ee2gDTkcgIXyFNJySEqxdIxlu3Q1Oj+V0ORXVBfA9kFap2fHPWASaDJvmy1zpgGKlbzCpr+IEyfYQ==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.59.3.tgz", + "integrity": "sha512-+gDsfhYdteAR4NyKl3B5JVQs/bXYT73ajoFrlprfDjAJCEVR9W1P4CULavoLtfASxVqBQcZyT87Hsb9/vbn6bg==", "dependencies": { - "@sentry-internal/tracing": "7.53.1" + "@sentry-internal/tracing": "7.59.3" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/types": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.53.1.tgz", - "integrity": "sha512-/ijchRIu+jz3+j/zY+7KRPfLSCY14fTx5xujjbOdmEKjmIHQmwPBdszcQm40uwofrR8taV4hbt5MFN+WnjCkCw==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.3.tgz", + "integrity": "sha512-HQ/Pd3YHyIa4HM0bGfOsfI4ZF+sLVs6II9VtlS4hsVporm4ETl3Obld5HywO3aVYvWOk5j/bpAW9JYsxXjRG5A==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.53.1.tgz", - "integrity": "sha512-DKJA1LSUOEv4KOR828MzVuLh+drjeAgzyKgN063OEKmnirgjgRgNNS8wUgwpG0Tn2k6ANZGCwrdfzPeSBxshKg==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.3.tgz", + "integrity": "sha512-Q57xauMKuzd6S+POA1fmulfjzTsb/z118TNAfZZNkHqVB48hHBqgzdhbEBmN4jPCSKV2Cx7VJUoDZxJfzQyLUQ==", "dependencies": { - "@sentry/types": "7.53.1", - "tslib": "^1.9.3" + "@sentry/types": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/utils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - }, "node_modules/@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "node_modules/@sinonjs/commons": { @@ -2971,10 +2930,9 @@ } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", - "deprecated": "Use version 10.1.0. Version 10.2.0 has potential breaking issues", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { "@sinonjs/commons": "^3.0.0" @@ -3513,9 +3471,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.0.tgz", - "integrity": "sha512-TBOjqAGf0hmaqRwpii5LLkJLg7c6OMm4nHLmpsUxwk9bBHtoTC6dAHdVWdGv4TBxj2CZOZY8Xfq8WmfoVi7n4Q==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "dependencies": { "@babel/types": "^7.20.7" @@ -3587,6 +3545,14 @@ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" }, + "node_modules/@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -3618,6 +3584,11 @@ "@types/node": "*" } }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, "node_modules/@types/ioredis": { "version": "4.28.10", "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", @@ -3656,9 +3627,9 @@ } }, "node_modules/@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "version": "29.5.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", + "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3706,10 +3677,15 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "node_modules/@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, "node_modules/@types/node": { - "version": "18.16.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", - "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==" + "version": "18.16.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz", + "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" }, "node_modules/@types/nodemailer": { "version": "6.4.8", @@ -3724,11 +3700,19 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", - "dev": true, "dependencies": { "@types/express": "*" } }, + "node_modules/@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "dependencies": { + "@types/express": "*", + "@types/passport": "*" + } + }, "node_modules/@types/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", @@ -3773,9 +3757,9 @@ } }, "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "node_modules/@types/qs": { @@ -3804,10 +3788,11 @@ } }, "node_modules/@types/serve-static": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", - "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", "dependencies": { + "@types/http-errors": "*", "@types/mime": "*", "@types/node": "*" } @@ -3872,6 +3857,31 @@ "@types/webidl-conversions": "*" } }, + "node_modules/@types/xml-crypto": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.2.tgz", + "integrity": "sha512-1kT+3gVkeBDg7Ih8NefxGYfCApwZViMIs5IEs5AXF6Fpsrnf9CLAEIRh0DYb1mIcRcvysVbe27cHsJD6rJi36w==", + "dependencies": { + "@types/node": "*", + "xpath": "0.0.27" + } + }, + "node_modules/@types/xml-encryption": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.1.tgz", + "integrity": "sha512-UeyZkfZFZSa9XCGU5uGgUmsSLwQESDJvF076bJGyDf2gkXJjKvK8fW/x4ckvEHB2M/5RHJEkMc5xI+JrdmCTKA==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/xml2js": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", + "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -3888,17 +3898,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", - "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/type-utils": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -3922,14 +3932,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" }, "engines": { @@ -3949,13 +3959,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3966,13 +3976,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", - "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -3993,9 +4003,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4006,13 +4016,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -4033,17 +4043,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -4059,12 +4069,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -4075,22 +4085,19 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -4104,9 +4111,9 @@ } }, "node_modules/acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4438,9 +4445,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1386.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1386.0.tgz", - "integrity": "sha512-bmUvpNRR4x1YvTaAm7WK/2lSNVPrNuiYlleU47GA5Xskh8PKaWedGHvGinH2YwhC720hM0Qc4f4/snUPGJ0eYg==", + "version": "2.1419.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1419.0.tgz", + "integrity": "sha512-JcD8gb8I5fH/TGdObG8UYyyXfnqVYk50wx9TGao6G/xBYT3YoYeQXj020W568YQpO+dBKRuR4U2LRYdKBNmQ/g==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -4476,21 +4483,21 @@ } }, "node_modules/axios-retry": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.0.tgz", - "integrity": "sha512-g48qNrLX30VU6ECWltpFCPegKK6dWzMDYv2o83W2zUL/Zh/SLXbT6ksGoKqYZHtghzqeeXhZBcSXJkO1fPbCcw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.1.tgz", + "integrity": "sha512-mQRJ4IyAUnYig14BQ4MnnNHHuH1cNH7NW4JxEUD6mNJwK6pwOY66wKLCwZ6Y0o3POpfStalqRC+J4+Hnn6Om7w==", "dependencies": { "@babel/runtime": "^7.15.4", "is-retry-allowed": "^2.2.0" } }, "node_modules/babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", + "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", "dev": true, "dependencies": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.6.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -4764,9 +4771,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.6.tgz", - "integrity": "sha512-PF07dKGXKR+/bljJzCB6rAYtHEu21TthLxmJagtQizx+rwiqdRDBO5971Xu1N7MgcMLi4+mr4Cnl76x7O3DHtA==", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "dev": true, "funding": [ { @@ -4783,8 +4790,8 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001489", - "electron-to-chromium": "^1.4.411", + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", "node-releases": "^2.0.12", "update-browserslist-db": "^1.0.11" }, @@ -4947,9 +4954,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001489", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", - "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", + "version": "1.0.30001517", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", + "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", "dev": true, "funding": [ { @@ -5063,9 +5070,9 @@ } }, "node_modules/cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "node_modules/clean-stack": { @@ -5117,9 +5124,9 @@ } }, "node_modules/collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "node_modules/color": { @@ -5179,9 +5186,9 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" }, "node_modules/colorspace": { "version": "1.1.4", @@ -5459,9 +5466,9 @@ } }, "node_modules/detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", "engines": { "node": ">=8" } @@ -5528,11 +5535,14 @@ } }, "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", "engines": { "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, "node_modules/ecdsa-sig-formatter": { @@ -5549,9 +5559,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.411.tgz", - "integrity": "sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==", + "version": "1.4.467", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", + "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", "dev": true }, "node_modules/emittery": { @@ -5627,16 +5637,16 @@ } }, "node_modules/eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -5647,7 +5657,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5657,7 +5667,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -5667,9 +5676,8 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "bin": { @@ -5738,9 +5746,9 @@ } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -5763,12 +5771,12 @@ } }, "node_modules/espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "dependencies": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" }, @@ -5859,14 +5867,6 @@ "node": ">= 0.6" } }, - "node_modules/event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -5916,16 +5916,17 @@ } }, "node_modules/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.5.0", + "@jest/expect-utils": "^29.6.1", + "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5993,12 +5994,49 @@ "node": ">=v12.22.9" } }, - "node_modules/express-rate-limit": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz", - "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==", + "node_modules/express-handlebars/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/express-handlebars/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">= 12.9.0" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/express-handlebars/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/express-rate-limit": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.8.0.tgz", + "integrity": "sha512-yVeDWczkh8qgo9INJB1tT4j7LFu+n6ei/oqSMsqpsUIGYjTM+gk+Q3wv19TMUdo8chvus8XohAuOhG7RYRM9ZQ==", + "engines": { + "node": ">= 14.0.0" }, "peerDependencies": { "express": "^4 || ^5" @@ -6046,11 +6084,6 @@ "node >=0.6.0" ] }, - "node_modules/fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -6058,9 +6091,9 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -6118,11 +6151,6 @@ "punycode": "^1.3.2" } }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - }, "node_modules/fast-xml-parser": { "version": "4.2.5", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", @@ -6469,18 +6497,19 @@ } }, "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" }, "engines": { - "node": ">=12" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -6498,25 +6527,6 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "13.20.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", @@ -6580,12 +6590,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "node_modules/grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -6694,15 +6698,6 @@ "node": ">=12.0.0" } }, - "node_modules/help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "dependencies": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, "node_modules/hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -6838,9 +6833,9 @@ } }, "node_modules/infisical-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", - "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.3.2.tgz", + "integrity": "sha512-o1rxfOBAmpTiipka9Xnfa2AgTS8CkJHo0aRQwk6UGi+yEkKzXS7dDM7bZD56M/z+yKGLK15QkfFGZXp1VomlHw==", "dependencies": { "axios": "^1.3.3", "dotenv": "^16.0.3", @@ -7083,15 +7078,11 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.11" }, "engines": { "node": ">= 0.4" @@ -7187,15 +7178,15 @@ } }, "node_modules/jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", + "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.6.1" }, "bin": { "jest": "bin/jest.js" @@ -7226,28 +7217,28 @@ } }, "node_modules/jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", + "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.6.1", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" @@ -7257,21 +7248,21 @@ } }, "node_modules/jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", + "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", "dev": true, "dependencies": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-config": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -7291,31 +7282,31 @@ } }, "node_modules/jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", + "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.6.1", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", + "jest-circus": "^29.6.1", + "jest-environment-node": "^29.6.1", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -7335,36 +7326,16 @@ } } }, - "node_modules/jest-config/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", + "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -7383,33 +7354,33 @@ } }, "node_modules/jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", + "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-util": "^29.6.1", + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", + "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -7425,20 +7396,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", + "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -7465,46 +7436,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", + "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", + "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", + "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -7513,14 +7484,14 @@ } }, "node_modules/jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", + "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -7553,17 +7524,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", + "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -7573,43 +7544,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", + "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-snapshot": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", + "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", "dev": true, "dependencies": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/environment": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-environment-node": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-leak-detector": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-resolve": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-util": "^29.6.1", + "jest-watcher": "^29.6.1", + "jest-worker": "^29.6.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -7618,31 +7589,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", + "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/globals": "^29.6.1", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -7650,67 +7621,45 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/jest-runtime/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", + "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", + "@jest/expect-utils": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.6.1", + "semver": "^7.5.3" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", + "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -7722,35 +7671,35 @@ } }, "node_modules/jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", + "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", "dev": true, "dependencies": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", + "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "string-length": "^4.0.1" }, "engines": { @@ -7758,13 +7707,13 @@ } }, "node_modules/jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", + "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -7878,9 +7827,9 @@ } }, "node_modules/jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", "dependencies": { "jws": "^3.2.2", "lodash": "^4.17.21", @@ -8391,9 +8340,9 @@ } }, "node_modules/mongoose": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.1.tgz", - "integrity": "sha512-AvQ8C5ZGF6GcsQhoRg/i7pbNZpb96qLGU5ICBllckp7qMOxcfUF1nA6JstZw841BqRcE6myZ/mx9CluEESaw5Q==", + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.4.tgz", + "integrity": "sha512-q9NaW9/BBYZofx80SqlR7uoSR09CS3g02y+KMj1lNLUxcFFsPshupY3WWisNFauYG9gyuDF4L/RgyIK3obSghg==", "dependencies": { "bson": "^4.7.2", "kareem": "2.5.1", @@ -8550,9 +8499,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8594,15 +8543,15 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, "node_modules/nodemailer": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz", - "integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg==", + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==", "engines": { "node": ">=6.0.0" } @@ -11334,11 +11283,6 @@ "@octokit/openapi-types": "^14.0.0" } }, - "node_modules/on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -11650,80 +11594,6 @@ "pino": "bin.js" } }, - "node_modules/pino-abstract-transport": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", - "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", - "dependencies": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - } - }, - "node_modules/pino-abstract-transport/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-abstract-transport/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/pino-abstract-transport/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/pino-abstract-transport/node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, "node_modules/pino-http": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-5.8.0.tgz", @@ -11740,100 +11610,41 @@ "integrity": "sha512-cK0pekc1Kjy5w9V2/n+8MkZwusa6EyyxfeQCB799CQRhRt/CqYKiWs5adeu8Shve2ZNffvfC/7J64A2PJo1W/Q==" }, "node_modules/pino-pretty": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.1.tgz", - "integrity": "sha512-yrn00+jNpkvZX/NrPVCPIVHAfTDy3ahF0PND9tKqZk4j9s+loK8dpzrJj4dGb7i+WLuR50ussuTAiWoMWU+qeA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", + "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", "dependencies": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", + "@hapi/bourne": "^2.0.0", + "args": "^5.0.1", + "colorette": "^1.3.0", + "dateformat": "^4.5.1", + "fast-safe-stringify": "^2.0.7", + "jmespath": "^0.15.0", + "joycon": "^3.0.0", "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", + "readable-stream": "^3.6.0", + "rfdc": "^1.3.0", + "split2": "^3.1.1", "strip-json-comments": "^3.1.1" }, "bin": { "pino-pretty": "bin.js" } }, - "node_modules/pino-pretty/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "node_modules/pino-pretty/node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "node_modules/pino-pretty/node_modules/jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==", "engines": { - "node": ">=0.8.x" + "node": ">= 0.6.0" } }, - "node_modules/pino-pretty/node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/pino-pretty/node_modules/readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", + "node_modules/pino-pretty/node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dependencies": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/pino-pretty/node_modules/sonic-boom": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", - "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", - "dependencies": { - "atomic-sleep": "^1.0.0" + "readable-stream": "^3.0.0" } }, "node_modules/pino-std-serializers": { @@ -11856,9 +11667,9 @@ } }, "node_modules/pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, "engines": { "node": ">= 6" @@ -12026,12 +11837,12 @@ } }, "node_modules/pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -12371,14 +12182,6 @@ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "engines": { - "node": ">= 0.6.0" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -12460,12 +12263,9 @@ } }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", - "engines": { - "node": ">=6" - } + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "node_modules/pure-rand": { "version": "6.0.2", @@ -12595,9 +12395,9 @@ } }, "node_modules/rate-limit-mongo/node_modules/mongodb": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz", + "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==", "dependencies": { "bl": "^2.2.1", "bson": "^1.1.4", @@ -12807,25 +12607,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/rimraf/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -12907,11 +12688,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, - "node_modules/secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -13152,40 +12928,6 @@ "node": ">=0.12.0" } }, - "node_modules/smee-client/node_modules/mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true, - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/smee-client/node_modules/superagent": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", - "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", - "dev": true, - "dependencies": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.3", - "readable-stream": "^3.6.0", - "semver": "^7.3.7" - }, - "engines": { - "node": ">=6.4.0 <13 || >=14" - } - }, "node_modules/snappy": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/snappy/-/snappy-7.1.1.tgz", @@ -13422,21 +13164,22 @@ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "node_modules/superagent": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", - "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", + "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", "dev": true, "dependencies": { "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", + "cookiejar": "^2.1.3", "debug": "^4.3.4", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.0", - "formidable": "^2.1.2", + "formidable": "^2.0.1", "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" + "mime": "^2.5.0", + "qs": "^6.10.3", + "readable-stream": "^3.6.0", + "semver": "^7.3.7" }, "engines": { "node": ">=6.4.0 <13 || >=14" @@ -13467,6 +13210,39 @@ "node": ">=6.4.0" } }, + "node_modules/supertest/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest/node_modules/superagent": { + "version": "8.0.9", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", + "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", + "dev": true, + "dependencies": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=6.4.0 <13 || >=14" + } + }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -13491,9 +13267,9 @@ } }, "node_modules/swagger-autogen": { - "version": "2.23.1", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.1.tgz", - "integrity": "sha512-tOAb5cOGNPduIHKoOxndCRy2Mrg7xV3O1RerrWExrDxeSTjXhA350pyJd7VUDY6ZO9gbZ34Bjlc5CXkleUgvAQ==", + "version": "2.23.5", + "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.5.tgz", + "integrity": "sha512-4Tl2+XhZMyHoBYkABnScHtQE0lKPKUD3NBt09mClrI6UKOUYljKlYw1xiFVwsHCTGR2hAXmhT4PpgjruCtt1ZA==", "dependencies": { "acorn": "^7.4.1", "deepmerge": "^4.2.2", @@ -13512,29 +13288,10 @@ "node": ">=0.4.0" } }, - "node_modules/swagger-autogen/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/swagger-ui-dist": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.19.0.tgz", - "integrity": "sha512-9C9fJGI18gK5AhaU5YRyPY1lXJH4lmWh8h9zFMrJBkYzdRjCbAzYl1ayWPYgwFvag/Luqi3Co599OK/39IS2QQ==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.1.3.tgz", + "integrity": "sha512-W/vZFeZHG+xTN4yu8LXdaIrcnT4Hbr7qRUILYlMEoIiG6nuTylnEGeRcvL64F2eHRA2Jo/fgCSTU06Qfh0lT3g==" }, "node_modules/swagger-ui-express": { "version": "4.6.3", @@ -13585,26 +13342,6 @@ "node": ">=8" } }, - "node_modules/test-exclude/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/text-hex": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", @@ -13698,15 +13435,26 @@ "node": ">=12" } }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, "node_modules/triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } }, "node_modules/ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -13715,7 +13463,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" }, "bin": { @@ -13790,9 +13538,9 @@ } }, "node_modules/tslib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -13992,6 +13740,15 @@ "punycode": "^2.1.0" } }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/url": { "version": "0.10.3", "resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz", @@ -14148,16 +13905,15 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", "dependencies": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -14175,9 +13931,9 @@ } }, "node_modules/winston": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", - "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.10.0.tgz", + "integrity": "sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==", "dependencies": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -14268,6 +14024,47 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, + "node_modules/xml-crypto": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", + "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", + "dependencies": { + "@xmldom/xmldom": "^0.8.8", + "xpath": "0.0.32" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xml-crypto/node_modules/xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/xml-encryption": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", + "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", + "dependencies": { + "@xmldom/xmldom": "^0.8.5", + "escape-html": "^1.0.3", + "xpath": "0.0.32" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/xml-encryption/node_modules/xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==", + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", @@ -14280,7 +14077,7 @@ "node": ">=4.0.0" } }, - "node_modules/xmlbuilder": { + "node_modules/xml2js/node_modules/xmlbuilder": { "version": "11.0.1", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", @@ -14288,6 +14085,22 @@ "node": ">=4.0" } }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==", + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -14942,41 +14755,41 @@ } }, "@babel/code-frame": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", - "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.5.tgz", + "integrity": "sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==", "dev": true, "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.5" } }, "@babel/compat-data": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", - "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.9.tgz", + "integrity": "sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==", "dev": true }, "@babel/core": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", - "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.9.tgz", + "integrity": "sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-compilation-targets": "^7.22.1", - "@babel/helper-module-transforms": "^7.22.1", - "@babel/helpers": "^7.22.0", - "@babel/parser": "^7.22.0", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.9", + "@babel/helper-compilation-targets": "^7.22.9", + "@babel/helper-module-transforms": "^7.22.9", + "@babel/helpers": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.8", + "@babel/types": "^7.22.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", "json5": "^2.2.2", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "dependencies": { "convert-source-map": { @@ -14994,28 +14807,28 @@ } }, "@babel/generator": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", - "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.9.tgz", + "integrity": "sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==", "dev": true, "requires": { - "@babel/types": "^7.22.3", + "@babel/types": "^7.22.5", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, "@babel/helper-compilation-targets": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.1.tgz", - "integrity": "sha512-Rqx13UM3yVB5q0D/KwQ8+SPfX/+Rnsy1Lw1k/UwOC4KC6qrzIQoY3lYnBu5EHKBlEHHcj0M0W8ltPSkD8rqfsQ==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.9.tgz", + "integrity": "sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==", "dev": true, "requires": { - "@babel/compat-data": "^7.22.0", - "@babel/helper-validator-option": "^7.21.0", - "browserslist": "^4.21.3", + "@babel/compat-data": "^7.22.9", + "@babel/helper-validator-option": "^7.22.5", + "browserslist": "^4.21.9", "lru-cache": "^5.1.1", - "semver": "^6.3.0" + "semver": "^6.3.1" }, "dependencies": { "semver": { @@ -15027,115 +14840,112 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.1.tgz", - "integrity": "sha512-Z2tgopurB/kTbidvzeBrc2To3PUP/9i5MUe+fU6QJCQDyPwSH2oRapkLw3KGECDYSjhQZCNxEvNvZlLw8JjGwA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz", + "integrity": "sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==", "dev": true }, "@babel/helper-function-name": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.21.0.tgz", - "integrity": "sha512-HfK1aMRanKHpxemaY2gqBmL04iAPOPRj7DxtNbiDOrJK+gdwkiNRVpCpUJYbUT+aZyemKN8brqTOxzCaG6ExRg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.22.5.tgz", + "integrity": "sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==", "dev": true, "requires": { - "@babel/template": "^7.20.7", - "@babel/types": "^7.21.0" + "@babel/template": "^7.22.5", + "@babel/types": "^7.22.5" } }, "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-module-imports": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.21.4.tgz", - "integrity": "sha512-orajc5T2PsRYUN3ZryCEFeMDYwyw09c/pZeaQEZPH0MpKzSvn3e0uXsDBu3k03VI+9DBiRo+l22BfKTpKwa/Wg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.5.tgz", + "integrity": "sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==", "dev": true, "requires": { - "@babel/types": "^7.21.4" + "@babel/types": "^7.22.5" } }, "@babel/helper-module-transforms": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.1.tgz", - "integrity": "sha512-dxAe9E7ySDGbQdCVOY/4+UcD8M9ZFqZcZhSPsPacvCG4M+9lwtDDQfI2EoaSvmf7W/8yCBkGU0m7Pvt1ru3UZw==", + "version": "7.22.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.22.9.tgz", + "integrity": "sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-module-imports": "^7.21.4", - "@babel/helper-simple-access": "^7.21.5", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/helper-validator-identifier": "^7.19.1", - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.0" + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-module-imports": "^7.22.5", + "@babel/helper-simple-access": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/helper-validator-identifier": "^7.22.5" } }, "@babel/helper-plugin-utils": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.21.5.tgz", - "integrity": "sha512-0WDaIlXKOX/3KfBK/dwP1oQGiPh6rjMkT7HIRv7i5RR2VUMwrx5ZL0dwBkKx7+SW1zwNdgjHd34IMk5ZjTeHVg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", + "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", "dev": true }, "@babel/helper-simple-access": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.21.5.tgz", - "integrity": "sha512-ENPDAMC1wAjR0uaCUwliBdiSl1KBJAVnMTzXqi64c2MG8MPR6ii4qf7bSXDqSFbr4W6W028/rf5ivoHop5/mkg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", + "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", "dev": true, "requires": { - "@babel/types": "^7.21.5" + "@babel/types": "^7.22.5" } }, "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-string-parser": { - "version": "7.21.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.21.5.tgz", - "integrity": "sha512-5pTUx3hAJaZIdW99sJ6ZUUgWq/Y+Hja7TowEnLNMm1VivRgZQL3vpBY3qUACVsvw+yQU6+YgfBVmcbLaZtrA1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz", + "integrity": "sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==", "dev": true }, "@babel/helper-validator-option": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz", - "integrity": "sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.5.tgz", + "integrity": "sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==", "dev": true }, "@babel/helpers": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", - "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.6.tgz", + "integrity": "sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==", "dev": true, "requires": { - "@babel/template": "^7.21.9", - "@babel/traverse": "^7.22.1", - "@babel/types": "^7.22.3" + "@babel/template": "^7.22.5", + "@babel/traverse": "^7.22.6", + "@babel/types": "^7.22.5" } }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.5.tgz", + "integrity": "sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.18.6", + "@babel/helper-validator-identifier": "^7.22.5", "chalk": "^2.0.0", "js-tokens": "^4.0.0" }, @@ -15199,9 +15009,9 @@ } }, "@babel/parser": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.3.tgz", - "integrity": "sha512-vrukxyW/ep8UD1UDzOYpTKQ6abgjFoeG6L+4ar9+c5TN9QnlqiOi6QK7LSR5ewm/ERyGkT/Ai6VboNrxhbr9Uw==", + "version": "7.22.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.7.tgz", + "integrity": "sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -15250,12 +15060,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", - "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", + "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -15322,47 +15132,47 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.21.4.tgz", - "integrity": "sha512-xz0D39NvhQn4t4RNsHmDnnsaQizIlUkdtYvLs8La1BlfjQ6JEwxkJGeqJMW2tAXx+q6H+WFuUTXNdYVpEya0YA==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.22.5.tgz", + "integrity": "sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.22.5" } }, "@babel/runtime": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", - "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.6.tgz", + "integrity": "sha512-wDb5pWm4WDdF6LFUde3Jl8WzPA+3ZbxYqkC6xAXuD3irdEHN1k0NfTRrJD8ZD378SJ61miMLCqIOXYhd8x+AJQ==", "requires": { "regenerator-runtime": "^0.13.11" } }, "@babel/template": { - "version": "7.21.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", - "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.5.tgz", + "integrity": "sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==", "dev": true, "requires": { - "@babel/code-frame": "^7.21.4", - "@babel/parser": "^7.21.9", - "@babel/types": "^7.21.5" + "@babel/code-frame": "^7.22.5", + "@babel/parser": "^7.22.5", + "@babel/types": "^7.22.5" } }, "@babel/traverse": { - "version": "7.22.1", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.1.tgz", - "integrity": "sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==", + "version": "7.22.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.8.tgz", + "integrity": "sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==", "dev": true, "requires": { - "@babel/code-frame": "^7.21.4", - "@babel/generator": "^7.22.0", - "@babel/helper-environment-visitor": "^7.22.1", - "@babel/helper-function-name": "^7.21.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.22.0", - "@babel/types": "^7.22.0", + "@babel/code-frame": "^7.22.5", + "@babel/generator": "^7.22.7", + "@babel/helper-environment-visitor": "^7.22.5", + "@babel/helper-function-name": "^7.22.5", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.22.7", + "@babel/types": "^7.22.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -15376,13 +15186,13 @@ } }, "@babel/types": { - "version": "7.22.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.3.tgz", - "integrity": "sha512-P3na3xIQHTKY4L0YOG7pM8M8uoUIB910WQaSiiMCZUC2Cy8XFEQONGABFnHWBa2gpGKODTAJcNhi5Zk0sLRrzg==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.5.tgz", + "integrity": "sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.21.5", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.5", "to-fast-properties": "^2.0.0" } }, @@ -15444,14 +15254,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", - "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", + "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.2", + "espree": "^9.6.0", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -15461,15 +15271,15 @@ } }, "@eslint/js": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", - "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", + "version": "8.44.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", + "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", "dev": true }, "@godaddy/terminus": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.0.tgz", - "integrity": "sha512-zbl6gKxPAnAoAAGCyRN1kOMHTXgiW3C09w8McLKZWSSHQlsiRZlMZzBwSv1aK9PaRU25w80cnOlt3ow+uQwR1Q==", + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.1.tgz", + "integrity": "sha512-Tm+wVu1/V37uZXcT7xOhzdpFoovQReErff8x3y82k6YyWa1gzxWBjTyrx4G2enjEqoXPnUUmJ3MOmwH+TiP6Sw==", "requires": { "stoppable": "^1.1.0" } @@ -15480,9 +15290,9 @@ "integrity": "sha512-i1BpaNDVLJdRBEKeJWkVO6tYX6DMFBuwMhSuWqLsY4ufeTKGVuV5rBsUhxPayXqnnWHgXUAmWK16H/ykO5Wj4Q==" }, "@humanwhocodes/config-array": { - "version": "0.11.8", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz", - "integrity": "sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==", + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", + "integrity": "sha512-KVVjQmNUepDVGXNuoRRdmmEjruj0KfiGSbS8LVc12LMsWDQzRXJ0qdhN8L8uUigKpfEHRhlaQFY0ib1tnUbNeQ==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -15592,30 +15402,30 @@ "dev": true }, "@jest/console": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", - "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.6.1.tgz", + "integrity": "sha512-Aj772AYgwTSr5w8qnyoJ0eDYvN6bMsH3ORH1ivMotrInHLKdUz6BDlaEXHdM6kODaBIkNIyQGzsMvRdOv7VG7Q==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", - "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.6.1.tgz", + "integrity": "sha512-CcowHypRSm5oYQ1obz1wfvkjZZ2qoQlrKKvlfPwh5jUXVU12TWr2qMeH8chLMuTFzHh5a1g2yaqlqDICbr+ukQ==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/reporters": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/reporters": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", @@ -15623,93 +15433,93 @@ "exit": "^0.1.2", "graceful-fs": "^4.2.9", "jest-changed-files": "^29.5.0", - "jest-config": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", + "jest-config": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-resolve-dependencies": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", - "jest-watcher": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-resolve-dependencies": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", + "jest-watcher": "^29.6.1", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", - "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.6.1.tgz", + "integrity": "sha512-RMMXx4ws+Gbvw3DfLSuo2cfQlK7IwGbpuEWXCqyYDcqYTI+9Ju3a5hDnXaxjNsa6uKh9PQF2v+qg+RLe63tz5A==", "dev": true, "requires": { - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0" + "jest-mock": "^29.6.1" } }, "@jest/expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-N5xlPrAYaRNyFgVf2s9Uyyvr795jnB6rObuPx4QFvNJz8aAjpZUDfO4bh5G/xuplMID8PrnuF1+SfSyDxhsgYg==", "dev": true, "requires": { - "expect": "^29.5.0", - "jest-snapshot": "^29.5.0" + "expect": "^29.6.1", + "jest-snapshot": "^29.6.1" } }, "@jest/expect-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", - "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.6.1.tgz", + "integrity": "sha512-o319vIf5pEMx0LmzSxxkYYxo4wrRLKHq9dP1yJU7FoPTB0LfAKSz8SWD6D/6U3v/O52t9cF5t+MeJiRsfk7zMw==", "dev": true, "requires": { "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", - "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.6.1.tgz", + "integrity": "sha512-RdgHgbXyosCDMVYmj7lLpUwXA4c69vcNzhrt69dJJdf8azUrpRh3ckFCaTPNjsEeRi27Cig0oKDGxy5j7hOgHg==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" } }, "@jest/globals": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", - "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.6.1.tgz", + "integrity": "sha512-2VjpaGy78JY9n9370H8zGRCFbYVWwjY6RdDMhoJHa1sYfwe6XM/azGN0SjY8kk7BOZApIejQ1BFPyH7FPG0w3A==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/types": "^29.5.0", - "jest-mock": "^29.5.0" + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/types": "^29.6.1", + "jest-mock": "^29.6.1" } }, "@jest/reporters": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", - "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.6.1.tgz", + "integrity": "sha512-9zuaI9QKr9JnoZtFQlw4GREQbxgmNYXU6QuWtmuODvk5nvPUeBYapVR/VYMyi2WSx3jXTLJTJji8rN6+Cm4+FA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/console": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "@types/node": "*", "chalk": "^4.0.0", "collect-v8-coverage": "^1.0.0", @@ -15721,92 +15531,76 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", "v8-to-istanbul": "^9.0.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "@jest/schemas": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", - "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.0.tgz", + "integrity": "sha512-rxLjXyJBTL4LQeJW3aKo0M/+GkCOXsO+8i9Iu7eDb6KwtP65ayoDsitrdPBtujxQ88k4wI2FNYfa6TOGwSn6cQ==", "dev": true, "requires": { - "@sinclair/typebox": "^0.25.16" + "@sinclair/typebox": "^0.27.8" } }, "@jest/source-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.4.3.tgz", - "integrity": "sha512-qyt/mb6rLyd9j1jUts4EQncvS6Yy3PM9HghnNv86QBlV+zdL2inCdK1tuVlL+J+lpiw2BI67qXOrX3UurBqQ1w==", + "version": "29.6.0", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.0.tgz", + "integrity": "sha512-oA+I2SHHQGxDCZpbrsCQSoMLb3Bz547JnM+jUr9qEbuw0vQlWZfpPS7CO9J7XiwKicEz9OFn/IYoLkkiUD7bzA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.15", + "@jridgewell/trace-mapping": "^0.3.18", "callsites": "^3.0.0", "graceful-fs": "^4.2.9" } }, "@jest/test-result": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", - "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.6.1.tgz", + "integrity": "sha512-Ynr13ZRcpX6INak0TPUukU8GWRfm/vAytE3JbJNGAvINySWYdfE7dGZMbk36oVuK4CigpbhMn8eg1dixZ7ZJOw==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/types": "^29.6.1", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", - "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.6.1.tgz", + "integrity": "sha512-oBkC36PCDf/wb6dWeQIhaviU0l5u6VCsXa119yqdUosYAt7/FbQU2M2UoziO3igj/HBDEgp57ONQ3fm0v9uyyg==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", + "@jest/test-result": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", - "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.1.tgz", + "integrity": "sha512-URnTneIU3ZjRSaf906cvf6Hpox3hIeJXRnz3VDSw5/X93gR8ycdfSIEy19FlVx8NFmpN7fe3Gb1xF+NjXaQLWg==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.5.0", - "@jridgewell/trace-mapping": "^0.3.15", + "@jest/types": "^29.6.1", + "@jridgewell/trace-mapping": "^0.3.18", "babel-plugin-istanbul": "^6.1.1", "chalk": "^4.0.0", "convert-source-map": "^2.0.0", "fast-json-stable-stringify": "^2.1.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -15814,12 +15608,12 @@ } }, "@jest/types": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", - "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz", + "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -15880,9 +15674,9 @@ "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" }, "@mapbox/node-pre-gyp": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.10.tgz", - "integrity": "sha512-4ySo4CjzStuprMwk35H5pPbkymjv1SF3jGLj6rAHp/xT/RF7TL7bd9CTm1xDY49K2qF7jmR/g7k+SkLETP6opA==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", "requires": { "detect-libc": "^2.0.0", "https-proxy-agent": "^5.0.0", @@ -15984,6 +15778,37 @@ "integrity": "sha512-Mu3yELySvzhBcNTVCq+hYxVh+lH3/KjoQ5HIEb3DDPoX0AGRTm3XZa+usq8pFWjl91Cgp9nWK+9lVSkCCIRaKA==", "optional": true }, + "@node-saml/node-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/node-saml/-/node-saml-4.0.4.tgz", + "integrity": "sha512-oybUBWBYVsHGckQxzyzlpRM4E2iuW3I2Ok/J9SwlotdmjvmZxSo6Ub74D9wltG8C9daJZYI57uy+1UK4FtcGXA==", + "requires": { + "@types/debug": "^4.1.7", + "@types/passport": "^1.0.11", + "@types/xml-crypto": "^1.4.2", + "@types/xml-encryption": "^1.2.1", + "@types/xml2js": "^0.4.11", + "@xmldom/xmldom": "^0.8.6", + "debug": "^4.3.4", + "xml-crypto": "^3.0.1", + "xml-encryption": "^3.0.2", + "xml2js": "^0.5.0", + "xmlbuilder": "^15.1.1" + } + }, + "@node-saml/passport-saml": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@node-saml/passport-saml/-/passport-saml-4.0.4.tgz", + "integrity": "sha512-xFw3gw0yo+K1mzlkW15NeBF7cVpRHN/4vpjmBKzov5YFImCWh/G0LcTZ8krH3yk2/eRPc3Or8LRPudVJBjmYaw==", + "requires": { + "@node-saml/node-saml": "^4.0.4", + "@types/express": "^4.17.14", + "@types/passport": "^1.0.11", + "@types/passport-strategy": "^0.2.35", + "passport": "^0.6.0", + "passport-strategy": "^1.0.0" + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -16072,12 +15897,9 @@ } }, "@octokit/auth-token": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.3.tgz", - "integrity": "sha512-/aFM2M4HVDBT/jjDBa84sJniv1t9Gm/rLkalaz9htOm+L+8JMj1k9w0CkUdcxNyNxZPlTxKPVko+m1VlM58ZVA==", - "requires": { - "@octokit/types": "^9.0.0" - } + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-3.0.4.tgz", + "integrity": "sha512-TWFX7cZF2LXoCvdmJWY7XVPi74aSY0+FfBZNSXEXFkMpjcqsQwDSYVv5FhRFaI0V1ECnwbz4j59T/G+rXNWaIQ==" }, "@octokit/auth-unauthenticated": { "version": "3.0.5", @@ -16089,9 +15911,9 @@ } }, "@octokit/core": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", - "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.4.tgz", + "integrity": "sha512-rYKilwgzQ7/imScn3M9/pFfUf4I1AZEH3KhyJmtPdE2zfaXAn2mFfUy4FbKewzc2We5y/LlKLj36fWJLKC2SIQ==", "requires": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -16103,9 +15925,9 @@ } }, "@octokit/endpoint": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.5.tgz", - "integrity": "sha512-LG4o4HMY1Xoaec87IqQ41TQ+glvIeTKqfjkCEmt5AIwDZJwQeVZFIEYXrYY6yLwK+pAScb9Gj4q+Nz2qSw1roA==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-7.0.6.tgz", + "integrity": "sha512-5L4fseVRUsDFGR00tMWD/Trdeeihn999rTMGRMC1G/Ldi1uWlWJzI98H4Iak5DB/RVvQuyMYKqSK/R6mbSOQyg==", "requires": { "@octokit/types": "^9.0.0", "is-plain-object": "^5.0.0", @@ -16140,9 +15962,9 @@ } }, "@octokit/openapi-types": { - "version": "17.2.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", - "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-18.0.0.tgz", + "integrity": "sha512-V8GImKs3TeQRxRtXFpG2wl19V7444NIOTDF24AWuIbmNaNYOQMWRbjcGDXV5B+0n887fgDcuMNOmlul+k+oJtw==" }, "@octokit/plugin-enterprise-compatibility": { "version": "1.3.0", @@ -16194,12 +16016,21 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.1.2.tgz", - "integrity": "sha512-R0oJ7j6f/AdqPLtB9qRXLO+wjI9pctUn8Ka8UGfGaFCcCv3Otx14CshQ89K4E88pmyYZS8p0rNTiprML/81jig==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.2.3.tgz", + "integrity": "sha512-I5Gml6kTAkzVlN7KCtjOM+Ruwe/rQppp0QU372K1GP7kNOYEKe8Xn5BW4sE62JAHdwpq95OQK/qGNyKQMUzVgA==", "requires": { - "@octokit/types": "^9.2.3", - "deprecation": "^2.3.1" + "@octokit/types": "^10.0.0" + }, + "dependencies": { + "@octokit/types": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-10.0.0.tgz", + "integrity": "sha512-Vm8IddVmhCgU1fxC1eyinpwqzXPEYu0NrYzD3YZjlGjyftdLBTeqNblRC0jmJmgxbJIsQlyogVeGnrNaaMVzIg==", + "requires": { + "@octokit/openapi-types": "^18.0.0" + } + } } }, "@octokit/plugin-retry": { @@ -16227,9 +16058,9 @@ } }, "@octokit/request": { - "version": "6.2.5", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", - "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.8.tgz", + "integrity": "sha512-ow4+pkVQ+6XVVsekSYBzJC0VTVvh/FCTUUgTsboGq+DTeWdyIFV8WSCdo0RIxk6wSkBTHqIK1mYuY7nOBXOchw==", "requires": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -16250,9 +16081,9 @@ } }, "@octokit/rest": { - "version": "19.0.11", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", - "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", + "version": "19.0.13", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.13.tgz", + "integrity": "sha512-/EzVox5V9gYGdbAI+ovYj3nXQT1TtTHRT+0eZPcuC05UFSWO3mdO9UY1C0i2eLF9Un1ONJkAk+IEtYGAC+TahA==", "requires": { "@octokit/core": "^4.2.1", "@octokit/plugin-paginate-rest": "^6.1.2", @@ -16266,11 +16097,11 @@ "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" }, "@octokit/types": { - "version": "9.2.3", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", - "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.3.2.tgz", + "integrity": "sha512-D4iHGTdAnEEVsB8fl95m1hiz7D5YiRdQ9b/OEb3BYRVwbLsGHcRVPz+u+BgRLNk0Q0/4iZCBqDN96j2XNxfXrA==", "requires": { - "@octokit/openapi-types": "^17.2.0" + "@octokit/openapi-types": "^18.0.0" } }, "@octokit/webhooks": { @@ -16404,45 +16235,6 @@ "tslib": "^1.9.3" } }, - "colorette": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", - "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" - }, - "jmespath": { - "version": "0.15.0", - "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", - "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==" - }, - "pino-pretty": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", - "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", - "requires": { - "@hapi/bourne": "^2.0.0", - "args": "^5.0.1", - "colorette": "^1.3.0", - "dateformat": "^4.5.1", - "fast-safe-stringify": "^2.0.7", - "jmespath": "^0.15.0", - "joycon": "^3.0.0", - "pump": "^3.0.0", - "readable-stream": "^3.6.0", - "rfdc": "^1.3.0", - "split2": "^3.1.1", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "split2": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", - "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", - "requires": { - "readable-stream": "^3.0.0" - } - } - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -16505,38 +16297,24 @@ "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, "@sentry-internal/tracing": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.53.1.tgz", - "integrity": "sha512-a4H4rvVdz0XDGgNfRqc7zg6rMt2P1P05xBmgfIfztYy94Vciw1QMdboNiT7einr8ra8wogdEaK4Pe2AzYAPBJQ==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.59.3.tgz", + "integrity": "sha512-/RkBj/0zQKGsW/UYg6hufrLHHguncLfu4610FCPWpVp0K5Yu5ou8/Aw8D76G3ZxD2TiuSNGwX0o7TYN371ZqTQ==", "requires": { - "@sentry/core": "7.53.1", - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "@sentry/core": "7.59.3", + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" } }, "@sentry/core": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.53.1.tgz", - "integrity": "sha512-DAH8IJNORJJ7kQLqsZuhMkN6cwJjXzFuuUoZor7IIDHIHjtl51W+2F3Stg3+I3ZoKDfJfUNKqhipk2WZjG0FBg==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.59.3.tgz", + "integrity": "sha512-cGBOwT9gziIn50fnlBH1WGQlGcHi7wrbvOCyrex4MxKnn1LSBYWBhwU0ymj8DI/9MyPrGDNGkrgpV0WJWBSClg==", "requires": { - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" } }, "@sentry/hub": { @@ -16593,60 +16371,46 @@ } }, "@sentry/node": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.53.1.tgz", - "integrity": "sha512-B4ax8sRd54xj4ad+4eY2EOKNt0Mh1NjuLW1zUKS8HW3h0bmuaDFzGuhEVvEY5H4SaV6tZKj1c0dvnMnyUbYkhA==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.59.3.tgz", + "integrity": "sha512-5dG90YzmKjuy5TK04qDuc9LBxnGfqsZw8Oh9giwOBfQVCaFp7R14AXyQ1F8k3iUF+4sGeTvoqi9I/GKAItVmlA==", "requires": { - "@sentry-internal/tracing": "7.53.1", - "@sentry/core": "7.53.1", - "@sentry/types": "7.53.1", - "@sentry/utils": "7.53.1", + "@sentry-internal/tracing": "7.59.3", + "@sentry/core": "7.59.3", + "@sentry/types": "7.59.3", + "@sentry/utils": "7.59.3", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "tslib": "^2.4.1 || ^1.9.3" } }, "@sentry/tracing": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.53.1.tgz", - "integrity": "sha512-1lpys/e19ee2gDTkcgIXyFNJySEqxdIxlu3Q1Oj+V0ORXVBfA9kFap2fHPWASaDJvmy1zpgGKlbzCpr+IEyfYQ==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.59.3.tgz", + "integrity": "sha512-+gDsfhYdteAR4NyKl3B5JVQs/bXYT73ajoFrlprfDjAJCEVR9W1P4CULavoLtfASxVqBQcZyT87Hsb9/vbn6bg==", "requires": { - "@sentry-internal/tracing": "7.53.1" + "@sentry-internal/tracing": "7.59.3" } }, "@sentry/types": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.53.1.tgz", - "integrity": "sha512-/ijchRIu+jz3+j/zY+7KRPfLSCY14fTx5xujjbOdmEKjmIHQmwPBdszcQm40uwofrR8taV4hbt5MFN+WnjCkCw==" + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.59.3.tgz", + "integrity": "sha512-HQ/Pd3YHyIa4HM0bGfOsfI4ZF+sLVs6II9VtlS4hsVporm4ETl3Obld5HywO3aVYvWOk5j/bpAW9JYsxXjRG5A==" }, "@sentry/utils": { - "version": "7.53.1", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.53.1.tgz", - "integrity": "sha512-DKJA1LSUOEv4KOR828MzVuLh+drjeAgzyKgN063OEKmnirgjgRgNNS8wUgwpG0Tn2k6ANZGCwrdfzPeSBxshKg==", + "version": "7.59.3", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.59.3.tgz", + "integrity": "sha512-Q57xauMKuzd6S+POA1fmulfjzTsb/z118TNAfZZNkHqVB48hHBqgzdhbEBmN4jPCSKV2Cx7VJUoDZxJfzQyLUQ==", "requires": { - "@sentry/types": "7.53.1", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } + "@sentry/types": "7.59.3", + "tslib": "^2.4.1 || ^1.9.3" } }, "@sinclair/typebox": { - "version": "0.25.24", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", - "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, "@sinonjs/commons": { @@ -16659,9 +16423,9 @@ } }, "@sinonjs/fake-timers": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", - "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "requires": { "@sinonjs/commons": "^3.0.0" @@ -17101,9 +16865,9 @@ } }, "@types/babel__traverse": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.0.tgz", - "integrity": "sha512-TBOjqAGf0hmaqRwpii5LLkJLg7c6OMm4nHLmpsUxwk9bBHtoTC6dAHdVWdGv4TBxj2CZOZY8Xfq8WmfoVi7n4Q==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz", + "integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==", "dev": true, "requires": { "@babel/types": "^7.20.7" @@ -17175,6 +16939,14 @@ "resolved": "https://registry.npmjs.org/@types/crypto-js/-/crypto-js-4.1.1.tgz", "integrity": "sha512-BG7fQKZ689HIoc5h+6D2Dgq1fABRa0RbBWKBd9SP/MVRVXROflpm5fhwyATX5duFmbStzyzyycPB8qUYKDH3NA==" }, + "@types/debug": { + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", + "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "requires": { + "@types/ms": "*" + } + }, "@types/express": { "version": "4.17.17", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", @@ -17206,6 +16978,11 @@ "@types/node": "*" } }, + "@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + }, "@types/ioredis": { "version": "4.28.10", "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.28.10.tgz", @@ -17244,9 +17021,9 @@ } }, "@types/jest": { - "version": "29.5.1", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", - "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", + "version": "29.5.3", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.3.tgz", + "integrity": "sha512-1Nq7YrO/vJE/FYnqYyw0FS8LdrjExSgIiHyKg7xPpn+yi8Q4huZryKnkJatN1ZRH89Kw2v33/8ZMB7DuZeSLlA==", "dev": true, "requires": { "expect": "^29.0.0", @@ -17294,10 +17071,15 @@ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" }, + "@types/ms": { + "version": "0.7.31", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", + "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + }, "@types/node": { - "version": "18.16.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", - "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==" + "version": "18.16.19", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz", + "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" }, "@types/nodemailer": { "version": "6.4.8", @@ -17312,11 +17094,19 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/@types/passport/-/passport-1.0.12.tgz", "integrity": "sha512-QFdJ2TiAEoXfEQSNDISJR1Tm51I78CymqcBa8imbjo6dNNu+l2huDxxbDEIoFIwOSKMkOfHEikyDuZ38WwWsmw==", - "dev": true, "requires": { "@types/express": "*" } }, + "@types/passport-strategy": { + "version": "0.2.35", + "resolved": "https://registry.npmjs.org/@types/passport-strategy/-/passport-strategy-0.2.35.tgz", + "integrity": "sha512-o5D19Jy2XPFoX2rKApykY15et3Apgax00RRLf0RUotPDUsYrQa7x4howLYr9El2mlUApHmCMv5CZ1IXqKFQ2+g==", + "requires": { + "@types/express": "*", + "@types/passport": "*" + } + }, "@types/picomatch": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.0.tgz", @@ -17359,9 +17149,9 @@ } }, "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", "dev": true }, "@types/qs": { @@ -17390,10 +17180,11 @@ } }, "@types/serve-static": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", - "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", "requires": { + "@types/http-errors": "*", "@types/mime": "*", "@types/node": "*" } @@ -17458,6 +17249,31 @@ "@types/webidl-conversions": "*" } }, + "@types/xml-crypto": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@types/xml-crypto/-/xml-crypto-1.4.2.tgz", + "integrity": "sha512-1kT+3gVkeBDg7Ih8NefxGYfCApwZViMIs5IEs5AXF6Fpsrnf9CLAEIRh0DYb1mIcRcvysVbe27cHsJD6rJi36w==", + "requires": { + "@types/node": "*", + "xpath": "0.0.27" + } + }, + "@types/xml-encryption": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@types/xml-encryption/-/xml-encryption-1.2.1.tgz", + "integrity": "sha512-UeyZkfZFZSa9XCGU5uGgUmsSLwQESDJvF076bJGyDf2gkXJjKvK8fW/x4ckvEHB2M/5RHJEkMc5xI+JrdmCTKA==", + "requires": { + "@types/node": "*" + } + }, + "@types/xml2js": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/@types/xml2js/-/xml2js-0.4.11.tgz", + "integrity": "sha512-JdigeAKmCyoJUiQljjr7tQG3if9NkqGUgwEUqBvV0N7LM4HyQk7UXCnusRa1lnvXAEYJ8mw8GtZWioagNztOwA==", + "requires": { + "@types/node": "*" + } + }, "@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -17474,17 +17290,17 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", - "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/type-utils": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", "semver": "^7.3.7", @@ -17492,53 +17308,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", - "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", - "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7" + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" } }, "@typescript-eslint/type-utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.7.tgz", - "integrity": "sha512-ozuz/GILuYG7osdY5O5yg0QxXUAEoI4Go3Do5xeu+ERH9PorHBPSdvD3Tjp2NN2bNLh1NJQSsQu2TPu/Ly+HaQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.7", - "@typescript-eslint/utils": "5.59.7", + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", - "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", - "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/visitor-keys": "5.59.7", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -17547,44 +17363,41 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", - "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.7", - "@typescript-eslint/types": "5.59.7", - "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.7", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.7.tgz", - "integrity": "sha512-tyN+X2jvMslUszIiYbF0ZleP+RqQsFVpGrKI6e0Eet1w8WmhsAtmzaqm8oM8WJQ1ysLwhnsK/4hYHJjOgJVfQQ==", + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/types": "5.62.0", "eslint-visitor-keys": "^3.3.0" } }, + "@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==" + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "requires": { - "event-target-shim": "^5.0.0" - } - }, "accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", @@ -17595,9 +17408,9 @@ } }, "acorn": { - "version": "8.8.2", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", - "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", + "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", "dev": true }, "acorn-jsx": { @@ -17839,9 +17652,9 @@ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==" }, "aws-sdk": { - "version": "2.1386.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1386.0.tgz", - "integrity": "sha512-bmUvpNRR4x1YvTaAm7WK/2lSNVPrNuiYlleU47GA5Xskh8PKaWedGHvGinH2YwhC720hM0Qc4f4/snUPGJ0eYg==", + "version": "2.1419.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1419.0.tgz", + "integrity": "sha512-JcD8gb8I5fH/TGdObG8UYyyXfnqVYk50wx9TGao6G/xBYT3YoYeQXj020W568YQpO+dBKRuR4U2LRYdKBNmQ/g==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -17873,21 +17686,21 @@ } }, "axios-retry": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.0.tgz", - "integrity": "sha512-g48qNrLX30VU6ECWltpFCPegKK6dWzMDYv2o83W2zUL/Zh/SLXbT6ksGoKqYZHtghzqeeXhZBcSXJkO1fPbCcw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.1.tgz", + "integrity": "sha512-mQRJ4IyAUnYig14BQ4MnnNHHuH1cNH7NW4JxEUD6mNJwK6pwOY66wKLCwZ6Y0o3POpfStalqRC+J4+Hnn6Om7w==", "requires": { "@babel/runtime": "^7.15.4", "is-retry-allowed": "^2.2.0" } }, "babel-jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", - "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.1.tgz", + "integrity": "sha512-qu+3bdPEQC6KZSPz+4Fyjbga5OODNcp49j6GKzG1EKbkfyJBxEYGVUmVGpwCSeGouG52R4EgYMLb6p9YeEEQ4A==", "dev": true, "requires": { - "@jest/transform": "^29.5.0", + "@jest/transform": "^29.6.1", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", "babel-preset-jest": "^29.5.0", @@ -18112,13 +17925,13 @@ } }, "browserslist": { - "version": "4.21.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.6.tgz", - "integrity": "sha512-PF07dKGXKR+/bljJzCB6rAYtHEu21TthLxmJagtQizx+rwiqdRDBO5971Xu1N7MgcMLi4+mr4Cnl76x7O3DHtA==", + "version": "4.21.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.9.tgz", + "integrity": "sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001489", - "electron-to-chromium": "^1.4.411", + "caniuse-lite": "^1.0.30001503", + "electron-to-chromium": "^1.4.431", "node-releases": "^2.0.12", "update-browserslist-db": "^1.0.11" } @@ -18230,9 +18043,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001489", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", - "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", + "version": "1.0.30001517", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001517.tgz", + "integrity": "sha512-Vdhm5S11DaFVLlyiKu4hiUTkpZu+y1KA/rZZqVQfOD5YdDT/eQKlkt7NaE0WGOFgX32diqt9MiP9CAiFeRklaA==", "dev": true }, "chalk": { @@ -18299,9 +18112,9 @@ } }, "cjs-module-lexer": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.2.tgz", - "integrity": "sha512-cOU9usZw8/dXIXKtwa8pM0OTJQuJkxMN6w30csNRUerHfeQ5R6U3kkU/FtJeIf3M202OHfY2U8ccInBG7/xogA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", + "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==", "dev": true }, "clean-stack": { @@ -18337,9 +18150,9 @@ "dev": true }, "collect-v8-coverage": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz", - "integrity": "sha512-iBPtljfCNcTKNAto0KEtDfZ3qzjJvqE3aTGZsbhjSBlorqpXJlaWWtPO35D+ZImoC3KWejX64o+yPGxhWSTzfg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", "dev": true }, "color": { @@ -18395,9 +18208,9 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" }, "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==" }, "colorspace": { "version": "1.1.4", @@ -18611,9 +18424,9 @@ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, "detect-libc": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz", - "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" }, "detect-newline": { "version": "3.1.0", @@ -18662,9 +18475,9 @@ } }, "dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==" }, "ecdsa-sig-formatter": { "version": "1.0.11", @@ -18680,9 +18493,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.411", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.411.tgz", - "integrity": "sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==", + "version": "1.4.467", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.467.tgz", + "integrity": "sha512-2qI70O+rR4poYeF2grcuS/bCps5KJh6y1jtZMDDEteyKJQrzLOEhFyXCLcHW6DTBjKjWkk26JhWoAi+Ux9A0fg==", "dev": true }, "emittery": { @@ -18740,16 +18553,16 @@ "dev": true }, "eslint": { - "version": "8.41.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", - "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", + "version": "8.45.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", + "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.3", - "@eslint/js": "8.41.0", - "@humanwhocodes/config-array": "^0.11.8", + "@eslint/eslintrc": "^2.1.0", + "@eslint/js": "8.44.0", + "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", "ajv": "^6.10.0", @@ -18760,7 +18573,7 @@ "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", "eslint-visitor-keys": "^3.4.1", - "espree": "^9.5.2", + "espree": "^9.6.0", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -18770,7 +18583,6 @@ "globals": "^13.19.0", "graphemer": "^1.4.0", "ignore": "^5.2.0", - "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", @@ -18780,16 +18592,15 @@ "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.1", + "optionator": "^0.9.3", "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.1.tgz", + "integrity": "sha512-CvefSOsDdaYYvxChovdrPo/ZGt8d5lrJWleAc1diXRKhHGiTYEI26cvo8Kle/wGnsizoCJjK73FMg1/IkIwiNA==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -18836,12 +18647,12 @@ "dev": true }, "espree": { - "version": "9.5.2", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", - "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, "requires": { - "acorn": "^8.8.0", + "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } @@ -18902,11 +18713,6 @@ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==" }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" - }, "events": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", @@ -18941,16 +18747,17 @@ "dev": true }, "expect": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", - "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.6.1.tgz", + "integrity": "sha512-XEdDLonERCU1n9uR56/Stx9OqojaLAQtZf9PrCHH9Hl8YXiEIka3H4NXJ3NOIBmQJTg7+j7buh34PMHfJujc8g==", "dev": true, "requires": { - "@jest/expect-utils": "^29.5.0", + "@jest/expect-utils": "^29.6.1", + "@types/node": "*", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0" + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1" } }, "express": { @@ -19025,12 +18832,42 @@ "glob": "^8.1.0", "graceful-fs": "^4.2.10", "handlebars": "^4.7.7" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "requires": { + "balanced-match": "^1.0.0" + } + }, + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "express-rate-limit": { - "version": "6.7.0", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz", - "integrity": "sha512-vhwIdRoqcYB/72TK3tRZI+0ttS8Ytrk24GfmsxDXK9o9IhHNO5bXRiXQSExPQ4GbaE5tvIS7j1SGrxsuWs+sGA==", + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.8.0.tgz", + "integrity": "sha512-yVeDWczkh8qgo9INJB1tT4j7LFu+n6ei/oqSMsqpsUIGYjTM+gk+Q3wv19TMUdo8chvus8XohAuOhG7RYRM9ZQ==", "requires": {} }, "express-validator": { @@ -19048,11 +18885,6 @@ "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", "dev": true }, - "fast-copy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.1.tgz", - "integrity": "sha512-Knr7NOtK3HWRYGtHoJrjkaWepqT8thIVGAwt0p0aUs1zqkAzXZV4vo9fFNwyb5fcqK1GKYFYxldQdIDVKhUAfA==" - }, "fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -19060,9 +18892,9 @@ "dev": true }, "fast-glob": { - "version": "3.2.12", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", - "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", + "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", @@ -19111,13 +18943,6 @@ "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "requires": { "punycode": "^1.3.2" - }, - "dependencies": { - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" - } } }, "fast-xml-parser": { @@ -19376,33 +19201,16 @@ "dev": true }, "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "requires": { - "brace-expansion": "^2.0.1" - } - } + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-parent": { @@ -19458,12 +19266,6 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==" }, - "grapheme-splitter": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz", - "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", - "dev": true - }, "graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -19534,15 +19336,6 @@ "resolved": "https://registry.npmjs.org/helmet/-/helmet-5.1.1.tgz", "integrity": "sha512-/yX0oVZBggA9cLJh8aw3PPCfedBnbd7J2aowjzsaWwZh7/UFY0nccn/aHAggIgWUFfnykX8GKd3a1pSbrmlcVQ==" }, - "help-me": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-4.2.0.tgz", - "integrity": "sha512-TAOnTB8Tz5Dw8penUuzHVrKNKlCIbwwbHnXraNJxPwf8LRtE2HlM84RYuezMFcwOJmoYOCWVDyJ8TQGxn9PgxA==", - "requires": { - "glob": "^8.0.0", - "readable-stream": "^3.6.0" - } - }, "hexoid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/hexoid/-/hexoid-1.0.0.tgz", @@ -19639,9 +19432,9 @@ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" }, "infisical-node": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", - "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.3.2.tgz", + "integrity": "sha512-o1rxfOBAmpTiipka9Xnfa2AgTS8CkJHo0aRQwk6UGi+yEkKzXS7dDM7bZD56M/z+yKGLK15QkfFGZXp1VomlHw==", "requires": { "axios": "^1.3.3", "dotenv": "^16.0.3", @@ -19810,15 +19603,11 @@ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" }, "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.11" } }, "isarray": { @@ -19892,15 +19681,15 @@ } }, "jest": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", - "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.1.tgz", + "integrity": "sha512-Nirw5B4nn69rVUZtemCQhwxOBhm0nsp3hmtF4rzCeWD7BkjAXRIji7xWQfnTNbz9g0aVsBX6aZK3n+23LM6uDw==", "dev": true, "requires": { - "@jest/core": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/types": "^29.6.1", "import-local": "^3.0.2", - "jest-cli": "^29.5.0" + "jest-cli": "^29.6.1" } }, "jest-changed-files": { @@ -19914,109 +19703,93 @@ } }, "jest-circus": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", - "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.6.1.tgz", + "integrity": "sha512-tPbYLEiBU4MYAL2XoZme/bgfUeotpDBd81lgHLCbDZZFaGmECk0b+/xejPFtmiBP87GgP/y4jplcRpbH+fgCzQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/expect": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/expect": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.5.0", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-each": "^29.6.1", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "p-limit": "^3.1.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", - "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.6.1.tgz", + "integrity": "sha512-607dSgTA4ODIN6go9w6xY3EYkyPFGicx51a69H7yfvt7lN53xNswEVLovq+E77VsTRi5fWprLH0yl4DJgE8Ing==", "dev": true, "requires": { - "@jest/core": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/core": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-config": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", - "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.6.1.tgz", + "integrity": "sha512-XdjYV2fy2xYixUiV2Wc54t3Z4oxYPAELUzWnV6+mcbq0rh742X2p52pii5A3oeRzYjLnQxCsZmp0qpI6klE2cQ==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.5.0", - "@jest/types": "^29.5.0", - "babel-jest": "^29.5.0", + "@jest/test-sequencer": "^29.6.1", + "@jest/types": "^29.6.1", + "babel-jest": "^29.6.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "deepmerge": "^4.2.2", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-circus": "^29.5.0", - "jest-environment-node": "^29.5.0", + "jest-circus": "^29.6.1", + "jest-environment-node": "^29.6.1", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-runner": "^29.5.0", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-runner": "^29.6.1", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "jest-diff": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", - "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.6.1.tgz", + "integrity": "sha512-FsNCvinvl8oVxpNLttNQX7FAq7vR+gMDGj90tiP7siWw1UdakWUGqrylpsYrpvj908IYckm5Y0Q7azNAozU1Kg==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-docblock": { @@ -20029,30 +19802,30 @@ } }, "jest-each": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.5.0.tgz", - "integrity": "sha512-HM5kIJ1BTnVt+DQZ2ALp3rzXEl+g726csObrW/jpEGl+CDSSQpOJJX2KE/vEg8cxcMXdyEPu6U4QX5eruQv5hA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.6.1.tgz", + "integrity": "sha512-n5eoj5eiTHpKQCAVcNTT7DRqeUmJ01hsAL0Q1SMiBHcBcvTKDELixQOGMCpqhbIuTcfC4kMfSnpmDqRgRJcLNQ==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.5.0", - "pretty-format": "^29.5.0" + "jest-util": "^29.6.1", + "pretty-format": "^29.6.1" } }, "jest-environment-node": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.5.0.tgz", - "integrity": "sha512-ExxuIK/+yQ+6PRGaHkKewYtg6hto2uGCgvKdb2nfJfKXgZ17DfXjvbZ+jA1Qt9A8EQSfPnt5FKIfnOO3u1h9qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.6.1.tgz", + "integrity": "sha512-ZNIfAiE+foBog24W+2caIldl4Irh8Lx1PUhg/GZ0odM1d/h2qORAsejiFc7zb+SEmYPn1yDZzEDSU5PmDkmVLQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-mock": "^29.5.0", - "jest-util": "^29.5.0" + "jest-mock": "^29.6.1", + "jest-util": "^29.6.1" } }, "jest-get-type": { @@ -20062,12 +19835,12 @@ "dev": true }, "jest-haste-map": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.5.0.tgz", - "integrity": "sha512-IspOPnnBro8YfVYSw6yDRKh/TiCdRngjxeacCps1cQ9cgVN6+10JUcuJ1EabrgYLOATsIAigxA0rLR9x/YlrSA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.1.tgz", + "integrity": "sha512-0m7f9PZXxOCk1gRACiVgX85knUKPKLPg4oRCjLoqIm9brTHXaorMA0JpmtmVkQiT8nmXyIVoZd/nnH1cfC33ig==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", @@ -20075,8 +19848,8 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-util": "^29.6.1", + "jest-worker": "^29.6.1", "micromatch": "^4.0.4", "walker": "^1.0.8" } @@ -20094,53 +19867,53 @@ } }, "jest-leak-detector": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", - "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.6.1.tgz", + "integrity": "sha512-OrxMNyZirpOEwkF3UHnIkAiZbtkBWiye+hhBweCHkVbCgyEy71Mwbb5zgeTNYWJBi1qgDVfPC1IwO9dVEeTLwQ==", "dev": true, "requires": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-matcher-utils": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.5.0.tgz", - "integrity": "sha512-lecRtgm/rjIK0CQ7LPQwzCs2VwW6WAahA55YBuI+xqmhm7LAaxokSB8C97yJeYyT+HvQkH741StzpU41wohhWw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.6.1.tgz", + "integrity": "sha512-SLaztw9d2mfQQKHmJXKM0HCbl2PPVld/t9Xa6P9sgiExijviSp7TnZZpw2Fpt+OI3nwUO/slJbOfzfUMKKC5QA==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-message-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", - "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.6.1.tgz", + "integrity": "sha512-KoAW2zAmNSd3Gk88uJ56qXUWbFk787QKmjjJVOjtGFmmGSZgDBrlIL4AfQw1xyMYPNVD7dNInfIbur9B2rd/wQ==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.5.0", + "pretty-format": "^29.6.1", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", - "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.6.1.tgz", + "integrity": "sha512-brovyV9HBkjXAEdRooaTQK42n8usKoSRR3gihzUpYeV/vwqgSoNfrksO7UfSACnPmxasO/8TmHM3w9Hp3G1dgw==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", - "jest-util": "^29.5.0" + "jest-util": "^29.6.1" } }, "jest-pnp-resolver": { @@ -20157,145 +19930,127 @@ "dev": true }, "jest-resolve": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.5.0.tgz", - "integrity": "sha512-1TzxJ37FQq7J10jPtQjcc+MkCkE3GBpBecsSUWJ0qZNJpmg6m0D9/7II03yJulm3H/fvVjgqLh/k2eYg+ui52w==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.6.1.tgz", + "integrity": "sha512-AeRkyS8g37UyJiP9w3mmI/VXU/q8l/IH52vj/cDAyScDcemRbSBhfX/NMYIGilQgSVwsjxrCHf3XJu4f+lxCMg==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", + "jest-haste-map": "^29.6.1", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.5.0", - "jest-validate": "^29.5.0", + "jest-util": "^29.6.1", + "jest-validate": "^29.6.1", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", - "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.6.1.tgz", + "integrity": "sha512-BbFvxLXtcldaFOhNMXmHRWx1nXQO5LoXiKSGQcA1LxxirYceZT6ch8KTE1bK3X31TNG/JbkI7OkS/ABexVahiw==", "dev": true, "requires": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.5.0" + "jest-snapshot": "^29.6.1" } }, "jest-runner": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", - "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.6.1.tgz", + "integrity": "sha512-tw0wb2Q9yhjAQ2w8rHRDxteryyIck7gIzQE4Reu3JuOBpGp96xWgF0nY8MDdejzrLCZKDcp8JlZrBN/EtkQvPQ==", "dev": true, "requires": { - "@jest/console": "^29.5.0", - "@jest/environment": "^29.5.0", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/console": "^29.6.1", + "@jest/environment": "^29.6.1", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.5.0", - "jest-haste-map": "^29.5.0", - "jest-leak-detector": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-resolve": "^29.5.0", - "jest-runtime": "^29.5.0", - "jest-util": "^29.5.0", - "jest-watcher": "^29.5.0", - "jest-worker": "^29.5.0", + "jest-environment-node": "^29.6.1", + "jest-haste-map": "^29.6.1", + "jest-leak-detector": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-resolve": "^29.6.1", + "jest-runtime": "^29.6.1", + "jest-util": "^29.6.1", + "jest-watcher": "^29.6.1", + "jest-worker": "^29.6.1", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", - "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.6.1.tgz", + "integrity": "sha512-D6/AYOA+Lhs5e5il8+5pSLemjtJezUr+8zx+Sn8xlmOux3XOqx4d8l/2udBea8CRPqqrzhsKUsN/gBDE/IcaPQ==", "dev": true, "requires": { - "@jest/environment": "^29.5.0", - "@jest/fake-timers": "^29.5.0", - "@jest/globals": "^29.5.0", - "@jest/source-map": "^29.4.3", - "@jest/test-result": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/environment": "^29.6.1", + "@jest/fake-timers": "^29.6.1", + "@jest/globals": "^29.6.1", + "@jest/source-map": "^29.6.0", + "@jest/test-result": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "cjs-module-lexer": "^1.0.0", "collect-v8-coverage": "^1.0.0", "glob": "^7.1.3", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-mock": "^29.5.0", + "jest-haste-map": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-mock": "^29.6.1", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.5.0", - "jest-snapshot": "^29.5.0", - "jest-util": "^29.5.0", + "jest-resolve": "^29.6.1", + "jest-snapshot": "^29.6.1", + "jest-util": "^29.6.1", "slash": "^3.0.0", "strip-bom": "^4.0.0" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "jest-snapshot": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", - "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.6.1.tgz", + "integrity": "sha512-G4UQE1QQ6OaCgfY+A0uR1W2AY0tGXUPQpoUClhWHq1Xdnx1H6JOrC2nH5lqnOEqaDgbHFgIwZ7bNq24HpB180A==", "dev": true, "requires": { "@babel/core": "^7.11.6", "@babel/generator": "^7.7.2", "@babel/plugin-syntax-jsx": "^7.7.2", "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.5.0", - "@jest/transform": "^29.5.0", - "@jest/types": "^29.5.0", - "@types/babel__traverse": "^7.0.6", + "@jest/expect-utils": "^29.6.1", + "@jest/transform": "^29.6.1", + "@jest/types": "^29.6.1", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.5.0", + "expect": "^29.6.1", "graceful-fs": "^4.2.9", - "jest-diff": "^29.5.0", + "jest-diff": "^29.6.1", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.5.0", - "jest-message-util": "^29.5.0", - "jest-util": "^29.5.0", + "jest-matcher-utils": "^29.6.1", + "jest-message-util": "^29.6.1", + "jest-util": "^29.6.1", "natural-compare": "^1.4.0", - "pretty-format": "^29.5.0", - "semver": "^7.3.5" + "pretty-format": "^29.6.1", + "semver": "^7.5.3" } }, "jest-util": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.5.0.tgz", - "integrity": "sha512-RYMgG/MTadOr5t8KdhejfvUU82MxsCu5MF6KuDUHl+NuwzUt+Sm6jJWxTJVrDR1j5M/gJVCPKQEpWXY+yIQ6lQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.1.tgz", + "integrity": "sha512-NRFCcjc+/uO3ijUVyNOQJluf8PtGCe/W6cix36+M3cTFgiYqFOOW5MgN4JOOcvbUhcKTYVd1CvHz/LWi8d16Mg==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -20304,43 +20059,43 @@ } }, "jest-validate": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.5.0.tgz", - "integrity": "sha512-pC26etNIi+y3HV8A+tUGr/lph9B18GnzSRAkPaaZJIE1eFdiYm6/CewuiJQ8/RlfHd1u/8Ioi8/sJ+CmbA+zAQ==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.6.1.tgz", + "integrity": "sha512-r3Ds69/0KCN4vx4sYAbGL1EVpZ7MSS0vLmd3gV78O+NAx3PDQQukRU5hNHPXlyqCgFY8XUk7EuTMLugh0KzahA==", "dev": true, "requires": { - "@jest/types": "^29.5.0", + "@jest/types": "^29.6.1", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.5.0" + "pretty-format": "^29.6.1" } }, "jest-watcher": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", - "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.6.1.tgz", + "integrity": "sha512-d4wpjWTS7HEZPaaj8m36QiaP856JthRZkrgcIY/7ISoUWPIillrXM23WPboZVLbiwZBt4/qn2Jke84Sla6JhFA==", "dev": true, "requires": { - "@jest/test-result": "^29.5.0", - "@jest/types": "^29.5.0", + "@jest/test-result": "^29.6.1", + "@jest/types": "^29.6.1", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", - "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.1.tgz", + "integrity": "sha512-U+Wrbca7S8ZAxAe9L6nb6g8kPdia5hj32Puu5iOqBCMTMWFHXuK6dOV2IFrpedbTV8fjMFLdWNttQTBL6u2MRA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.5.0", + "jest-util": "^29.6.1", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -20426,9 +20181,9 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" }, "jsonwebtoken": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.0.tgz", - "integrity": "sha512-tuGfYXxkQGDPnLJ7SibiQgVgeDgfbPq2k2ICcbgqW8WxWLBAxKQM/ZCu/IT8SOSwmaYl4dpTFCW5xZv7YbbWUw==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", "requires": { "jws": "^3.2.2", "lodash": "^4.17.21", @@ -20832,9 +20587,9 @@ } }, "mongoose": { - "version": "6.11.1", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.1.tgz", - "integrity": "sha512-AvQ8C5ZGF6GcsQhoRg/i7pbNZpb96qLGU5ICBllckp7qMOxcfUF1nA6JstZw841BqRcE6myZ/mx9CluEESaw5Q==", + "version": "6.11.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.4.tgz", + "integrity": "sha512-q9NaW9/BBYZofx80SqlR7uoSR09CS3g02y+KMj1lNLUxcFFsPshupY3WWisNFauYG9gyuDF4L/RgyIK3obSghg==", "requires": { "bson": "^4.7.2", "kareem": "2.5.1", @@ -20955,9 +20710,9 @@ } }, "node-fetch": { - "version": "2.6.11", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", - "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", "requires": { "whatwg-url": "^5.0.0" }, @@ -20990,15 +20745,15 @@ "dev": true }, "node-releases": { - "version": "2.0.12", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", - "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", + "version": "2.0.13", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", + "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", "dev": true }, "nodemailer": { - "version": "6.9.2", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz", - "integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg==" + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.4.tgz", + "integrity": "sha512-CXjQvrQZV4+6X5wP6ZIgdehJamI63MFoYFGGPtHudWym9qaEHDNdPzaj5bfMCvxG1vhAileSWW90q7nL0N36mA==" }, "nodemon": { "version": "2.0.22", @@ -22914,11 +22669,6 @@ } } }, - "on-exit-leak-free": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.0.tgz", - "integrity": "sha512-VuCaZZAjReZ3vUwgOB8LxAosIurDiAW0s13rI1YwmaP++jvcxP77AWoQvenZebpCA2m8WC1/EosPYPMjnRAp/w==" - }, "on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -23154,48 +22904,6 @@ } } }, - "pino-abstract-transport": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-1.0.0.tgz", - "integrity": "sha512-c7vo5OpW4wIS42hUVcT5REsL8ZljsUfBjqV/e2sFxmFEFZiq1XLUp5EYLtuDH6PEHq9W1egWqRbnLUP5FuZmOA==", - "requires": { - "readable-stream": "^4.0.0", - "split2": "^4.0.0" - }, - "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - } - } - }, "pino-http": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/pino-http/-/pino-http-5.8.0.tgz", @@ -23214,63 +22922,35 @@ } }, "pino-pretty": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-10.0.1.tgz", - "integrity": "sha512-yrn00+jNpkvZX/NrPVCPIVHAfTDy3ahF0PND9tKqZk4j9s+loK8dpzrJj4dGb7i+WLuR50ussuTAiWoMWU+qeA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-6.0.0.tgz", + "integrity": "sha512-jyeR2fXXWc68st1DTTM5NhkHlx8p+1fKZMfm84Jwq+jSw08IwAjNaZBZR6ts69hhPOfOjg/NiE1HYW7vBRPL3A==", "requires": { - "colorette": "^2.0.7", - "dateformat": "^4.6.3", - "fast-copy": "^3.0.0", - "fast-safe-stringify": "^2.1.1", - "help-me": "^4.0.1", - "joycon": "^3.1.1", - "minimist": "^1.2.6", - "on-exit-leak-free": "^2.1.0", - "pino-abstract-transport": "^1.0.0", + "@hapi/bourne": "^2.0.0", + "args": "^5.0.1", + "colorette": "^1.3.0", + "dateformat": "^4.5.1", + "fast-safe-stringify": "^2.0.7", + "jmespath": "^0.15.0", + "joycon": "^3.0.0", "pump": "^3.0.0", - "readable-stream": "^4.0.0", - "secure-json-parse": "^2.4.0", - "sonic-boom": "^3.0.0", + "readable-stream": "^3.6.0", + "rfdc": "^1.3.0", + "split2": "^3.1.1", "strip-json-comments": "^3.1.1" }, "dependencies": { - "buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "jmespath": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.15.0.tgz", + "integrity": "sha512-+kHj8HXArPfpPEKGLZ+kB5ONRTCiGQXo8RQYL0hH8t6pWXUBBK5KkkQmTNOwKK4LEsd0yTsgtjJVm4UBSZea4w==" + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "requires": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==" - }, - "ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" - }, - "readable-stream": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.4.2.tgz", - "integrity": "sha512-Lk/fICSyIhodxy1IDK2HazkeGjSmezAWX2egdtJnYhtzKEsBPJowlI6F6LPb5tqIQILrMbx22S5o3GuJavPusA==", - "requires": { - "abort-controller": "^3.0.0", - "buffer": "^6.0.3", - "events": "^3.3.0", - "process": "^0.11.10", - "string_decoder": "^1.3.0" - } - }, - "sonic-boom": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.3.0.tgz", - "integrity": "sha512-LYxp34KlZ1a2Jb8ZQgFCK3niIHzibdwtwNUWKg0qQRzsDoJ3Gfgkf8KdBTFU3SkejDEIlWwnSnpVdOZIhFMl/g==", - "requires": { - "atomic-sleep": "^1.0.0" + "readable-stream": "^3.0.0" } } } @@ -23281,9 +22961,9 @@ "integrity": "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA==" }, "pirates": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.5.tgz", - "integrity": "sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true }, "pkg-conf": { @@ -23409,12 +23089,12 @@ "dev": true }, "pretty-format": { - "version": "29.5.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", - "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "version": "29.6.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.6.1.tgz", + "integrity": "sha512-7jRj+yXO0W7e4/tSJKoR7HRIHLPPjtNaUGG2xxKQnGvPNRkgWcQ0AZX6P4KBRJN4FcTBWb3sa7DVUJmocYuoog==", "dev": true, "requires": { - "@jest/schemas": "^29.4.3", + "@jest/schemas": "^29.6.0", "ansi-styles": "^5.0.0", "react-is": "^18.0.0" }, @@ -23743,11 +23423,6 @@ } } }, - "process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==" - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -23818,9 +23493,9 @@ } }, "punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==" }, "pure-rand": { "version": "6.0.2", @@ -23898,9 +23573,9 @@ "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==" }, "mongodb": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.3.tgz", - "integrity": "sha512-Psm+g3/wHXhjBEktkxXsFMZvd3nemI0r3IPsE0bU+4//PnvNWKkzhZcEsbPcYiWqe8XqXJJEg4Tgtr7Raw67Yw==", + "version": "3.7.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.7.4.tgz", + "integrity": "sha512-K5q8aBqEXMwWdVNh94UQTwZ6BejVbFhh1uB6c5FKtPE9eUMZPUO3sRZdgIEcHSrAWmxzpG/FeODDKL388sqRmw==", "requires": { "bl": "^2.2.1", "bson": "^1.1.4", @@ -24038,21 +23713,6 @@ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "ripemd160": { @@ -24102,11 +23762,6 @@ "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz", "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, - "secure-json-parse": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", - "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -24310,31 +23965,6 @@ "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz", "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==", "dev": true - }, - "mime": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", - "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", - "dev": true - }, - "superagent": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", - "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", - "dev": true, - "requires": { - "component-emitter": "^1.3.0", - "cookiejar": "^2.1.3", - "debug": "^4.3.4", - "fast-safe-stringify": "^2.1.1", - "form-data": "^4.0.0", - "formidable": "^2.0.1", - "methods": "^1.1.2", - "mime": "^2.5.0", - "qs": "^6.10.3", - "readable-stream": "^3.6.0", - "semver": "^7.3.7" - } } } }, @@ -24516,21 +24146,22 @@ "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==" }, "superagent": { - "version": "8.0.9", - "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", - "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-7.1.5.tgz", + "integrity": "sha512-HQYyGuDRFGmZ6GNC4hq2f37KnsY9Lr0/R1marNZTgMweVDQLTLJJ6DGQ9Tj/xVVs5HEnop9EMmTbywb5P30aqw==", "dev": true, "requires": { "component-emitter": "^1.3.0", - "cookiejar": "^2.1.4", + "cookiejar": "^2.1.3", "debug": "^4.3.4", "fast-safe-stringify": "^2.1.1", "form-data": "^4.0.0", - "formidable": "^2.1.2", + "formidable": "^2.0.1", "methods": "^1.1.2", - "mime": "2.6.0", - "qs": "^6.11.0", - "semver": "^7.3.8" + "mime": "^2.5.0", + "qs": "^6.10.3", + "readable-stream": "^3.6.0", + "semver": "^7.3.7" }, "dependencies": { "mime": { @@ -24549,6 +24180,32 @@ "requires": { "methods": "^1.1.2", "superagent": "^8.0.5" + }, + "dependencies": { + "mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true + }, + "superagent": { + "version": "8.0.9", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-8.0.9.tgz", + "integrity": "sha512-4C7Bh5pyHTvU33KpZgwrNKh/VQnvgtCSqPRfJAUdmrtSYePVzVg4E4OzsrbkhJj9O7SO6Bnv75K/F8XVZT8YHA==", + "dev": true, + "requires": { + "component-emitter": "^1.3.0", + "cookiejar": "^2.1.4", + "debug": "^4.3.4", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.0", + "formidable": "^2.1.2", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.0", + "semver": "^7.3.8" + } + } } }, "supports-color": { @@ -24566,9 +24223,9 @@ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" }, "swagger-autogen": { - "version": "2.23.1", - "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.1.tgz", - "integrity": "sha512-tOAb5cOGNPduIHKoOxndCRy2Mrg7xV3O1RerrWExrDxeSTjXhA350pyJd7VUDY6ZO9gbZ34Bjlc5CXkleUgvAQ==", + "version": "2.23.5", + "resolved": "https://registry.npmjs.org/swagger-autogen/-/swagger-autogen-2.23.5.tgz", + "integrity": "sha512-4Tl2+XhZMyHoBYkABnScHtQE0lKPKUD3NBt09mClrI6UKOUYljKlYw1xiFVwsHCTGR2hAXmhT4PpgjruCtt1ZA==", "requires": { "acorn": "^7.4.1", "deepmerge": "^4.2.2", @@ -24580,26 +24237,13 @@ "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" - }, - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } } } }, "swagger-ui-dist": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.19.0.tgz", - "integrity": "sha512-9C9fJGI18gK5AhaU5YRyPY1lXJH4lmWh8h9zFMrJBkYzdRjCbAzYl1ayWPYgwFvag/Luqi3Co599OK/39IS2QQ==" + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.1.3.tgz", + "integrity": "sha512-W/vZFeZHG+xTN4yu8LXdaIrcnT4Hbr7qRUILYlMEoIiG6nuTylnEGeRcvL64F2eHRA2Jo/fgCSTU06Qfh0lT3g==" }, "swagger-ui-express": { "version": "4.6.3", @@ -24638,22 +24282,6 @@ "@istanbuljs/schema": "^0.1.2", "glob": "^7.1.4", "minimatch": "^3.0.4" - }, - "dependencies": { - "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } } }, "text-hex": { @@ -24725,17 +24353,24 @@ "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", "requires": { "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + } } }, "triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==" }, "ts-jest": { - "version": "29.1.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", - "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", + "version": "29.1.1", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.1.tgz", + "integrity": "sha512-D6xjnnbP17cC85nliwGiL+tpoKN0StpgE0TeOjXQTU6MVCfsB4v7aW05CgQ/1OywGb0x/oy9hHFnN+sczTiRaA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -24744,7 +24379,7 @@ "json5": "^2.2.3", "lodash.memoize": "4.x", "make-error": "1.x", - "semver": "7.x", + "semver": "^7.5.3", "yargs-parser": "^21.0.1" } }, @@ -24770,9 +24405,9 @@ } }, "tslib": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", - "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" }, "tsutils": { "version": "3.21.0", @@ -24915,6 +24550,14 @@ "dev": true, "requires": { "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "dev": true + } } }, "url": { @@ -25044,16 +24687,15 @@ } }, "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", + "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", "requires": { "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.0" } }, "wide-align": { @@ -25065,9 +24707,9 @@ } }, "winston": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", - "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.10.0.tgz", + "integrity": "sha512-nT6SIDaE9B7ZRO0u3UvdrimG0HkB7dSTAgInQnNR2SOPJ4bvq5q79+pXLftKmP52lJGW15+H5MCK0nM9D3KB/g==", "requires": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -25141,6 +24783,39 @@ "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", "dev": true }, + "xml-crypto": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/xml-crypto/-/xml-crypto-3.2.0.tgz", + "integrity": "sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==", + "requires": { + "@xmldom/xmldom": "^0.8.8", + "xpath": "0.0.32" + }, + "dependencies": { + "xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" + } + } + }, + "xml-encryption": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/xml-encryption/-/xml-encryption-3.0.2.tgz", + "integrity": "sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==", + "requires": { + "@xmldom/xmldom": "^0.8.5", + "escape-html": "^1.0.3", + "xpath": "0.0.32" + }, + "dependencies": { + "xpath": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.32.tgz", + "integrity": "sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==" + } + } + }, "xml2js": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", @@ -25148,12 +24823,24 @@ "requires": { "sax": ">=0.6.0", "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + } } }, "xmlbuilder": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", - "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==" + }, + "xpath": { + "version": "0.0.27", + "resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.27.tgz", + "integrity": "sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==" }, "y18n": { "version": "5.0.8", diff --git a/backend/package.json b/backend/package.json index a6cf3aa70a..fb20375845 100644 --- a/backend/package.json +++ b/backend/package.json @@ -2,6 +2,7 @@ "dependencies": { "@aws-sdk/client-secrets-manager": "^3.319.0", "@godaddy/terminus": "^4.12.0", + "@node-saml/passport-saml": "^4.0.4", "@octokit/rest": "^19.0.5", "@sentry/node": "^7.49.0", "@sentry/tracing": "^7.48.0", diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index bcbb715ade..655081f842 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -37,6 +37,7 @@ export const getClientIdNetlify = async () => (await client.getSecret("CLIENT_ID export const getClientIdGitHub = async () => (await client.getSecret("CLIENT_ID_GITHUB")).secretValue; export const getClientIdGitLab = async () => (await client.getSecret("CLIENT_ID_GITLAB")).secretValue; export const getClientIdGoogle = async () => (await client.getSecret("CLIENT_ID_GOOGLE")).secretValue; +export const getClientIdBitBucket = async () => (await client.getSecret("CLIENT_ID_BITBUCKET")).secretValue; export const getClientSecretAzure = async () => (await client.getSecret("CLIENT_SECRET_AZURE")).secretValue; export const getClientSecretHeroku = async () => (await client.getSecret("CLIENT_SECRET_HEROKU")).secretValue; export const getClientSecretVercel = async () => (await client.getSecret("CLIENT_SECRET_VERCEL")).secretValue; @@ -44,6 +45,7 @@ export const getClientSecretNetlify = async () => (await client.getSecret("CLIEN export const getClientSecretGitHub = async () => (await client.getSecret("CLIENT_SECRET_GITHUB")).secretValue; export const getClientSecretGitLab = async () => (await client.getSecret("CLIENT_SECRET_GITLAB")).secretValue; export const getClientSecretGoogle = async () => (await client.getSecret("CLIENT_SECRET_GOOGLE")).secretValue; +export const getClientSecretBitBucket = async () => (await client.getSecret("CLIENT_SECRET_BITBUCKET")).secretValue; export const getClientSlugVercel = async () => (await client.getSecret("CLIENT_SLUG_VERCEL")).secretValue; export const getPostHogHost = async () => (await client.getSecret("POSTHOG_HOST")).secretValue || "https://app.posthog.com"; export const getPostHogProjectApiKey = async () => (await client.getSecret("POSTHOG_PROJECT_API_KEY")).secretValue || "phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE"; diff --git a/backend/src/controllers/v1/integrationAuthController.ts b/backend/src/controllers/v1/integrationAuthController.ts index f625f10a2d..43d223ad65 100644 --- a/backend/src/controllers/v1/integrationAuthController.ts +++ b/backend/src/controllers/v1/integrationAuthController.ts @@ -7,6 +7,8 @@ import { IntegrationService } from "../../services"; import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_UTF8, + INTEGRATION_BITBUCKET_API_URL, + INTEGRATION_NORTHFLANK_API_URL, INTEGRATION_RAILWAY_API_URL, INTEGRATION_SET, INTEGRATION_VERCEL_API_URL, @@ -141,12 +143,14 @@ export const saveIntegrationAccessToken = async (req: Request, res: Response) => */ export const getIntegrationAuthApps = async (req: Request, res: Response) => { const teamId = req.query.teamId as string; + const workspaceSlug = req.query.workspaceSlug as string; const apps = await getApps({ integrationAuth: req.integrationAuth, accessToken: req.accessToken, accessId: req.accessId, - ...(teamId && { teamId }) + ...(teamId && { teamId }), + ...(workspaceSlug && { workspaceSlug }) }); return res.status(200).send({ @@ -382,6 +386,139 @@ export const getIntegrationAuthRailwayServices = async (req: Request, res: Respo }); }; +/** + * Return list of workspaces allowed for Bitbucket integration + * @param req + * @param res + * @returns + */ +export const getIntegrationAuthBitBucketWorkspaces = async (req: Request, res: Response) => { + + interface WorkspaceResponse { + size: number; + page: number; + pageLen: number; + next: string; + previous: string; + values: Array; + } + + interface Workspace { + type: string; + uuid: string; + name: string; + slug: string; + is_private: boolean; + created_on: string; + updated_on: string; + } + + const workspaces: Workspace[] = []; + let hasNextPage = true; + let workspaceUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/workspaces` + + while (hasNextPage) { + const { data }: { data: WorkspaceResponse } = await standardRequest.get( + workspaceUrl, + { + headers: { + Authorization: `Bearer ${req.accessToken}`, + "Accept-Encoding": "application/json" + } + } + ); + + if (data?.values.length > 0) { + data.values.forEach((workspace) => { + workspaces.push(workspace) + }) + } + + if (data.next) { + workspaceUrl = data.next + } else { + hasNextPage = false + } + } + + return res.status(200).send({ + workspaces + }); +}; + +/** + * Return list of secret groups for Northflank project with id [appId] + * @param req + * @param res + * @returns + */ +export const getIntegrationAuthNorthflankSecretGroups = async (req: Request, res: Response) => { + const appId = req.query.appId as string; + + interface NorthflankSecretGroup { + id: string; + name: string; + description: string; + priority: number; + projectId: string; + } + + interface SecretGroup { + name: string; + groupId: string; + } + + const secretGroups: SecretGroup[] = []; + + if (appId && appId !== "") { + let page = 1; + const perPage = 10; + let hasMorePages = true; + + while(hasMorePages) { + const params = new URLSearchParams({ + page: String(page), + per_page: String(perPage), + filter: "all", + }); + + const { + data: { + data: { + secrets + } + } + } = await standardRequest.get<{ data: { secrets: NorthflankSecretGroup[] }}>( + `${INTEGRATION_NORTHFLANK_API_URL}/v1/projects/${appId}/secrets`, + { + params, + headers: { + Authorization: `Bearer ${req.accessToken}`, + "Accept-Encoding": "application/json", + }, + } + ); + + secrets.forEach((a: any) => { + secretGroups.push({ + name: a.name, + groupId: a.id + }); + }); + + if (secrets.length < perPage) { + hasMorePages = false; + } + + page++; + } + } + + return res.status(200).send({ + secretGroups + }); +} + /** * Delete integration authorization with id [integrationAuthId] * @param req @@ -398,3 +535,4 @@ export const deleteIntegrationAuth = async (req: Request, res: Response) => { integrationAuth }); }; + diff --git a/backend/src/controllers/v1/integrationController.ts b/backend/src/controllers/v1/integrationController.ts index 7ab79976b0..91b32c805a 100644 --- a/backend/src/controllers/v1/integrationController.ts +++ b/backend/src/controllers/v1/integrationController.ts @@ -2,7 +2,7 @@ import { Request, Response } from "express"; import { Types } from "mongoose"; import { Integration } from "../../models"; import { EventService } from "../../services"; -import { eventPushSecrets, eventStartIntegration } from "../../events"; +import { eventStartIntegration } from "../../events"; import Folder from "../../models/folder"; import { getFolderByPath } from "../../services/FolderService"; import { BadRequestError } from "../../utils/errors"; diff --git a/backend/src/controllers/v1/membershipOrgController.ts b/backend/src/controllers/v1/membershipOrgController.ts index b5669a6715..02b99537f1 100644 --- a/backend/src/controllers/v1/membershipOrgController.ts +++ b/backend/src/controllers/v1/membershipOrgController.ts @@ -1,6 +1,7 @@ import { Types } from "mongoose"; import { Request, Response } from "express"; import { MembershipOrg, Organization, User } from "../../models"; +import { SSOConfig } from "../../ee/models"; import { deleteMembershipOrg as deleteMemberFromOrg } from "../../helpers/membershipOrg"; import { createToken } from "../../helpers/auth"; import { updateSubscriptionOrgQuantity } from "../../helpers/organization"; @@ -110,6 +111,18 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => { } const plan = await EELicenseService.getPlan(organizationId); + + const ssoConfig = await SSOConfig.findOne({ + organization: new Types.ObjectId(organizationId) + }); + + if (ssoConfig && ssoConfig.isActive) { + // case: SAML SSO is enabled for the organization + return res.status(400).send({ + message: + "Failed to invite member due to SAML SSO configured for organization" + }); + } if (plan.memberLimit !== null) { // case: limit imposed on number of members allowed diff --git a/backend/src/controllers/v1/organizationController.ts b/backend/src/controllers/v1/organizationController.ts index 8cbc5232f1..6de5a7c63c 100644 --- a/backend/src/controllers/v1/organizationController.ts +++ b/backend/src/controllers/v1/organizationController.ts @@ -9,7 +9,7 @@ import { import { createOrganization as create } from "../../helpers/organization"; import { addMembershipsOrg } from "../../helpers/membershipOrg"; import { ACCEPTED, OWNER } from "../../variables"; -import { getSiteURL, getLicenseServerUrl } from "../../config"; +import { getLicenseServerUrl, getSiteURL } from "../../config"; import { licenseServerKeyRequest } from "../../config/request"; export const getOrganizations = async (req: Request, res: Response) => { diff --git a/backend/src/controllers/v1/secretImportController.ts b/backend/src/controllers/v1/secretImportController.ts index a55b20a949..4b6539930d 100644 --- a/backend/src/controllers/v1/secretImportController.ts +++ b/backend/src/controllers/v1/secretImportController.ts @@ -30,7 +30,6 @@ export const createSecretImport = async (req: Request, res: Response) => { if (doesImportExist) { throw BadRequestError({ message: "Secret import already exist" }); } - importSecDoc.imports.push({ environment: secretImport.environment, secretPath: secretImport.secretPath diff --git a/backend/src/controllers/v2/environmentController.ts b/backend/src/controllers/v2/environmentController.ts index e1381db542..58f1e10f89 100644 --- a/backend/src/controllers/v2/environmentController.ts +++ b/backend/src/controllers/v2/environmentController.ts @@ -27,16 +27,16 @@ export const createWorkspaceEnvironment = async ( const { workspaceId } = req.params; const { environmentName, environmentSlug } = req.body; const workspace = await Workspace.findById(workspaceId).exec(); - + if (!workspace) throw WorkspaceNotFoundError(); - + const plan = await EELicenseService.getPlan(workspace.organization.toString()); - + if (plan.environmentLimit !== null) { // case: limit imposed on number of environments allowed if (workspace.environments.length >= plan.environmentLimit) { // case: number of environments used exceeds the number of environments allowed - + return res.status(400).send({ message: "Failed to create environment due to environment limit reached. Upgrade plan to create more environments.", }); @@ -191,14 +191,21 @@ export const deleteWorkspaceEnvironment = async ( workspace: workspaceId, environment: environmentSlug, }); - await ServiceToken.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await ServiceTokenData.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); + + // await ServiceToken.deleteMany({ + // workspace: workspaceId, + // environment: environmentSlug, + // }); + + const result = await ServiceTokenData.updateMany( + { workspace: workspaceId }, + { $pull: { scopes: { environment: environmentSlug } } } + ); + + if (result.modifiedCount > 0) { + await ServiceTokenData.deleteMany({ workspace: workspaceId, scopes: { $size: 0 } }); + } + await Integration.deleteMany({ workspace: workspaceId, environment: environmentSlug, diff --git a/backend/src/controllers/v2/secretController.ts b/backend/src/controllers/v2/secretController.ts index edc1d50aa7..1d5874e73d 100644 --- a/backend/src/controllers/v2/secretController.ts +++ b/backend/src/controllers/v2/secretController.ts @@ -9,8 +9,6 @@ import { } from "../../types/secret"; const { ValidationError } = mongoose.Error; import { - BadRequestError, - InternalServerError, ValidationError as RouteValidationError, UnauthorizedRequestError } from "../../utils/errors"; diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index ea8098e375..284c69c09b 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -830,7 +830,7 @@ export const getSecrets = async (req: Request, res: Response) => { // TODO(akhilmhdh) - secret-imp change this to org type let importedSecrets: any[] = []; - if (include_imports) { + if (include_imports === "true") { importedSecrets = await getAllImportedSecrets(workspaceId, environment, folderId as string); } diff --git a/backend/src/controllers/v2/serviceTokenDataController.ts b/backend/src/controllers/v2/serviceTokenDataController.ts index d81fb97d69..25176a5ff1 100644 --- a/backend/src/controllers/v2/serviceTokenDataController.ts +++ b/backend/src/controllers/v2/serviceTokenDataController.ts @@ -5,8 +5,6 @@ import { ServiceAccount, ServiceTokenData, User } from "../../models"; import { AUTH_MODE_JWT, AUTH_MODE_SERVICE_ACCOUNT } from "../../variables"; import { getSaltRounds } from "../../config"; import { BadRequestError } from "../../utils/errors"; -import Folder from "../../models/folder"; -import { getFolderByPath } from "../../services/FolderService"; /** * Return service token data associated with service token on request diff --git a/backend/src/controllers/v2/signupController.ts b/backend/src/controllers/v2/signupController.ts index 45a7db963e..66daf57013 100644 --- a/backend/src/controllers/v2/signupController.ts +++ b/backend/src/controllers/v2/signupController.ts @@ -18,7 +18,7 @@ import { updateSubscriptionOrgQuantity } from "../../helpers/organization"; * @returns */ export const completeAccountSignup = async (req: Request, res: Response) => { - let user, token, refreshToken; + let user; const { email, firstName, @@ -119,7 +119,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => { userAgent: req.headers["user-agent"] ?? "", }); - token = tokens.token; + const token = tokens.token; // sending a welcome email to new users if (await getLoopsApiKey()) { @@ -159,7 +159,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => { * @returns */ export const completeAccountInvite = async (req: Request, res: Response) => { - let user, token, refreshToken; + let user; const { email, firstName, @@ -244,7 +244,7 @@ export const completeAccountInvite = async (req: Request, res: Response) => { userAgent: req.headers["user-agent"] ?? "", }); - token = tokens.token; + const token = tokens.token; // store (refresh) token in httpOnly cookie res.cookie("jid", tokens.refreshToken, { diff --git a/backend/src/controllers/v2/usersController.ts b/backend/src/controllers/v2/usersController.ts index b5849f2e79..237d326711 100644 --- a/backend/src/controllers/v2/usersController.ts +++ b/backend/src/controllers/v2/usersController.ts @@ -4,6 +4,7 @@ import crypto from "crypto"; import bcrypt from "bcrypt"; import { APIKeyData, + AuthProvider, MembershipOrg, TokenVersion, User @@ -81,25 +82,66 @@ export const updateMyMfaEnabled = async (req: Request, res: Response) => { } /** - * Update the current user's name [firstName, lastName]. + * Update name of the current user to [firstName, lastName]. * @param req * @param res * @returns */ export const updateName = async (req: Request, res: Response) => { - const { firstName, lastName }: { firstName: string; lastName: string; } = req.body; - req.user.firstName = firstName; - req.user.lastName = lastName || ""; + const { + firstName, + lastName + }: { + firstName: string; + lastName: string; + } = req.body; - await req.user.save(); - - const user = req.user; + const user = await User.findByIdAndUpdate( + req.user._id.toString(), + { + firstName, + lastName: lastName ?? "" + }, + { + new: true + } + ); return res.status(200).send({ user, }); } +/** + * Update auth provider of the current user to [authProvider] + * @param req + * @param res + * @returns + */ +export const updateAuthProvider = async (req: Request, res: Response) => { + const { + authProvider + } = req.body; + + if (req.user?.authProvider === AuthProvider.OKTA_SAML) return res.status(400).send({ + message: "Failed to update user authentication method because SAML SSO is enforced" + }); + + const user = await User.findByIdAndUpdate( + req.user._id.toString(), + { + authProvider + }, + { + new: true + } + ); + + return res.status(200).send({ + user + }); +} + /** * Return organizations that the current user is part of. * @param req diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index b90b1a47b6..123e0b24b1 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -179,10 +179,9 @@ export const getWorkspaceKey = async (req: Request, res: Response) => { } } */ - let key; const { workspaceId } = req.params; - key = await Key.findOne({ + const key = await Key.findOne({ workspace: workspaceId, receiver: req.user._id }).populate("sender", "+publicKey"); diff --git a/backend/src/controllers/v3/authController.ts b/backend/src/controllers/v3/authController.ts index 7a70f171c1..7cb3cfd971 100644 --- a/backend/src/controllers/v3/authController.ts +++ b/backend/src/controllers/v3/authController.ts @@ -56,7 +56,7 @@ export const login1 = async (req: Request, res: Response) => { if (!user) throw new Error("Failed to find user"); - if (user.authProvider) { + if (user.authProvider && user.authProvider !== AuthProvider.EMAIL) { await validateProviderAuthToken({ email, user, @@ -117,7 +117,7 @@ export const login2 = async (req: Request, res: Response) => { if (!user) throw new Error("Failed to find user"); - if (user.authProvider) { + if (user.authProvider && user.authProvider !== AuthProvider.EMAIL) { await validateProviderAuthToken({ email, user, diff --git a/backend/src/controllers/v3/secretsController.ts b/backend/src/controllers/v3/secretsController.ts index cd2d3248e5..4b6c1adabf 100644 --- a/backend/src/controllers/v3/secretsController.ts +++ b/backend/src/controllers/v3/secretsController.ts @@ -3,12 +3,15 @@ import { Types } from "mongoose"; import { EventService, SecretService } from "../../services"; import { eventPushSecrets } from "../../events"; import { BotService } from "../../services"; -import { repackageSecretToRaw } from "../../helpers/secrets"; +import { containsGlobPatterns, repackageSecretToRaw } from "../../helpers/secrets"; import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; import { getAllImportedSecrets } from "../../services/SecretImportService"; import Folder from "../../models/folder"; import { getFolderByPath } from "../../services/FolderService"; import { BadRequestError } from "../../utils/errors"; +import { IServiceTokenData } from "../../models"; +import { requireWorkspaceAuth } from "../../middleware"; +import { ADMIN, MEMBER, PERMISSION_READ_SECRETS } from "../../variables"; /** * Return secrets for workspace with id [workspaceId] and environment @@ -17,11 +20,30 @@ import { BadRequestError } from "../../utils/errors"; * @param res */ export const getSecretsRaw = async (req: Request, res: Response) => { - const workspaceId = req.query.workspaceId as string; - const environment = req.query.environment as string; - const secretPath = req.query.secretPath as string; + let workspaceId = req.query.workspaceId as string; + let environment = req.query.environment as string; + let secretPath = req.query.secretPath as string; const includeImports = req.query.include_imports as string; + // if the service token has single scope, it will get all secrets for that scope by default + const serviceTokenDetails: IServiceTokenData = req?.serviceTokenData; + if (serviceTokenDetails && serviceTokenDetails.scopes.length == 1 && !containsGlobPatterns(serviceTokenDetails.scopes[0].secretPath)) { + const scope = serviceTokenDetails.scopes[0]; + secretPath = scope.secretPath; + environment = scope.environment; + workspaceId = serviceTokenDetails.workspace.toString(); + } else { + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }); + } + + const secrets = await SecretService.getSecrets({ workspaceId: new Types.ObjectId(workspaceId), environment, @@ -33,7 +55,7 @@ export const getSecretsRaw = async (req: Request, res: Response) => { workspaceId: new Types.ObjectId(workspaceId) }); - if (includeImports) { + if (includeImports === "true") { const folders = await Folder.findOne({ workspace: workspaceId, environment }); let folderId = "root"; // if folder exist get it and replace folderid with new one @@ -271,7 +293,7 @@ export const getSecrets = async (req: Request, res: Response) => { authData: req.authData }); - if (includeImports) { + if (includeImports === "true") { const folders = await Folder.findOne({ workspace: workspaceId, environment }); let folderId = "root"; // if folder exist get it and replace folderid with new one diff --git a/backend/src/controllers/v3/signupController.ts b/backend/src/controllers/v3/signupController.ts index 3d9f897c46..b33a7fe0c2 100644 --- a/backend/src/controllers/v3/signupController.ts +++ b/backend/src/controllers/v3/signupController.ts @@ -12,6 +12,7 @@ import { standardRequest } from "../../config/request"; import { getHttpsEnabled, getJwtSignupSecret, getLoopsApiKey } from "../../config"; import { BadRequestError } from "../../utils/errors"; import { TelemetryService } from "../../services"; +import { AuthProvider } from "../../models"; /** * Complete setting up user by adding their personal and auth information as part of the @@ -116,11 +117,13 @@ export const completeAccountSignup = async (req: Request, res: Response) => { if (!user) throw new Error("Failed to complete account for non-existent user"); // ensure user is non-null - // initialize default organization and workspace - await initializeDefaultOrg({ - organizationName, - user, - }); + if (user.authProvider !== AuthProvider.OKTA_SAML) { + // initialize default organization and workspace + await initializeDefaultOrg({ + organizationName, + user, + }); + } // update organization membership statuses that are // invited to completed with user attached @@ -174,7 +177,7 @@ export const completeAccountSignup = async (req: Request, res: Response) => { distinctId: email, properties: { email, - attributionSource, + ...(attributionSource ? { attributionSource } : {}) }, }); } diff --git a/backend/src/ee/controllers/v1/index.ts b/backend/src/ee/controllers/v1/index.ts index 75b30ff95a..0c63b41c05 100644 --- a/backend/src/ee/controllers/v1/index.ts +++ b/backend/src/ee/controllers/v1/index.ts @@ -1,6 +1,8 @@ import * as secretController from "./secretController"; import * as secretSnapshotController from "./secretSnapshotController"; import * as organizationsController from "./organizationsController"; +import * as ssoController from "./ssoController"; +import * as usersController from "./usersController"; import * as workspaceController from "./workspaceController"; import * as actionController from "./actionController"; import * as membershipController from "./membershipController"; @@ -10,6 +12,8 @@ export { secretController, secretSnapshotController, organizationsController, + ssoController, + usersController, workspaceController, actionController, membershipController, diff --git a/backend/src/ee/controllers/v1/organizationsController.ts b/backend/src/ee/controllers/v1/organizationsController.ts index 652fc4b32a..7f54323210 100644 --- a/backend/src/ee/controllers/v1/organizationsController.ts +++ b/backend/src/ee/controllers/v1/organizationsController.ts @@ -178,6 +178,12 @@ export const addOrganizationTaxId = async (req: Request, res: Response) => { return res.status(200).send(data); } +/** + * Delete tax id with id [taxId] from organization tax ids on file + * @param req + * @param res + * @returns + */ export const deleteOrganizationTaxId = async (req: Request, res: Response) => { const { taxId } = req.params; @@ -188,6 +194,12 @@ export const deleteOrganizationTaxId = async (req: Request, res: Response) => { return res.status(200).send(data); } +/** + * Return organization's invoices on file + * @param req + * @param res + * @returns + */ export const getOrganizationInvoices = async (req: Request, res: Response) => { const { data: { invoices } } = await licenseServerKeyRequest.get( `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/invoices` diff --git a/backend/src/ee/controllers/v1/ssoController.ts b/backend/src/ee/controllers/v1/ssoController.ts new file mode 100644 index 0000000000..4837dfd15b --- /dev/null +++ b/backend/src/ee/controllers/v1/ssoController.ts @@ -0,0 +1,267 @@ +import { Request, Response } from "express"; +import { Types } from "mongoose"; +import { BotOrgService } from "../../../services"; +import { SSOConfig } from "../../models"; +import { + MembershipOrg, + User +} from "../../../models"; +import { getSSOConfigHelper } from "../../helpers/organizations"; +import { client } from "../../../config"; +import { ResourceNotFoundError } from "../../../utils/errors"; +import { getSiteURL } from "../../../config"; +import { EELicenseService } from "../../services"; + +/** + * Redirect user to appropriate SSO endpoint after successful authentication + * to finish inputting their master key for logging in or signing up + * @param req + * @param res + * @returns + */ +export const redirectSSO = async (req: Request, res: Response) => { + if (req.isUserCompleted) { + return res.redirect(`${await getSiteURL()}/login/sso?token=${encodeURIComponent(req.providerAuthToken)}`); + } + + return res.redirect(`${await getSiteURL()}/signup/sso?token=${encodeURIComponent(req.providerAuthToken)}`); +} + +/** + * Return organization SAML SSO configuration + * @param req + * @param res + * @returns + */ +export const getSSOConfig = async (req: Request, res: Response) => { + const organizationId = req.query.organizationId as string; + + const data = await getSSOConfigHelper({ + organizationId: new Types.ObjectId(organizationId) + }); + + return res.status(200).send(data); +} + +/** + * Update organization SAML SSO configuration + * @param req + * @param res + * @returns + */ +export const updateSSOConfig = async (req: Request, res: Response) => { + const { + organizationId, + authProvider, + isActive, + entryPoint, + issuer, + cert, + audience + } = req.body; + + const plan = await EELicenseService.getPlan(organizationId); + + if (!plan.samlSSO) return res.status(400).send({ + message: "Failed to update SAML SSO configuration due to plan restriction. Upgrade plan to update SSO configuration." + }); + + interface PatchUpdate { + authProvider?: string; + isActive?: boolean; + encryptedEntryPoint?: string; + entryPointIV?: string; + entryPointTag?: string; + encryptedIssuer?: string; + issuerIV?: string; + issuerTag?: string; + encryptedCert?: string; + certIV?: string; + certTag?: string; + encryptedAudience?: string; + audienceIV?: string; + audienceTag?: string; + } + + const update: PatchUpdate = {}; + + if (authProvider) { + update.authProvider = authProvider; + } + + if (isActive !== undefined) { + update.isActive = isActive; + } + + const key = await BotOrgService.getSymmetricKey( + new Types.ObjectId(organizationId) + ); + + if (entryPoint) { + const { + ciphertext: encryptedEntryPoint, + iv: entryPointIV, + tag: entryPointTag + } = client.encryptSymmetric(entryPoint, key); + + update.encryptedEntryPoint = encryptedEntryPoint; + update.entryPointIV = entryPointIV; + update.entryPointTag = entryPointTag; + } + + if (issuer) { + const { + ciphertext: encryptedIssuer, + iv: issuerIV, + tag: issuerTag + } = client.encryptSymmetric(issuer, key); + + update.encryptedIssuer = encryptedIssuer; + update.issuerIV = issuerIV; + update.issuerTag = issuerTag; + } + + if (cert) { + const { + ciphertext: encryptedCert, + iv: certIV, + tag: certTag + } = client.encryptSymmetric(cert, key); + + update.encryptedCert = encryptedCert; + update.certIV = certIV; + update.certTag = certTag; + } + + if (audience) { + const { + ciphertext: encryptedAudience, + iv: audienceIV, + tag: audienceTag + } = client.encryptSymmetric(audience, key); + + update.encryptedAudience = encryptedAudience; + update.audienceIV = audienceIV; + update.audienceTag = audienceTag; + } + + const ssoConfig = await SSOConfig.findOneAndUpdate( + { + organization: new Types.ObjectId(organizationId) + }, + update, + { + new: true + } + ); + + if (!ssoConfig) throw ResourceNotFoundError({ + message: "Failed to find SSO config to update" + }); + + if (update.isActive !== undefined) { + const membershipOrgs = await MembershipOrg.find({ + organization: new Types.ObjectId(organizationId) + }).select("user"); + + if (update.isActive) { + await User.updateMany( + { + _id: { + $in: membershipOrgs.map((membershipOrg) => membershipOrg.user) + } + }, + { + authProvider: ssoConfig.authProvider + } + ); + } else { + await User.updateMany( + { + _id: { + $in: membershipOrgs.map((membershipOrg) => membershipOrg.user) + } + }, + { + $unset: { + authProvider: 1 + } + } + ); + } + } + + return res.status(200).send(ssoConfig); +} + +/** + * Create organization SAML SSO configuration + * @param req + * @param res + * @returns + */ +export const createSSOConfig = async (req: Request, res: Response) => { + const { + organizationId, + authProvider, + isActive, + entryPoint, + issuer, + cert, + audience + } = req.body; + + const plan = await EELicenseService.getPlan(organizationId); + + if (!plan.samlSSO) return res.status(400).send({ + message: "Failed to create SAML SSO configuration due to plan restriction. Upgrade plan to add SSO configuration." + }); + + const key = await BotOrgService.getSymmetricKey( + new Types.ObjectId(organizationId) + ); + + const { + ciphertext: encryptedEntryPoint, + iv: entryPointIV, + tag: entryPointTag + } = client.encryptSymmetric(entryPoint, key); + + const { + ciphertext: encryptedIssuer, + iv: issuerIV, + tag: issuerTag + } = client.encryptSymmetric(issuer, key); + + const { + ciphertext: encryptedCert, + iv: certIV, + tag: certTag + } = client.encryptSymmetric(cert, key); + + const { + ciphertext: encryptedAudience, + iv: audienceIV, + tag: audienceTag + } = client.encryptSymmetric(audience, key); + + const ssoConfig = await new SSOConfig({ + organization: new Types.ObjectId(organizationId), + authProvider, + isActive, + encryptedEntryPoint, + entryPointIV, + entryPointTag, + encryptedIssuer, + issuerIV, + issuerTag, + encryptedCert, + certIV, + certTag, + encryptedAudience, + audienceIV, + audienceTag + }).save(); + + return res.status(200).send(ssoConfig); +} \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/usersController.ts b/backend/src/ee/controllers/v1/usersController.ts new file mode 100644 index 0000000000..13e36a883a --- /dev/null +++ b/backend/src/ee/controllers/v1/usersController.ts @@ -0,0 +1,13 @@ +import { Request, Response } from "express"; + +/** + * Return the ip address of the current user + * @param req + * @param res + * @returns + */ +export const getMyIp = (req: Request, res: Response) => { + return res.status(200).send({ + ip: req.authData.authIP + }); +} \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/workspaceController.ts b/backend/src/ee/controllers/v1/workspaceController.ts index 5ec54d6764..d4f097ea20 100644 --- a/backend/src/ee/controllers/v1/workspaceController.ts +++ b/backend/src/ee/controllers/v1/workspaceController.ts @@ -3,16 +3,20 @@ import { PipelineStage, Types } from "mongoose"; import { Secret } from "../../../models"; import { FolderVersion, + IPType, ISecretVersion, Log, SecretSnapshot, SecretVersion, TFolderRootVersionSchema, + TrustedIP } from "../../models"; import { EESecretService } from "../../services"; import { getLatestSecretVersionIds } from "../../helpers/secretVersion"; import Folder, { TFolderSchema } from "../../../models/folder"; import { searchByFolderId } from "../../../services/FolderService"; +import { EELicenseService } from "../../services"; +import { extractIPDetails, isValidIpOrCidr } from "../../../utils/ip"; /** * Return secret snapshots for workspace with id [workspaceId] @@ -588,3 +592,147 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => { logs, }); }; + +/** + * Return trusted ips for workspace with id [workspaceId] + * @param req + * @param res + */ +export const getWorkspaceTrustedIps = async (req: Request, res: Response) => { + const { workspaceId } = req.params; + + const trustedIps = await TrustedIP.find({ + workspace: new Types.ObjectId(workspaceId) + }); + + return res.status(200).send({ + trustedIps + }); +} + +/** + * Add a trusted ip to workspace with id [workspaceId] + * @param req + * @param res + */ +export const addWorkspaceTrustedIp = async (req: Request, res: Response) => { + const { workspaceId } = req.params; + const { + ipAddress: ip, + comment, + isActive + } = req.body; + + const plan = await EELicenseService.getPlan(req.workspace.organization.toString()); + + if (!plan.ipAllowlisting) return res.status(400).send({ + message: "Failed to add IP access range due to plan restriction. Upgrade plan to add IP access range." + }); + + const isValidIPOrCidr = isValidIpOrCidr(ip); + + if (!isValidIPOrCidr) return res.status(400).send({ + message: "The IP is not a valid IPv4, IPv6, or CIDR block" + }); + + const { ipAddress, type, prefix } = extractIPDetails(ip); + + const trustedIp = await new TrustedIP({ + workspace: new Types.ObjectId(workspaceId), + ipAddress, + type, + prefix, + isActive, + comment, + }).save(); + + return res.status(200).send({ + trustedIp + }); +} + +/** + * Update trusted ip with id [trustedIpId] workspace with id [workspaceId] + * @param req + * @param res + */ +export const updateWorkspaceTrustedIp = async (req: Request, res: Response) => { + const { workspaceId, trustedIpId } = req.params; + const { + ipAddress: ip, + comment + } = req.body; + + const plan = await EELicenseService.getPlan(req.workspace.organization.toString()); + + if (!plan.ipAllowlisting) return res.status(400).send({ + message: "Failed to update IP access range due to plan restriction. Upgrade plan to update IP access range." + }); + + const isValidIPOrCidr = isValidIpOrCidr(ip); + + if (!isValidIPOrCidr) return res.status(400).send({ + message: "The IP is not a valid IPv4, IPv6, or CIDR block" + }); + + const { ipAddress, type, prefix } = extractIPDetails(ip); + + const updateObject: { + ipAddress: string; + type: IPType; + comment: string; + prefix?: number; + $unset?: { + prefix: number; + } + } = { + ipAddress, + type, + comment + }; + + if (prefix !== undefined) { + updateObject.prefix = prefix; + } else { + updateObject.$unset = { prefix: 1 }; + } + + const trustedIp = await TrustedIP.findOneAndUpdate( + { + _id: new Types.ObjectId(trustedIpId), + workspace: new Types.ObjectId(workspaceId), + }, + updateObject, + { + new: true + } + ); + + return res.status(200).send({ + trustedIp + }); +} + +/** + * Delete IP access range from workspace with id [workspaceId] + * @param req + * @param res + */ +export const deleteWorkspaceTrustedIp = async (req: Request, res: Response) => { + const { workspaceId, trustedIpId } = req.params; + + const plan = await EELicenseService.getPlan(req.workspace.organization.toString()); + + if (!plan.ipAllowlisting) return res.status(400).send({ + message: "Failed to delete IP access range due to plan restriction. Upgrade plan to delete IP access range." + }); + + const trustedIp = await TrustedIP.findOneAndDelete({ + _id: new Types.ObjectId(trustedIpId), + workspace: new Types.ObjectId(workspaceId) + }); + + return res.status(200).send({ + trustedIp + }); +} \ No newline at end of file diff --git a/backend/src/ee/helpers/organizations.ts b/backend/src/ee/helpers/organizations.ts new file mode 100644 index 0000000000..477b05ccd4 --- /dev/null +++ b/backend/src/ee/helpers/organizations.ts @@ -0,0 +1,72 @@ +import { Types } from "mongoose"; +import { + SSOConfig +} from "../models"; +import { + BotOrgService +} from "../../services"; +import { client } from "../../config"; +import { ValidationError } from "../../utils/errors"; + +export const getSSOConfigHelper = async ({ + organizationId, + ssoConfigId +}: { + organizationId?: Types.ObjectId; + ssoConfigId?: Types.ObjectId; +}) => { + + if (!organizationId && !ssoConfigId) throw ValidationError({ + message: "Getting SSO data requires either id of organization or SSO data" + }); + + const ssoConfig = await SSOConfig.findOne({ + ...(organizationId ? { organization: organizationId } : {}), + ...(ssoConfigId ? { _id: ssoConfigId } : {}) + }); + + if (!ssoConfig) throw new Error("Failed to find organization SSO data"); + + const key = await BotOrgService.getSymmetricKey( + ssoConfig.organization + ); + + const entryPoint = client.decryptSymmetric( + ssoConfig.encryptedEntryPoint, + key, + ssoConfig.entryPointIV, + ssoConfig.entryPointTag + ); + + const issuer = client.decryptSymmetric( + ssoConfig.encryptedIssuer, + key, + ssoConfig.issuerIV, + ssoConfig.issuerTag + ); + + const cert = client.decryptSymmetric( + ssoConfig.encryptedCert, + key, + ssoConfig.certIV, + ssoConfig.certTag + ); + + const audience = client.decryptSymmetric( + ssoConfig.encryptedAudience, + key, + ssoConfig.audienceIV, + ssoConfig.audienceTag + ); + + return ({ + _id: ssoConfig._id, + organization: ssoConfig.organization, + authProvider: ssoConfig.authProvider, + isActive: ssoConfig.isActive, + entryPoint, + issuer, + cert, + audience + }); +} \ No newline at end of file diff --git a/backend/src/ee/middleware/index.ts b/backend/src/ee/middleware/index.ts index a984d924b3..6a9cd2a071 100644 --- a/backend/src/ee/middleware/index.ts +++ b/backend/src/ee/middleware/index.ts @@ -1,7 +1,5 @@ -import requireLicenseAuth from "./requireLicenseAuth"; import requireSecretSnapshotAuth from "./requireSecretSnapshotAuth"; export { - requireLicenseAuth, requireSecretSnapshotAuth, } \ No newline at end of file diff --git a/backend/src/ee/middleware/requireLicenseAuth.ts b/backend/src/ee/middleware/requireLicenseAuth.ts deleted file mode 100644 index 476a3e82bf..0000000000 --- a/backend/src/ee/middleware/requireLicenseAuth.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { NextFunction, Request, Response } from "express"; - -/** - * Validate if organization hosting meets license requirements to - * access a license-specific route. - * @param {Object} obj - * @param {String[]} obj.acceptedTiers - */ -const requireLicenseAuth = ({ - acceptedTiers, -}: { - acceptedTiers: string[]; -}) => { - return async (req: Request, res: Response, next: NextFunction) => { - try { - - } catch (err) { - - } - } -} - -export default requireLicenseAuth; \ No newline at end of file diff --git a/backend/src/ee/models/action.ts b/backend/src/ee/models/action.ts index 2e84329146..c763915ee8 100644 --- a/backend/src/ee/models/action.ts +++ b/backend/src/ee/models/action.ts @@ -66,6 +66,4 @@ const actionSchema = new Schema( } ); -const Action = model("Action", actionSchema); - -export default Action; \ No newline at end of file +export const Action = model("Action", actionSchema); \ No newline at end of file diff --git a/backend/src/ee/models/folderVersion.ts b/backend/src/ee/models/folderVersion.ts index 4bfa2f67cc..dbcebcb928 100644 --- a/backend/src/ee/models/folderVersion.ts +++ b/backend/src/ee/models/folderVersion.ts @@ -52,9 +52,7 @@ const folderRootVersionSchema = new Schema( } ); -const FolderVersion = model( +export const FolderVersion = model( "FolderVersion", folderRootVersionSchema -); - -export default FolderVersion; +); \ No newline at end of file diff --git a/backend/src/ee/models/index.ts b/backend/src/ee/models/index.ts index 7867674d68..1def9073d5 100644 --- a/backend/src/ee/models/index.ts +++ b/backend/src/ee/models/index.ts @@ -1,18 +1,7 @@ -import SecretSnapshot, { ISecretSnapshot } from "./secretSnapshot"; -import SecretVersion, { ISecretVersion } from "./secretVersion"; -import FolderVersion, { TFolderRootVersionSchema } from "./folderVersion"; -import Log, { ILog } from "./log"; -import Action, { IAction } from "./action"; - -export { - SecretSnapshot, - ISecretSnapshot, - SecretVersion, - ISecretVersion, - FolderVersion, - TFolderRootVersionSchema, - Log, - ILog, - Action, - IAction, -}; +export * from "./secretSnapshot"; +export * from "./secretVersion"; +export * from "./folderVersion"; +export * from "./log"; +export * from "./action"; +export * from "./ssoConfig"; +export * from "./trustedIp"; \ No newline at end of file diff --git a/backend/src/ee/models/log.ts b/backend/src/ee/models/log.ts index 5e3d0dbbbf..ed8ff17f7d 100644 --- a/backend/src/ee/models/log.ts +++ b/backend/src/ee/models/log.ts @@ -63,11 +63,10 @@ const logSchema = new Schema( ipAddress: { type: String, }, - }, { - timestamps: true, -} + }, + { + timestamps: true, + } ); -const Log = model("Log", logSchema); - -export default Log; \ No newline at end of file +export const Log = model("Log", logSchema); \ No newline at end of file diff --git a/backend/src/ee/models/secretSnapshot.ts b/backend/src/ee/models/secretSnapshot.ts index d0fb61110b..71d1b27e62 100644 --- a/backend/src/ee/models/secretSnapshot.ts +++ b/backend/src/ee/models/secretSnapshot.ts @@ -46,9 +46,7 @@ const secretSnapshotSchema = new Schema( } ); -const SecretSnapshot = model( +export const SecretSnapshot = model( "SecretSnapshot", secretSnapshotSchema -); - -export default SecretSnapshot; +); \ No newline at end of file diff --git a/backend/src/ee/models/secretVersion.ts b/backend/src/ee/models/secretVersion.ts index 1922d45399..d63f05cf71 100644 --- a/backend/src/ee/models/secretVersion.ts +++ b/backend/src/ee/models/secretVersion.ts @@ -124,9 +124,7 @@ const secretVersionSchema = new Schema( } ); -const SecretVersion = model( +export const SecretVersion = model( "SecretVersion", secretVersionSchema -); - -export default SecretVersion; +); \ No newline at end of file diff --git a/backend/src/ee/models/ssoConfig.ts b/backend/src/ee/models/ssoConfig.ts new file mode 100644 index 0000000000..ab870afd7f --- /dev/null +++ b/backend/src/ee/models/ssoConfig.ts @@ -0,0 +1,80 @@ +import { Schema, Types, model } from "mongoose"; + +export interface ISSOConfig { + organization: Types.ObjectId; + authProvider: "okta-saml" + isActive: boolean; + encryptedEntryPoint: string; + entryPointIV: string; + entryPointTag: string; + encryptedIssuer: string; + issuerIV: string; + issuerTag: string; + encryptedCert: string; + certIV: string; + certTag: string; + encryptedAudience: string; + audienceIV: string; + audienceTag: string; +} + +const ssoConfigSchema = new Schema( + { + organization: { + type: Schema.Types.ObjectId, + ref: "Organization" + }, + authProvider: { + type: String, + enum: [ + "okta-saml" + ], + required: true + }, + isActive: { + type: Boolean, + required: true + }, + encryptedEntryPoint: { + type: String + }, + entryPointIV: { + type: String + }, + entryPointTag: { + type: String + }, + encryptedIssuer: { + type: String + }, + issuerIV: { + type: String + }, + issuerTag: { + type: String + }, + encryptedCert: { + type: String + }, + certIV: { + type: String + }, + certTag: { + type: String + }, + encryptedAudience: { + type: String + }, + audienceIV: { + type: String + }, + audienceTag: { + type: String + } + }, + { + timestamps: true + } +); + +export const SSOConfig = model("SSOConfig", ssoConfigSchema); \ No newline at end of file diff --git a/backend/src/ee/models/trustedIp.ts b/backend/src/ee/models/trustedIp.ts new file mode 100644 index 0000000000..85616be112 --- /dev/null +++ b/backend/src/ee/models/trustedIp.ts @@ -0,0 +1,54 @@ +import { Schema, Types, model } from "mongoose"; + +export enum IPType { + IPV4 = "ipv4", + IPV6 = "ipv6" +} + +export interface ITrustedIP { + _id: Types.ObjectId; + workspace: Types.ObjectId; + ipAddress: string; + type: "ipv4" | "ipv6", // either IPv4/IPv6 address or network IPv4/IPv6 address + isActive: boolean; + comment: string; + prefix?: number; // CIDR +} + +const trustedIpSchema = new Schema( + { + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true + }, + ipAddress: { + type: String, + required: true + }, + type: { + type: String, + enum: [ + IPType.IPV4, + IPType.IPV6 + ], + required: true + }, + prefix: { + type: Number, + required: false + }, + isActive: { + type: Boolean, + required: true + }, + comment: { + type: String + } + }, + { + timestamps: true + } +); + +export const TrustedIP = model("TrustedIP", trustedIpSchema); \ No newline at end of file diff --git a/backend/src/ee/routes/v1/index.ts b/backend/src/ee/routes/v1/index.ts index c68196c647..cf92bfc6c2 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -1,6 +1,8 @@ import secret from "./secret"; import secretSnapshot from "./secretSnapshot"; import organizations from "./organizations"; +import sso from "./sso"; +import users from "./users"; import workspace from "./workspace"; import action from "./action"; import cloudProducts from "./cloudProducts"; @@ -9,6 +11,8 @@ export { secret, secretSnapshot, organizations, + sso, + users, workspace, action, cloudProducts, diff --git a/backend/src/ee/routes/v1/sso.ts b/backend/src/ee/routes/v1/sso.ts new file mode 100644 index 0000000000..4771b51441 --- /dev/null +++ b/backend/src/ee/routes/v1/sso.ts @@ -0,0 +1,121 @@ +import express from "express"; +const router = express.Router(); +import passport from "passport"; +import { + requireAuth, + requireOrganizationAuth, + validateRequest, +} from "../../../middleware"; +import { body, query } from "express-validator"; +import { ssoController } from "../../controllers/v1"; +import { authLimiter } from "../../../helpers/rateLimiter"; +import { + ACCEPTED, + ADMIN, + OWNER +} from "../../../variables"; + +router.get( + "/redirect/google", + authLimiter, + (req, res, next) => { + passport.authenticate("google", { + scope: ["profile", "email"], + session: false, + ...(req.query.callback_port ? { + state: req.query.callback_port as string + } : {}) + })(req, res, next); + } +); + +router.get( + "/google", + passport.authenticate("google", { + failureRedirect: "/login/provider/error", + session: false + }), + ssoController.redirectSSO +); + +router.get( + "/redirect/saml2/:ssoIdentifier", + authLimiter, + (req, res, next) => { + const options = { + failureRedirect: "/", + additionalParams: { + RelayState: req.query.callback_port ?? "" + }, + }; + passport.authenticate("saml", options)(req, res, next); + } +); + +router.post("/saml2/:ssoIdentifier", + passport.authenticate("saml", { + failureRedirect: "/login/provider/error", + failureFlash: true, + session: false + }), + ssoController.redirectSSO +); + +router.get( + "/config", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED], + locationOrganizationId: "query" + }), + query("organizationId").exists().trim(), + validateRequest, + ssoController.getSSOConfig +); + +router.post( + "/config", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED], + locationOrganizationId: "body" + }), + body("organizationId").exists().trim(), + body("authProvider").exists().isString(), + body("isActive").exists().isBoolean(), + body("entryPoint").exists().isString(), + body("issuer").exists().isString(), + body("cert").exists().isString(), + body("audience").exists().isString(), + validateRequest, + ssoController.createSSOConfig +); + +router.patch( + "/config", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED], + locationOrganizationId: "body" + }), + body("organizationId").exists().trim(), + body("authProvider").optional().isString(), + body("isActive").optional().isBoolean(), + body("entryPoint").optional().isString(), + body("issuer").optional().isString(), + body("cert").optional().isString(), + body("audience").optional().isString(), + validateRequest, + ssoController.updateSSOConfig +); + +export default router; \ No newline at end of file diff --git a/backend/src/ee/routes/v1/users.ts b/backend/src/ee/routes/v1/users.ts new file mode 100644 index 0000000000..14dcaa49cf --- /dev/null +++ b/backend/src/ee/routes/v1/users.ts @@ -0,0 +1,17 @@ +import express from "express"; +const router = express.Router(); +import { + requireAuth +} from "../../../middleware"; +import { AUTH_MODE_API_KEY, AUTH_MODE_JWT } from "../../../variables"; +import { usersController } from "../../controllers/v1"; + +router.get( + "/me/ip", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], + }), + usersController.getMyIp +); + +export default router; \ No newline at end of file diff --git a/backend/src/ee/routes/v1/workspace.ts b/backend/src/ee/routes/v1/workspace.ts index 40392b45f4..49b13e6a56 100644 --- a/backend/src/ee/routes/v1/workspace.ts +++ b/backend/src/ee/routes/v1/workspace.ts @@ -6,13 +6,18 @@ import { validateRequest, } from "../../../middleware"; import { body, param, query } from "express-validator"; -import { ADMIN, MEMBER } from "../../../variables"; +import { + ADMIN, + AUTH_MODE_API_KEY, + AUTH_MODE_JWT, + MEMBER +} from "../../../variables"; import { workspaceController } from "../../controllers/v1"; router.get( "/:workspaceId/secret-snapshots", requireAuth({ - acceptedAuthModes: ["jwt", "apiKey"], + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -30,7 +35,7 @@ router.get( router.get( "/:workspaceId/secret-snapshots/count", requireAuth({ - acceptedAuthModes: ["jwt"], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -46,7 +51,7 @@ router.get( router.post( "/:workspaceId/secret-snapshots/rollback", requireAuth({ - acceptedAuthModes: ["jwt", "apiKey"], + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -63,7 +68,7 @@ router.post( router.get( "/:workspaceId/logs", requireAuth({ - acceptedAuthModes: ["jwt", "apiKey"], + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -79,4 +84,66 @@ router.get( workspaceController.getWorkspaceLogs ); +router.get( + "/:workspaceId/trusted-ips", + param("workspaceId").exists().isString().trim(), + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "params", + }), + workspaceController.getWorkspaceTrustedIps +); + +router.post( + "/:workspaceId/trusted-ips", + param("workspaceId").exists().isString().trim(), + body("ipAddress").exists().isString().trim(), + body("comment").default("").isString().trim(), + body("isActive").exists().isBoolean(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: "params", + }), + workspaceController.addWorkspaceTrustedIp +); + +router.patch( + "/:workspaceId/trusted-ips/:trustedIpId", + param("workspaceId").exists().isString().trim(), + param("trustedIpId").exists().isString().trim(), + body("ipAddress").isString().trim().default(""), + body("comment").default("").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: "params", + }), + workspaceController.updateWorkspaceTrustedIp +); + +router.delete( + "/:workspaceId/trusted-ips/:trustedIpId", + param("workspaceId").exists().isString().trim(), + param("trustedIpId").exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: "params", + }), + workspaceController.deleteWorkspaceTrustedIp +); + export default router; diff --git a/backend/src/ee/services/EELicenseService.ts b/backend/src/ee/services/EELicenseService.ts index 88220933d9..12e3e496ab 100644 --- a/backend/src/ee/services/EELicenseService.ts +++ b/backend/src/ee/services/EELicenseService.ts @@ -26,11 +26,13 @@ interface FeatureSet { environmentsUsed: number; secretVersioning: boolean; pitRecovery: boolean; + ipAllowlisting: boolean; rbac: boolean; customRateLimits: boolean; customAlerts: boolean; auditLogs: boolean; - status: 'incomplete' | 'incomplete_expired' | 'trialing' | 'active' | 'past_due' | 'canceled' | 'unpaid' | null; + samlSSO: boolean; + status: "incomplete" | "incomplete_expired" | "trialing" | "active" | "past_due" | "canceled" | "unpaid" | null; trial_end: number | null; has_used_trial: boolean; } @@ -59,10 +61,12 @@ class EELicenseService { environmentsUsed: 0, secretVersioning: true, pitRecovery: false, + ipAllowlisting: false, rbac: true, customRateLimits: true, customAlerts: true, auditLogs: false, + samlSSO: false, status: null, trial_end: null, has_used_trial: true diff --git a/backend/src/helpers/bot.ts b/backend/src/helpers/bot.ts index d3db7febf1..2252dcc64b 100644 --- a/backend/src/helpers/bot.ts +++ b/backend/src/helpers/bot.ts @@ -16,7 +16,6 @@ import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; import { InternalServerError } from "../utils/errors"; import Folder from "../models/folder"; import { getFolderByPath } from "../services/FolderService"; -import { environment } from "../routes/v2"; /** * Create an inactive bot with name [name] for workspace with id [workspaceId] diff --git a/backend/src/helpers/botOrg.ts b/backend/src/helpers/botOrg.ts new file mode 100644 index 0000000000..003cabbdc0 --- /dev/null +++ b/backend/src/helpers/botOrg.ts @@ -0,0 +1,134 @@ +import { Types } from "mongoose"; +import { client, getEncryptionKey, getRootEncryptionKey } from "../config"; +import { BotOrg } from "../models"; +import { decryptSymmetric128BitHexKeyUTF8 } from "../utils/crypto"; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_BASE64, + ENCODING_SCHEME_UTF8 +} from "../variables"; +import { InternalServerError } from "../utils/errors"; +import { encryptSymmetric128BitHexKeyUTF8, generateKeyPair } from "../utils/crypto"; + +/** + * Create a bot with name [name] for organization with id [organizationId] + * @param {Object} obj + * @param {String} obj.name - name of bot + * @param {String} obj.organizationId - id of organization that bot belongs to + */ +export const createBotOrg = async ({ + name, + organizationId, +}: { + name: string; + organizationId: Types.ObjectId; +}) => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const { publicKey, privateKey } = generateKeyPair(); + const key = client.createSymmetricKey(); + + if (rootEncryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv: privateKeyIV, + tag: privateKeyTag + } = client.encryptSymmetric(privateKey, rootEncryptionKey); + + const { + ciphertext: encryptedSymmetricKey, + iv: symmetricKeyIV, + tag: symmetricKeyTag + } = client.encryptSymmetric(key, rootEncryptionKey); + + return await new BotOrg({ + name, + organization: organizationId, + publicKey, + encryptedSymmetricKey, + symmetricKeyIV, + symmetricKeyTag, + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, + encryptedPrivateKey, + privateKeyIV, + privateKeyTag, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_BASE64 + }).save(); + } else if (encryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv: privateKeyIV, + tag: privateKeyTag + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: privateKey, + key: encryptionKey + }); + + const { + ciphertext: encryptedSymmetricKey, + iv: symmetricKeyIV, + tag: symmetricKeyTag + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: key, + key: encryptionKey + }); + + return await new BotOrg({ + name, + organization: organizationId, + publicKey, + encryptedSymmetricKey, + symmetricKeyIV, + symmetricKeyTag, + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, + encryptedPrivateKey, + privateKeyIV, + privateKeyTag, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 + }).save(); + } + + throw InternalServerError({ + message: "Failed to create new organization bot due to missing encryption key", + }); +}; + +export const getSymmetricKeyHelper = async (organizationId: Types.ObjectId) => { + const rootEncryptionKey = await getRootEncryptionKey(); + const encryptionKey = await getEncryptionKey(); + + const botOrg = await BotOrg.findOne({ + organization: organizationId + }); + + if (!botOrg) throw new Error("Failed to find organization bot"); + + if (rootEncryptionKey && botOrg.symmetricKeyKeyEncoding == ENCODING_SCHEME_BASE64) { + const key = client.decryptSymmetric( + botOrg.encryptedSymmetricKey, + rootEncryptionKey, + botOrg.symmetricKeyIV, + botOrg.symmetricKeyTag + ); + + return key; + } else if (encryptionKey && botOrg.symmetricKeyKeyEncoding === ENCODING_SCHEME_UTF8) { + const key = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: botOrg.encryptedSymmetricKey, + iv: botOrg.symmetricKeyIV, + tag: botOrg.symmetricKeyTag, + key: encryptionKey + }); + + return key; + } + + throw InternalServerError({ + message: "Failed to match encryption key with organization bot symmetric key encoding" + }); +} \ No newline at end of file diff --git a/backend/src/helpers/integration.ts b/backend/src/helpers/integration.ts index 47c99adaa4..196078533c 100644 --- a/backend/src/helpers/integration.ts +++ b/backend/src/helpers/integration.ts @@ -9,6 +9,7 @@ import { INTEGRATION_VERCEL, } from "../variables"; import { UnauthorizedRequestError } from "../utils/errors"; +import * as Sentry from "@sentry/node"; interface Update { workspace: string; @@ -115,53 +116,60 @@ export const syncIntegrationsHelper = async ({ workspaceId: Types.ObjectId; environment?: string; }) => { - const integrations = await Integration.find({ - workspace: workspaceId, - ...(environment - ? { + try { + const integrations = await Integration.find({ + workspace: workspaceId, + ...(environment + ? { environment, } : {}), - isActive: true, - app: { $ne: null }, - }); - - // for each workspace integration, sync/push secrets - // to that integration - for await (const integration of integrations) { - // get workspace, environment (shared) secrets - const secrets = await BotService.getSecrets({ - workspaceId: integration.workspace, - environment: integration.environment, - secretPath: integration.secretPath, + isActive: true, + app: { $ne: null }, }); - // get workspace, environment (shared) secrets comments - const secretComments = await BotService.getSecretComments({ - workspaceId: integration.workspace, - environment: integration.environment, - secretPath: integration.secretPath, - }) + // for each workspace integration, sync/push secrets + // to that integration + for await (const integration of integrations) { + // get workspace, environment (shared) secrets + const secrets = await BotService.getSecrets({ + workspaceId: integration.workspace, + environment: integration.environment, + secretPath: integration.secretPath, + }); - const integrationAuth = await IntegrationAuth.findById( - integration.integrationAuth - ); - if (!integrationAuth) throw new Error("Failed to find integration auth"); + // get workspace, environment (shared) secrets comments + const secretComments = await BotService.getSecretComments({ + workspaceId: integration.workspace, + environment: integration.environment, + secretPath: integration.secretPath, + }) - // get integration auth access token - const access = await getIntegrationAuthAccessHelper({ - integrationAuthId: integration.integrationAuth, - }); + const integrationAuth = await IntegrationAuth.findById( + integration.integrationAuth + ); - // sync secrets to integration - await syncSecrets({ - integration, - integrationAuth, - secrets, - accessId: access.accessId === undefined ? null : access.accessId, - accessToken: access.accessToken, - secretComments - }); + if (!integrationAuth) throw new Error("Failed to find integration auth"); + + // get integration auth access token + const access = await getIntegrationAuthAccessHelper({ + integrationAuthId: integration.integrationAuth, + }); + + // sync secrets to integration + await syncSecrets({ + integration, + integrationAuth, + secrets, + accessId: access.accessId === undefined ? null : access.accessId, + accessToken: access.accessToken, + secretComments + }); + } + } catch (err) { + Sentry.captureException(err); + console.log(`syncIntegrationsHelper: failed with [workspaceId=${workspaceId}] [environment=${environment}]`, err) // eslint-disable-line no-use-before-define + throw err } }; diff --git a/backend/src/helpers/organization.ts b/backend/src/helpers/organization.ts index 3748f18fe6..3123e1c161 100644 --- a/backend/src/helpers/organization.ts +++ b/backend/src/helpers/organization.ts @@ -14,6 +14,9 @@ import { licenseKeyRequest, licenseServerKeyRequest, } from "../config/request"; +import { + createBotOrg +} from "./botOrg"; /** * Create an organization with name [name] @@ -29,6 +32,7 @@ export const createOrganization = async ({ name: string; email: string; }) => { + const licenseServerKey = await getLicenseServerKey(); let organization; @@ -52,6 +56,12 @@ export const createOrganization = async ({ }).save(); } + // initialize bot for organization + await createBotOrg({ + name, + organizationId: organization._id + }); + return organization; }; diff --git a/backend/src/helpers/secrets.ts b/backend/src/helpers/secrets.ts index 1a68930bc6..c770e78fbf 100644 --- a/backend/src/helpers/secrets.ts +++ b/backend/src/helpers/secrets.ts @@ -44,6 +44,7 @@ import { EELogService, EESecretService } from "../ee/services"; import { getAuthDataPayloadIdObj, getAuthDataPayloadUserObj } from "../utils/auth"; import { getFolderIdFromServiceToken } from "../services/FolderService"; import picomatch from "picomatch"; +import path from "path"; export const isValidScope = ( authPayload: IServiceTokenData, @@ -60,6 +61,13 @@ export const isValidScope = ( return Boolean(validScope); }; +export function containsGlobPatterns(secretPath: string) { + const globChars = ["*", "?", "[", "]", "{", "}", "**"]; + const normalizedPath = path.normalize(secretPath); + return globChars.some(char => normalizedPath.includes(char)); +} + + /** * Returns an object containing secret [secret] but with its value, key, comment decrypted. * diff --git a/backend/src/helpers/workspace.ts b/backend/src/helpers/workspace.ts index d79d6c4537..ef38e4fc15 100644 --- a/backend/src/helpers/workspace.ts +++ b/backend/src/helpers/workspace.ts @@ -5,6 +5,10 @@ import { Secret, Workspace, } from "../models"; +import { + IPType, + TrustedIP +} from "../ee/models"; import { createBot } from "../helpers/bot"; import { EELicenseService } from "../ee/services"; import { SecretService } from "../services"; @@ -40,6 +44,26 @@ export const createWorkspace = async ({ await SecretService.createSecretBlindIndexData({ workspaceId: workspace._id, }); + + // initialize default trusted IPv4 CIDR - 0.0.0.0/0 + await new TrustedIP({ + workspace: workspace._id, + ipAddress: "0.0.0.0", + type: IPType.IPV4, + prefix: 0, + isActive: true, + comment: "" + }).save() + + // initialize default trusted IPv6 CIDR - ::/0 + await new TrustedIP({ + workspace: workspace._id, + ipAddress: "::", + type: IPType.IPV6, + prefix: 0, + isActive: true, + comment: "" + }); await EELicenseService.refreshPlan(organizationId); diff --git a/backend/src/index.ts b/backend/src/index.ts index a8a111f533..098e7fc273 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -19,9 +19,11 @@ import { action as eeActionRouter, cloudProducts as eeCloudProductsRouter, organizations as eeOrganizationsRouter, + sso as eeSSORouter, secret as eeSecretRouter, secretSnapshot as eeSecretSnapshotRouter, - workspace as eeWorkspaceRouter + users as eeUsersRouter, + workspace as eeWorkspaceRouter, } from "./ee/routes/v1"; import { auth as v1AuthRouter, @@ -34,6 +36,7 @@ import { membership as v1MembershipRouter, organization as v1OrganizationRouter, password as v1PasswordRouter, + secretImport as v1SecretImportRouter, secret as v1SecretRouter, secretScanning as v1SecretScanningRouter, secretsFolder as v1SecretsFolder, @@ -41,22 +44,21 @@ import { signup as v1SignupRouter, userAction as v1UserActionRouter, user as v1UserRouter, - workspace as v1WorkspaceRouter, webhooks as v1WebhooksRouter, - secretImport as v1SecretImportRouter + workspace as v1WorkspaceRouter } from "./routes/v1"; import { auth as v2AuthRouter, + environment as v2EnvironmentRouter, organizations as v2OrganizationsRouter, - signup as v2SignupRouter, - users as v2UsersRouter, - workspace as v2WorkspaceRouter, secret as v2SecretRouter, // begin to phase out secrets as v2SecretsRouter, - serviceTokenData as v2ServiceTokenDataRouter, serviceAccounts as v2ServiceAccountsRouter, - environment as v2EnvironmentRouter, - tags as v2TagsRouter + serviceTokenData as v2ServiceTokenDataRouter, + signup as v2SignupRouter, + tags as v2TagsRouter, + users as v2UsersRouter, + workspace as v2WorkspaceRouter, } from "./routes/v2"; import { auth as v3AuthRouter, @@ -81,6 +83,7 @@ const main = async () => { const app = express(); app.enable("trust proxy"); app.use(express.json()); + app.use(express.urlencoded({ extended: false })); app.use(cookieParser()); app.use( cors({ @@ -127,9 +130,11 @@ const main = async () => { // (EE) routes app.use("/api/v1/secret", eeSecretRouter); app.use("/api/v1/secret-snapshot", eeSecretSnapshotRouter); + app.use("/api/v1/users", eeUsersRouter); app.use("/api/v1/workspace", eeWorkspaceRouter); app.use("/api/v1/action", eeActionRouter); app.use("/api/v1/organizations", eeOrganizationsRouter); + app.use("/api/v1/sso", eeSSORouter); app.use("/api/v1/cloud-products", eeCloudProductsRouter); // v1 routes (default) diff --git a/backend/src/integrations/apps.ts b/backend/src/integrations/apps.ts index cd243e9d0c..0e5a9bf33c 100644 --- a/backend/src/integrations/apps.ts +++ b/backend/src/integrations/apps.ts @@ -1,16 +1,21 @@ -import { Octokit } from "@octokit/rest"; -import { IIntegrationAuth } from "../models"; -import { standardRequest } from "../config/request"; import { INTEGRATION_AWS_PARAMETER_STORE, INTEGRATION_AWS_SECRET_MANAGER, INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_BITBUCKET, + INTEGRATION_BITBUCKET_API_URL, INTEGRATION_CHECKLY, INTEGRATION_CHECKLY_API_URL, INTEGRATION_CIRCLECI, INTEGRATION_CIRCLECI_API_URL, INTEGRATION_CLOUDFLARE_PAGES, INTEGRATION_CLOUDFLARE_PAGES_API_URL, + INTEGRATION_CLOUD_66, + INTEGRATION_CLOUD_66_API_URL, + INTEGRATION_CODEFRESH, + INTEGRATION_CODEFRESH_API_URL, + INTEGRATION_DIGITAL_OCEAN_API_URL, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, INTEGRATION_FLYIO, INTEGRATION_FLYIO_API_URL, INTEGRATION_GITHUB, @@ -22,21 +27,26 @@ import { INTEGRATION_LARAVELFORGE_API_URL, INTEGRATION_NETLIFY, INTEGRATION_NETLIFY_API_URL, + INTEGRATION_NORTHFLANK, + INTEGRATION_NORTHFLANK_API_URL, INTEGRATION_RAILWAY, INTEGRATION_RAILWAY_API_URL, INTEGRATION_RENDER, INTEGRATION_RENDER_API_URL, INTEGRATION_SUPABASE, INTEGRATION_SUPABASE_API_URL, + INTEGRATION_TERRAFORM_CLOUD, + INTEGRATION_TERRAFORM_CLOUD_API_URL, INTEGRATION_TRAVISCI, INTEGRATION_TRAVISCI_API_URL, INTEGRATION_VERCEL, INTEGRATION_VERCEL_API_URL, - INTEGRATION_CODEFRESH, - INTEGRATION_CODEFRESH_API_URL, INTEGRATION_WINDMILL, INTEGRATION_WINDMILL_API_URL, } from "../variables"; +import { IIntegrationAuth } from "../models"; +import { Octokit } from "@octokit/rest"; +import { standardRequest } from "../config/request"; interface App { name: string; @@ -58,11 +68,13 @@ const getApps = async ({ accessToken, accessId, teamId, + workspaceSlug, }: { integrationAuth: IIntegrationAuth; accessToken: string; accessId?: string; teamId?: string; + workspaceSlug?: string; }) => { let apps: App[] = []; switch (integrationAuth.integration) { @@ -128,6 +140,12 @@ const getApps = async ({ serverId: accessId }); break; + case INTEGRATION_TERRAFORM_CLOUD: + apps = await getAppsTerraformCloud({ + accessToken, + workspacesId: accessId, + }); + break; case INTEGRATION_TRAVISCI: apps = await getAppsTravisCI({ accessToken, @@ -147,7 +165,18 @@ const getApps = async ({ apps = await getAppsCloudflarePages({ accessToken, accountId: accessId - }) + }); + break; + case INTEGRATION_NORTHFLANK: + apps = await getAppsNorthflank({ + accessToken, + }); + break; + case INTEGRATION_BITBUCKET: + apps = await getAppsBitBucket({ + accessToken, + workspaceSlug + }); break; case INTEGRATION_CODEFRESH: apps = await getAppsCodefresh({ @@ -156,6 +185,16 @@ const getApps = async ({ break; case INTEGRATION_WINDMILL: apps = await getAppsWindmill({ + accessToken + }); + break; + case INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM: + apps = await getAppsDigitalOceanAppPlatform({ + accessToken + }); + break; + case INTEGRATION_CLOUD_66: + apps = await getAppsCloud66({ accessToken, }); break; @@ -546,6 +585,43 @@ const getAppsTravisCI = async ({ accessToken }: { accessToken: string }) => { return apps; }; +/** + * Return list of projects for Terraform Cloud integration + * @param {Object} obj + * @param {String} obj.accessToken - access token for Terraform Cloud API + * @param {String} obj.workspacesId - workspace id of Terraform Cloud projects + * @returns {Object[]} apps - names and ids of Terraform Cloud projects + * @returns {String} apps.name - name of Terraform Cloud projects + */ +const getAppsTerraformCloud = async ({ + accessToken, + workspacesId +}: { + accessToken: string; + workspacesId?: string; +}) => { + const res = ( + await standardRequest.get(`${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${workspacesId}`, { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + }, + }) + ).data.data; + + const apps = [] + + const appsObj = { + name: res?.attributes.name, + appId: res?.id, + }; + + apps.push(appsObj) + + return apps; +}; + + /** * Return list of repositories for GitLab integration * @param {Object} obj @@ -735,6 +811,113 @@ const getAppsCloudflarePages = async ({ return apps; } +/** + * Return list of repositories for the BitBucket integration based on provided BitBucket workspace + * @param {Object} obj + * @param {String} obj.accessToken - access token for BitBucket API + * @param {String} obj.workspaceSlug - Workspace identifier for fetching BitBucket repositories + * @returns {Object[]} apps - BitBucket repositories + * @returns {String} apps.name - name of BitBucket repository + */ +const getAppsBitBucket = async ({ + accessToken, + workspaceSlug, +}: { + accessToken: string; + workspaceSlug?: string; +}) => { + interface RepositoriesResponse { + size: number; + page: number; + pageLen: number; + next: string; + previous: string; + values: Array; + } + + interface Repository { + type: string; + uuid: string; + name: string; + is_private: boolean; + created_on: string; + updated_on: string; + } + + if (!workspaceSlug) { + return [] + } + + const repositories: Repository[] = []; + let hasNextPage = true; + let repositoriesUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/repositories/${workspaceSlug}` + + while (hasNextPage) { + const { data }: { data: RepositoriesResponse } = await standardRequest.get( + repositoriesUrl, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + }, + } + ); + + if (data?.values.length > 0) { + data.values.forEach((repository) => { + repositories.push(repository) + }) + } + + if (data.next) { + repositoriesUrl = data.next + } else { + hasNextPage = false + } + } + + const apps = repositories.map((repository) => { + return { + name: repository.name, + appId: repository.uuid, + }; + }); + return apps; +} + +/** Return list of projects for Northflank integration + * @param {Object} obj + * @param {String} obj.accessToken - access token for Northflank API + * @returns {Object[]} apps - names of Northflank apps + * @returns {String} apps.name - name of Northflank app + */ +const getAppsNorthflank = async ({ accessToken }: { accessToken: string }) => { + const { + data: { + data: { + projects + } + } + } = await standardRequest.get( + `${INTEGRATION_NORTHFLANK_API_URL}/v1/projects`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, + } + ); + + const apps = projects.map((a: any) => { + return { + name: a.name, + appId: a.id + }; + }); + + return apps; +}; + /** * Return list of projects for Supabase integration * @param {Object} obj @@ -742,7 +925,6 @@ const getAppsCloudflarePages = async ({ * @returns {Object[]} apps - names of Supabase apps * @returns {String} apps.name - name of Supabase app */ - const getAppsCodefresh = async ({ accessToken, }: { @@ -862,9 +1044,109 @@ const getAppsWindmill = async ({ accessToken }: { accessToken: string }) => { appId: a.id, }; }); + + return apps; +} + +/** + * Return list of applications for DigitalOcean App Platform integration + * @param {Object} obj + * @param {String} obj.accessToken - personal access token for DigitalOcean + * @returns {Object[]} apps - names of DigitalOcean apps + * @returns {String} apps.name - name of DigitalOcean app + * @returns {String} apps.appId - id of DigitalOcean app + */ +const getAppsDigitalOceanAppPlatform = async ({ accessToken }: { accessToken: string }) => { + interface DigitalOceanApp { + id: string; + owner_uuid: string; + spec: Spec; + } + + interface Spec { + name: string; + region: string; + envs: Env[]; + } + + interface Env { + key: string; + value: string; + scope: string; + } + + const res = ( + await standardRequest.get(`${INTEGRATION_DIGITAL_OCEAN_API_URL}/v2/apps`, { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json" + } + }) + ).data; + + return (res.apps ?? []).map((a: DigitalOceanApp) => ({ + name: a.spec.name, + appId: a.id + })); +} + +/** + * Return list of applications for Cloud66 integration + * @param {Object} obj + * @param {String} obj.accessToken - personal access token for Cloud66 API + * @returns {Object[]} apps - Cloud66 apps + * @returns {String} apps.name - name of Cloud66 app + * @returns {String} apps.appId - uid of Cloud66 app + */ +const getAppsCloud66 = async ({ accessToken }: { accessToken: string }) => { + interface Cloud66Apps { + uid: string; + name: string; + account_id: number; + git: string; + git_branch: string; + environment: string; + cloud: string; + fqdn: string; + language: string; + framework: string; + status: number; + health: number; + last_activity: string; + last_activity_iso: string; + maintenance_mode: boolean; + has_loadbalancer: boolean; + created_at: string; + updated_at: string; + deploy_directory: string; + cloud_status: string; + backend: string; + version: string; + revision: string; + is_busy: boolean; + account_name: string; + is_cluster: boolean; + is_inside_cluster: boolean; + cluster_name: any; + application_address: string; + configstore_namespace: string; + } + + const stacks = ( + await standardRequest.get(`${INTEGRATION_CLOUD_66_API_URL}/3/stacks`, { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json" + } + }) + ).data.response as Cloud66Apps[] + + const apps = stacks.map((app) => ({ + name: app.name, + appId: app.uid + })); return apps; }; - export { getApps }; diff --git a/backend/src/integrations/exchange.ts b/backend/src/integrations/exchange.ts index 12948d4030..dddbb65c64 100644 --- a/backend/src/integrations/exchange.ts +++ b/backend/src/integrations/exchange.ts @@ -2,6 +2,8 @@ import { standardRequest } from "../config/request"; import { INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_AZURE_TOKEN_URL, + INTEGRATION_BITBUCKET, + INTEGRATION_BITBUCKET_TOKEN_URL, INTEGRATION_GITHUB, INTEGRATION_GITHUB_TOKEN_URL, INTEGRATION_GITLAB, @@ -15,11 +17,13 @@ import { } from "../variables"; import { getClientIdAzure, + getClientIdBitBucket, getClientIdGitHub, getClientIdGitLab, getClientIdNetlify, getClientIdVercel, getClientSecretAzure, + getClientSecretBitBucket, getClientSecretGitHub, getClientSecretGitLab, getClientSecretHeroku, @@ -78,6 +82,15 @@ interface ExchangeCodeGitlabResponse { created_at: number; } +interface ExchangeCodeBitBucketResponse { + access_token: string; + token_type: string; + expires_in: number; + refresh_token: string; + scopes: string; + state: string; +} + /** * Return [accessToken], [accessExpiresAt], and [refreshToken] for OAuth2 * code-token exchange for integration named [integration] @@ -129,6 +142,12 @@ const exchangeCode = async ({ obj = await exchangeCodeGitlab({ code, }); + break; + case INTEGRATION_BITBUCKET: + obj = await exchangeCodeBitBucket({ + code, + }); + break; } return obj; @@ -347,4 +366,43 @@ const exchangeCodeGitlab = async ({ code }: { code: string }) => { }; }; +/** + * Return [accessToken], [accessExpiresAt], and [refreshToken] for BitBucket + * code-token exchange + * @param {Object} obj1 + * @param {Object} obj1.code - code for code-token exchange + * @returns {Object} obj2 + * @returns {String} obj2.accessToken - access token for BitBucket API + * @returns {String} obj2.refreshToken - refresh token for BitBucket API + * @returns {Date} obj2.accessExpiresAt - date of expiration for access token + */ +const exchangeCodeBitBucket = async ({ code }: { code: string }) => { + const accessExpiresAt = new Date(); + const res: ExchangeCodeBitBucketResponse = ( + await standardRequest.post( + INTEGRATION_BITBUCKET_TOKEN_URL, + new URLSearchParams({ + grant_type: "authorization_code", + code: code, + client_id: await getClientIdBitBucket(), + client_secret: await getClientSecretBitBucket(), + redirect_uri: `${await getSiteURL()}/integrations/bitbucket/oauth2/callback`, + } as any), + { + headers: { + "Accept-Encoding": "application/json", + }, + } + ) + ).data; + + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); + + return { + accessToken: res.access_token, + refreshToken: res.refresh_token, + accessExpiresAt, + }; +}; + export { exchangeCode }; diff --git a/backend/src/integrations/refresh.ts b/backend/src/integrations/refresh.ts index d530ab2f58..426d414f5a 100644 --- a/backend/src/integrations/refresh.ts +++ b/backend/src/integrations/refresh.ts @@ -2,6 +2,8 @@ import { standardRequest } from "../config/request"; import { IIntegrationAuth } from "../models"; import { INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_BITBUCKET, + INTEGRATION_BITBUCKET_TOKEN_URL, INTEGRATION_GITLAB, INTEGRATION_HEROKU, } from "../variables"; @@ -13,8 +15,10 @@ import { import { IntegrationService } from "../services"; import { getClientIdAzure, + getClientIdBitBucket, getClientIdGitLab, getClientSecretAzure, + getClientSecretBitBucket, getClientSecretGitLab, getClientSecretHeroku, getSiteURL, @@ -46,6 +50,15 @@ interface RefreshTokenGitLabResponse { created_at: number; } +interface RefreshTokenBitBucketResponse { + access_token: string; + token_type: string; + expires_in: number; + refresh_token: string; + scopes: string; + state: string; +} + /** * Return new access token by exchanging refresh token [refreshToken] for integration * named [integration] @@ -83,6 +96,11 @@ const exchangeRefresh = async ({ refreshToken, }); break; + case INTEGRATION_BITBUCKET: + tokenDetails = await exchangeRefreshBitBucket({ + refreshToken, + }); + break; default: throw new Error("Failed to exchange token for incompatible integration"); } @@ -218,4 +236,46 @@ const exchangeRefreshGitLab = async ({ }; }; +/** + * Return new access token by exchanging refresh token [refreshToken] for the + * BitBucket integration + * @param {Object} obj + * @param {String} obj.refreshToken - refresh token to use to get new access token for BitBucket + * @returns + */ +const exchangeRefreshBitBucket = async ({ + refreshToken, +}: { + refreshToken: string; +}) => { + const accessExpiresAt = new Date(); + const { + data, + }: { + data: RefreshTokenBitBucketResponse; + } = await standardRequest.post( + INTEGRATION_BITBUCKET_TOKEN_URL, + new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: refreshToken, + client_id: await getClientIdBitBucket(), + client_secret: await getClientSecretBitBucket(), + redirect_uri: `${await getSiteURL()}/integrations/bitbucket/oauth2/callback`, + } as any), + { + headers: { + "Accept-Encoding": "application/json", + }, + } + ); + + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); + + return { + accessToken: data.access_token, + refreshToken: data.refresh_token, + accessExpiresAt, + }; +}; + export { exchangeRefresh }; diff --git a/backend/src/integrations/revoke.ts b/backend/src/integrations/revoke.ts index d4747a52a9..4d4f790c6d 100644 --- a/backend/src/integrations/revoke.ts +++ b/backend/src/integrations/revoke.ts @@ -18,7 +18,6 @@ const revokeAccess = async ({ integrationAuth: IIntegrationAuth; accessToken: string; }) => { - let deletedIntegrationAuth; // add any integration-specific revocation logic switch (integrationAuth.integration) { case INTEGRATION_HEROKU: @@ -33,7 +32,7 @@ const revokeAccess = async ({ break; } - deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ + const deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ _id: integrationAuth._id, }); diff --git a/backend/src/integrations/sync.ts b/backend/src/integrations/sync.ts index 8e5bf327cf..7aa74112f5 100644 --- a/backend/src/integrations/sync.ts +++ b/backend/src/integrations/sync.ts @@ -1,25 +1,29 @@ -import _ from "lodash"; -import AWS from "aws-sdk"; import { CreateSecretCommand, GetSecretValueCommand, ResourceNotFoundException, SecretsManagerClient, - UpdateSecretCommand, + UpdateSecretCommand } from "@aws-sdk/client-secrets-manager"; -import { Octokit } from "@octokit/rest"; -import sodium from "libsodium-wrappers"; import { IIntegration, IIntegrationAuth } from "../models"; import { INTEGRATION_AWS_PARAMETER_STORE, INTEGRATION_AWS_SECRET_MANAGER, INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_BITBUCKET, + INTEGRATION_BITBUCKET_API_URL, INTEGRATION_CHECKLY, INTEGRATION_CHECKLY_API_URL, INTEGRATION_CIRCLECI, INTEGRATION_CIRCLECI_API_URL, INTEGRATION_CLOUDFLARE_PAGES, INTEGRATION_CLOUDFLARE_PAGES_API_URL, + INTEGRATION_CLOUD_66, + INTEGRATION_CLOUD_66_API_URL, + INTEGRATION_CODEFRESH, + INTEGRATION_CODEFRESH_API_URL, + INTEGRATION_DIGITAL_OCEAN_API_URL, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, INTEGRATION_FLYIO, INTEGRATION_FLYIO_API_URL, INTEGRATION_GITHUB, @@ -32,23 +36,28 @@ import { INTEGRATION_LARAVELFORGE_API_URL, INTEGRATION_NETLIFY, INTEGRATION_NETLIFY_API_URL, + INTEGRATION_NORTHFLANK, + INTEGRATION_NORTHFLANK_API_URL, INTEGRATION_RAILWAY, INTEGRATION_RAILWAY_API_URL, INTEGRATION_RENDER, INTEGRATION_RENDER_API_URL, INTEGRATION_SUPABASE, INTEGRATION_SUPABASE_API_URL, + INTEGRATION_TERRAFORM_CLOUD, + INTEGRATION_TERRAFORM_CLOUD_API_URL, INTEGRATION_TRAVISCI, INTEGRATION_TRAVISCI_API_URL, INTEGRATION_VERCEL, INTEGRATION_VERCEL_API_URL, - INTEGRATION_CODEFRESH, - INTEGRATION_CODEFRESH_API_URL, INTEGRATION_WINDMILL, INTEGRATION_WINDMILL_API_URL, } from "../variables"; +import AWS from "aws-sdk"; +import { Octokit } from "@octokit/rest"; +import _ from "lodash"; +import sodium from "libsodium-wrappers"; import { standardRequest } from "../config/request"; -import { handleAuthProviderCallback } from "../controllers/v1/authController"; /** * Sync/push [secrets] to [app] in integration named [integration] @@ -186,34 +195,6 @@ const syncSecrets = async ({ accessToken, }); break; - case INTEGRATION_FLYIO: - await syncSecretsFlyio({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_CIRCLECI: - await syncSecretsCircleCI({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_TRAVISCI: - await syncSecretsTravisCI({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_SUPABASE: - await syncSecretsSupabase({ - integration, - secrets, - accessToken, - }); - break; case INTEGRATION_CHECKLY: await syncSecretsCheckly({ integration, @@ -221,6 +202,13 @@ const syncSecrets = async ({ accessToken, }); break; + case INTEGRATION_TERRAFORM_CLOUD: + await syncSecretsTerraformCloud({ + integration, + secrets, + accessToken, + }); + break; case INTEGRATION_HASHICORP_VAULT: await syncSecretsHashiCorpVault({ integration, @@ -245,6 +233,34 @@ const syncSecrets = async ({ accessToken, }); break; + case INTEGRATION_BITBUCKET: + await syncSecretsBitBucket({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM: + await syncSecretsDigitalOceanAppPlatform({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_CLOUD_66: + await syncSecretsCloud66({ + integration, + secrets, + accessToken + }); + break; + case INTEGRATION_NORTHFLANK: + await syncSecretsNorthflank({ + integration, + secrets, + accessToken + }); + break; case INTEGRATION_WINDMILL: await syncSecretsWindmill({ integration, @@ -720,8 +736,6 @@ const syncSecretsVercel = async ({ return true; }); - // return secret.target.includes(integration.targetEnvironment); - const res: { [key: string]: VercelSecret } = {}; for await (const vercelSecret of vercelSecrets) { @@ -1857,6 +1871,106 @@ const syncSecretsCheckly = async ({ } }; +/** + * Sync/push [secrets] to Terraform Cloud project with id [integration.appId] + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) + * @param {String} obj.accessToken - access token for Terraform Cloud API + */ +const syncSecretsTerraformCloud = async ({ + integration, + secrets, + accessToken, +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + // get secrets from Terraform Cloud + const getSecretsRes = ( + await standardRequest.get(`${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + }, + } + )) + .data + .data + .reduce((obj: any, secret: any) => ({ + ...obj, + [secret.attributes.key]: secret + }), {}); + + // create or update secrets on Terraform Cloud + for await (const key of Object.keys(secrets)) { + if (!(key in getSecretsRes)) { + // case: secret does not exist in Terraform Cloud + // -> add secret + await standardRequest.post( + `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars`, + { + data: { + type: "vars", + attributes: { + key, + value: secrets[key], + category: integration.targetService, + }, + }, + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/vnd.api+json", + Accept: "application/vnd.api+json", + }, + } + ); + } else { + // case: secret exists in Terraform Cloud + if (secrets[key] !== getSecretsRes[key].attributes.value) { + // -> update secret + await standardRequest.patch( + `${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars/${getSecretsRes[key].id}`, + { + data: { + type: "vars", + id: getSecretsRes[key].id, + attributes: { + ...getSecretsRes[key], + value: secrets[key] + }, + }, + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/vnd.api+json", + Accept: "application/vnd.api+json", + }, + } + ); + } + } + } + + for await (const key of Object.keys(getSecretsRes)) { + if (!(key in secrets)) { + // case: delete secret + await standardRequest.delete(`${INTEGRATION_TERRAFORM_CLOUD_API_URL}/api/v2/workspaces/${integration.appId}/vars/${getSecretsRes[key].id}`, { + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/vnd.api+json", + Accept: "application/vnd.api+json", + }, + }) + } + } +}; + /** * Sync/push [secrets] to HashiCorp Vault path * @param {Object} obj @@ -1949,7 +2063,7 @@ const syncSecretsCloudflarePages = async ({ } ) ) - .data.result['deployment_configs'][integration.targetEnvironment]['env_vars']; + .data.result["deployment_configs"][integration.targetEnvironment]["env_vars"]; // copy the secrets object, so we can set deleted keys to null const secretsObj: any = { ...secrets }; @@ -1989,9 +2103,125 @@ const syncSecretsCloudflarePages = async ({ } /** - * Sync/push [secrets] to Codefresh with name [integration.app] + * Sync/push [secrets] to BitBucket repo with name [integration.app] * @param {Object} obj * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth details + * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) + * @param {String} obj.accessToken - access token for BitBucket integration + */ +const syncSecretsBitBucket = async ({ + integration, + secrets, + accessToken, +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + interface VariablesResponse { + size: number; + page: number; + pageLen: number; + next: string; + previous: string; + values: Array; + } + + interface BitbucketVariable { + type: string; + uuid: string; + key: string; + value: string; + secured: boolean; + } + + const res: { [key: string]: BitbucketVariable } = {}; + + let hasNextPage = true; + let variablesUrl = `${INTEGRATION_BITBUCKET_API_URL}/2.0/repositories/${integration.targetEnvironmentId}/${integration.appId}/pipelines_config/variables` + + while (hasNextPage) { + const { data }: { data: VariablesResponse } = await standardRequest.get( + variablesUrl, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + }, + } + ); + + if (data?.values.length > 0) { + data.values.forEach((variable) => { + res[variable.key] = variable; + }); + } + + if (data.next) { + variablesUrl = data.next + } else { + hasNextPage = false + } + } + + for await (const key of Object.keys(secrets)) { + if (key in res) { + // update existing secret + await standardRequest.put( + `${variablesUrl}/${res[key].uuid}`, + { + key, + value: secrets[key], + secured: true + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + }, + } + ); + } else { + // create new secret + await standardRequest.post( + variablesUrl, + { + key, + value: secrets[key], + secured: true + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + }, + } + ); + } + } + + for await (const key of Object.keys(res)) { + if (!(key in secrets)) { + // delete secret + await standardRequest.delete( + `${variablesUrl}/${res[key].uuid}`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + } + } + ); + } + } +} + +/** + * Sync/push [secrets] to Codefresh project with name [integration.app] + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth details * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) * @param {String} obj.accessToken - access token for Codefresh integration */ @@ -2021,6 +2251,40 @@ const syncSecretsCodefresh = async ({ ); }; +/** + * Sync/push [secrets] to DigitalOcean App Platform application with name [integration.app] + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth details + * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) + * @param {String} obj.accessToken - access token for integration + */ +const syncSecretsDigitalOceanAppPlatform = async ({ + integration, + secrets, + accessToken +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + await standardRequest.put( + `${INTEGRATION_DIGITAL_OCEAN_API_URL}/v2/apps/${integration.appId}`, + { + spec: { + name: integration.app, + envs: Object.entries(secrets).map(([key, value]) => ({ key, value })) + } + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); +} + /** * Sync/push [secrets] to Windmill with name [integration.app] * @param {Object} obj @@ -2067,7 +2331,8 @@ const syncSecretsWindmill = async ({ {} ); - const pattern = /^(u\/|f\/)[a-zA-Z0-9_-]+\/([a-zA-Z0-9_-]+\/)*[a-zA-Z0-9_-]*[^\/]$/; + // eslint-disable-next-line no-useless-escape + const pattern = new RegExp("^(u\/|f\/)[a-zA-Z0-9_-]+\/([a-zA-Z0-9_-]+\/)*[a-zA-Z0-9_-]*[^\/]$"); for await (const key of Object.keys(secrets)) { if((key.startsWith("u/") || key.startsWith("f/")) && pattern.test(key)) { @@ -2108,7 +2373,7 @@ const syncSecretsWindmill = async ({ } ); } - }; + } } for await (const key of Object.keys(res)) { @@ -2126,6 +2391,140 @@ const syncSecretsWindmill = async ({ ); } } +} + +/** + * Sync/push [secrets] to Cloud66 application with name [integration.app] + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {IIntegrationAuth} obj.integrationAuth - integration auth details + * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) + * @param {String} obj.accessToken - access token for Cloud66 integration + */ +const syncSecretsCloud66 = async ({ + integration, + secrets, + accessToken +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + + interface Cloud66Secret { + id: number; + key: string; + value: string; + readonly: boolean; + created_at: string; + updated_at: string; + is_password: boolean; + is_generated: boolean; + history: any[]; + } + + // get all current secrets + const res = ( + await standardRequest.get( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ) + ) + .data + .response + .filter((secret: Cloud66Secret) => !secret.readonly || !secret.is_generated) + .reduce( + (obj: any, secret: any) => ({ + ...obj, + [secret.key]: secret + }), + {} + ); + + for await (const key of Object.keys(secrets)) { + if (key in res) { + // update existing secret + await standardRequest.put( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, + { + key, + value: secrets[key] + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } else { + // create new secret + await standardRequest.post( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments`, + { + key, + value: secrets[key] + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } + } + + for await (const key of Object.keys(res)) { + if (!(key in secrets)) { + // delete secret + await standardRequest.delete( + `${INTEGRATION_CLOUD_66_API_URL}/3/stacks/${integration.appId}/environments/${key}`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json" + } + } + ); + } + } +}; + +/** Sync/push [secrets] to Northflank + * @param {Object} obj + * @param {IIntegration} obj.integration - integration details + * @param {Object} obj.secrets - secrets to push to integration (object where keys are secret keys and values are secret values) + * @param {String} obj.accessToken - access token for Northflank integration + */ +const syncSecretsNorthflank = async ({ + integration, + secrets, + accessToken +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + await standardRequest.patch( + `${INTEGRATION_NORTHFLANK_API_URL}/v1/projects/${integration.appId}/secrets/${integration.targetServiceId}`, + { + secrets: { + variables: secrets + } + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json" + } + } + ); }; export { syncSecrets }; diff --git a/backend/src/middleware/requireAuth.ts b/backend/src/middleware/requireAuth.ts index 667524afdb..6c20be25a2 100644 --- a/backend/src/middleware/requireAuth.ts +++ b/backend/src/middleware/requireAuth.ts @@ -1,4 +1,5 @@ import jwt from "jsonwebtoken"; +import { Types } from "mongoose"; import { NextFunction, Request, Response } from "express"; import { getAuthAPIKeyPayload, @@ -51,6 +52,10 @@ const requireAuth = ({ }); let authPayload: IUser | IServiceAccount | IServiceTokenData; + let authUserPayload: { + user: IUser; + tokenVersionId: Types.ObjectId; + }; switch (authMode) { case AUTH_MODE_SERVICE_ACCOUNT: authPayload = await getAuthSAAKPayload({ @@ -71,12 +76,12 @@ const requireAuth = ({ req.user = authPayload; break; default: - const { user, tokenVersionId } = await getAuthUserPayload({ + authUserPayload = await getAuthUserPayload({ authTokenValue, }); - authPayload = user; - req.user = user; - req.tokenVersionId = tokenVersionId; + authPayload = authUserPayload.user; + req.user = authUserPayload.user; + req.tokenVersionId = authUserPayload.tokenVersionId; break; } diff --git a/backend/src/middleware/requireWorkspaceAuth.ts b/backend/src/middleware/requireWorkspaceAuth.ts index 197995a65e..f6f7405a9c 100644 --- a/backend/src/middleware/requireWorkspaceAuth.ts +++ b/backend/src/middleware/requireWorkspaceAuth.ts @@ -18,6 +18,7 @@ const requireWorkspaceAuth = ({ requiredPermissions = [], requireBlindIndicesEnabled = false, requireE2EEOff = false, + checkIPAllowlist = false }: { acceptedRoles: Array<"admin" | "member">; locationWorkspaceId: req; @@ -25,6 +26,7 @@ const requireWorkspaceAuth = ({ requiredPermissions?: string[]; requireBlindIndicesEnabled?: boolean; requireE2EEOff?: boolean; + checkIPAllowlist?: boolean; }) => { return async (req: Request, res: Response, next: NextFunction) => { const workspaceId = req[locationWorkspaceId]?.workspaceId; @@ -39,6 +41,7 @@ const requireWorkspaceAuth = ({ requiredPermissions, requireBlindIndicesEnabled, requireE2EEOff, + checkIPAllowlist }); if (membership) { diff --git a/backend/src/models/botOrg.ts b/backend/src/models/botOrg.ts new file mode 100644 index 0000000000..f7d3cd3ae1 --- /dev/null +++ b/backend/src/models/botOrg.ts @@ -0,0 +1,98 @@ +import { Schema, Types, model } from "mongoose"; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_BASE64, + ENCODING_SCHEME_UTF8, +} from "../variables"; + +export interface IBotOrg { + _id: Types.ObjectId; + name: string; + organization: Types.ObjectId; + publicKey: string; + encryptedSymmetricKey: string; + symmetricKeyIV: string; + symmetricKeyTag: string; + symmetricKeyAlgorithm: "aes-256-gcm"; + symmetricKeyKeyEncoding: "base64" | "utf8"; + encryptedPrivateKey: string; + privateKeyIV: string; + privateKeyTag: string; + privateKeyAlgorithm: "aes-256-gcm"; + privateKeyKeyEncoding: "base64" | "utf8"; +} + +const botOrgSchema = new Schema( + { + name: { + type: String, + required: true, + }, + organization: { + type: Schema.Types.ObjectId, + ref: "Organization", + required: true, + }, + publicKey: { + type: String, + required: true, + }, + encryptedSymmetricKey: { + type: String, + required: true + }, + symmetricKeyIV: { + type: String, + required: true + }, + symmetricKeyTag: { + type: String, + required: true + }, + symmetricKeyAlgorithm: { + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true + }, + symmetricKeyKeyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, + ], + required: true + }, + encryptedPrivateKey: { + type: String, + required: true + }, + privateKeyIV: { + type: String, + required: true + }, + privateKeyTag: { + type: String, + required: true + }, + privateKeyAlgorithm: { + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true + }, + privateKeyKeyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, + ], + required: true + }, + }, + { + timestamps: true, + } +); + +const BotOrg = model("BotOrg", botOrgSchema); + +export default BotOrg; diff --git a/backend/src/models/index.ts b/backend/src/models/index.ts index 10e460520e..d94d2b9177 100644 --- a/backend/src/models/index.ts +++ b/backend/src/models/index.ts @@ -1,5 +1,6 @@ import BackupPrivateKey, { IBackupPrivateKey } from "./backupPrivateKey"; import Bot, { IBot } from "./bot"; +import BotOrg, { IBotOrg } from "./botOrg"; import BotKey, { IBotKey } from "./botKey"; import IncidentContactOrg, { IIncidentContactOrg } from "./incidentContactOrg"; import Integration, { IIntegration } from "./integration"; @@ -31,6 +32,8 @@ export { IBackupPrivateKey, Bot, IBot, + BotOrg, + IBotOrg, BotKey, IBotKey, IncidentContactOrg, diff --git a/backend/src/models/integration.ts b/backend/src/models/integration.ts index a443c3f836..e6673e77e3 100644 --- a/backend/src/models/integration.ts +++ b/backend/src/models/integration.ts @@ -1,11 +1,14 @@ -import { Schema, Types, model } from "mongoose"; import { INTEGRATION_AWS_PARAMETER_STORE, INTEGRATION_AWS_SECRET_MANAGER, INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_BITBUCKET, INTEGRATION_CHECKLY, INTEGRATION_CIRCLECI, INTEGRATION_CLOUDFLARE_PAGES, + INTEGRATION_CLOUD_66, + INTEGRATION_CODEFRESH, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, INTEGRATION_FLYIO, INTEGRATION_GITHUB, INTEGRATION_GITLAB, @@ -13,14 +16,16 @@ import { INTEGRATION_HEROKU, INTEGRATION_LARAVELFORGE, INTEGRATION_NETLIFY, + INTEGRATION_NORTHFLANK, INTEGRATION_RAILWAY, INTEGRATION_RENDER, INTEGRATION_SUPABASE, + INTEGRATION_TERRAFORM_CLOUD, INTEGRATION_TRAVISCI, INTEGRATION_VERCEL, - INTEGRATION_CODEFRESH, - INTEGRATION_WINDMILL, + INTEGRATION_WINDMILL } from "../variables"; +import { Schema, Types, model } from "mongoose"; export interface IIntegration { _id: Types.ObjectId; @@ -55,9 +60,14 @@ export interface IIntegration { | "travisci" | "supabase" | "checkly" + | "terraform-cloud" | "hashicorp-vault" | "cloudflare-pages" + | "bitbucket" | "codefresh" + | "digital-ocean-app-platform" + | "cloud-66" + | "northflank" | "windmill"; integrationAuth: Types.ObjectId; } @@ -146,10 +156,15 @@ const integrationSchema = new Schema( INTEGRATION_TRAVISCI, INTEGRATION_SUPABASE, INTEGRATION_CHECKLY, + INTEGRATION_TERRAFORM_CLOUD, INTEGRATION_HASHICORP_VAULT, INTEGRATION_CLOUDFLARE_PAGES, INTEGRATION_CODEFRESH, INTEGRATION_WINDMILL, + INTEGRATION_BITBUCKET, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, + INTEGRATION_CLOUD_66, + INTEGRATION_NORTHFLANK ], required: true, }, @@ -162,7 +177,7 @@ const integrationSchema = new Schema( type: String, required: true, default: "/", - }, + } }, { timestamps: true, diff --git a/backend/src/models/integrationAuth.ts b/backend/src/models/integrationAuth.ts index 219c1e428f..6791868cd0 100644 --- a/backend/src/models/integrationAuth.ts +++ b/backend/src/models/integrationAuth.ts @@ -1,4 +1,3 @@ -import { Document, Schema, Types, model } from "mongoose"; import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_BASE64, @@ -6,8 +5,12 @@ import { INTEGRATION_AWS_PARAMETER_STORE, INTEGRATION_AWS_SECRET_MANAGER, INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_BITBUCKET, INTEGRATION_CIRCLECI, INTEGRATION_CLOUDFLARE_PAGES, + INTEGRATION_CLOUD_66, + INTEGRATION_CODEFRESH, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, INTEGRATION_FLYIO, INTEGRATION_GITHUB, INTEGRATION_GITLAB, @@ -15,19 +18,45 @@ import { INTEGRATION_HEROKU, INTEGRATION_LARAVELFORGE, INTEGRATION_NETLIFY, + INTEGRATION_NORTHFLANK, INTEGRATION_RAILWAY, INTEGRATION_RENDER, INTEGRATION_SUPABASE, + INTEGRATION_TERRAFORM_CLOUD, INTEGRATION_TRAVISCI, INTEGRATION_VERCEL, - INTEGRATION_CODEFRESH, INTEGRATION_WINDMILL } from "../variables"; +import { Document, Schema, Types, model } from "mongoose"; export interface IIntegrationAuth extends Document { _id: Types.ObjectId; workspace: Types.ObjectId; - integration: 'heroku' | 'vercel' | 'netlify' | 'github' | 'gitlab' | 'render' | 'railway' | 'flyio' | 'azure-key-vault' | 'laravel-forge' | 'circleci' | 'travisci' | 'supabase' | 'aws-parameter-store' | 'aws-secret-manager' | 'checkly' | 'cloudflare-pages' | 'windmill' | 'codefresh'; + integration: + | "heroku" + | "vercel" + | "netlify" + | "github" + | "gitlab" + | "render" + | "railway" + | "flyio" + | "azure-key-vault" + | "laravel-forge" + | "circleci" + | "travisci" + | "supabase" + | "aws-parameter-store" + | "aws-secret-manager" + | "checkly" + | "cloudflare-pages" + | "codefresh" + | "digital-ocean-app-platform" + | "bitbucket" + | "cloud-66" + | "terraform-cloud" + | "northflank" + | "windmill"; teamId: string; accountId: string; url: string; @@ -71,10 +100,15 @@ const integrationAuthSchema = new Schema( INTEGRATION_LARAVELFORGE, INTEGRATION_TRAVISCI, INTEGRATION_SUPABASE, + INTEGRATION_TERRAFORM_CLOUD, INTEGRATION_HASHICORP_VAULT, INTEGRATION_CLOUDFLARE_PAGES, INTEGRATION_CODEFRESH, INTEGRATION_WINDMILL, + INTEGRATION_BITBUCKET, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, + INTEGRATION_CLOUD_66, + INTEGRATION_NORTHFLANK ], required: true, }, diff --git a/backend/src/models/user.ts b/backend/src/models/user.ts index b5f0027ca1..6559b1b7e7 100644 --- a/backend/src/models/user.ts +++ b/backend/src/models/user.ts @@ -1,7 +1,9 @@ import { Document, Schema, Types, model } from "mongoose"; export enum AuthProvider { + EMAIL = "email", GOOGLE = "google", + OKTA_SAML = "okta-saml" } export interface IUser extends Document { diff --git a/backend/src/routes/v1/auth.ts b/backend/src/routes/v1/auth.ts index fcf9869cc4..ae85aa36c3 100644 --- a/backend/src/routes/v1/auth.ts +++ b/backend/src/routes/v1/auth.ts @@ -1,7 +1,6 @@ import express from "express"; const router = express.Router(); import { body } from "express-validator"; -import passport from "passport"; import { requireAuth, validateRequest } from "../../middleware"; import { authController } from "../../controllers/v1"; import { authLimiter } from "../../helpers/rateLimiter"; @@ -44,21 +43,6 @@ router.post( authController.checkAuth ); -router.get( - "/redirect/google", - authLimiter, - passport.authenticate("google", { - scope: ["profile", "email"], - session: false, - }), -); - -router.get( - "/callback/google", - passport.authenticate("google", { failureRedirect: "/login/provider/error", session: false }), - authController.handleAuthProviderCallback, -); - router.get( "/common-passwords", authLimiter, diff --git a/backend/src/routes/v1/integrationAuth.ts b/backend/src/routes/v1/integrationAuth.ts index 28fa65af80..4fdc290e7c 100644 --- a/backend/src/routes/v1/integrationAuth.ts +++ b/backend/src/routes/v1/integrationAuth.ts @@ -81,6 +81,7 @@ router.get( }), param("integrationAuthId"), query("teamId"), + query("workspaceSlug"), validateRequest, integrationAuthController.getIntegrationAuthApps ); @@ -141,6 +142,33 @@ router.get( integrationAuthController.getIntegrationAuthRailwayServices ); +router.get( + "/:integrationAuthId/bitbucket/workspaces", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireIntegrationAuthorizationAuth({ + acceptedRoles: [ADMIN, MEMBER], + }), + param("integrationAuthId").exists().isString(), + validateRequest, + integrationAuthController.getIntegrationAuthBitBucketWorkspaces +); + +router.get( + "/:integrationAuthId/northflank/secret-groups", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireIntegrationAuthorizationAuth({ + acceptedRoles: [ADMIN, MEMBER], + }), + param("integrationAuthId").exists().isString(), + query("appId").exists().isString(), + validateRequest, + integrationAuthController.getIntegrationAuthNorthflankSecretGroups +); + router.delete( "/:integrationAuthId", requireAuth({ diff --git a/backend/src/routes/v1/secretImport.ts b/backend/src/routes/v1/secretImport.ts index 60ed16bc81..655fbd9338 100644 --- a/backend/src/routes/v1/secretImport.ts +++ b/backend/src/routes/v1/secretImport.ts @@ -46,7 +46,7 @@ router.delete( body("secretImportPath").isString().exists().trim(), body("secretImportEnv").isString().exists().trim(), validateRequest, - secretImportController.updateSecretImport + secretImportController.deleteSecretImport ); router.get( diff --git a/backend/src/routes/v1/webhook.ts b/backend/src/routes/v1/webhook.ts index 2091fa4471..11507e68ba 100644 --- a/backend/src/routes/v1/webhook.ts +++ b/backend/src/routes/v1/webhook.ts @@ -2,7 +2,7 @@ import express from "express"; const router = express.Router(); import { requireAuth, requireWorkspaceAuth, validateRequest } from "../../middleware"; import { body, param, query } from "express-validator"; -import { ADMIN, AUTH_MODE_JWT, AUTH_MODE_SERVICE_ACCOUNT, MEMBER } from "../../variables"; +import { ADMIN, AUTH_MODE_JWT, MEMBER } from "../../variables"; import { webhookController } from "../../controllers/v1"; router.post( diff --git a/backend/src/routes/v2/users.ts b/backend/src/routes/v2/users.ts index 7815513ec7..94d912b489 100644 --- a/backend/src/routes/v2/users.ts +++ b/backend/src/routes/v2/users.ts @@ -10,6 +10,9 @@ import { AUTH_MODE_API_KEY, AUTH_MODE_JWT, } from "../../variables"; +import { + AuthProvider +} from "../../models"; router.get( "/me", @@ -34,11 +37,25 @@ router.patch( requireAuth({ acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], }), - body("firstName").exists(), + body("firstName").exists().isString(), + body("lastName").isString(), validateRequest, usersController.updateName ); +router.patch( + "/me/auth-provider", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY], + }), + body("authProvider").exists().isString().isIn([ + AuthProvider.EMAIL, + AuthProvider.GOOGLE + ]), + validateRequest, + usersController.updateAuthProvider +); + router.get( "/me/organizations", requireAuth({ @@ -76,7 +93,7 @@ router.delete( usersController.deleteAPIKey ); -router.get( // new +router.get( "/me/sessions", requireAuth({ acceptedAuthModes: [AUTH_MODE_JWT], @@ -84,7 +101,7 @@ router.get( // new usersController.getMySessions ); -router.delete( // new +router.delete( "/me/sessions", requireAuth({ acceptedAuthModes: [AUTH_MODE_JWT], diff --git a/backend/src/routes/v3/secrets.ts b/backend/src/routes/v3/secrets.ts index 445503dec8..5a33e30ff5 100644 --- a/backend/src/routes/v3/secrets.ts +++ b/backend/src/routes/v3/secrets.ts @@ -18,10 +18,10 @@ import { router.get( "/raw", - query("workspaceId").exists().isString().trim(), - query("environment").exists().isString().trim(), + query("workspaceId").optional().isString().trim(), + query("environment").optional().isString().trim(), query("secretPath").default("/").isString().trim(), - query("include_imports").isBoolean().default(false), + query("include_imports").optional().isBoolean().default(false), validateRequest, requireAuth({ acceptedAuthModes: [ @@ -31,14 +31,6 @@ router.get( AUTH_MODE_SERVICE_ACCOUNT ] }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - locationWorkspaceId: "query", - locationEnvironment: "query", - requiredPermissions: [PERMISSION_READ_SECRETS], - requireBlindIndicesEnabled: true, - requireE2EEOff: true - }), secretsController.getSecretsRaw ); @@ -64,7 +56,8 @@ router.get( locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true + requireE2EEOff: true, + checkIPAllowlist: false }), secretsController.getSecretByNameRaw ); @@ -92,7 +85,8 @@ router.post( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true + requireE2EEOff: true, + checkIPAllowlist: false }), secretsController.createSecretRaw ); @@ -120,7 +114,8 @@ router.patch( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true + requireE2EEOff: true, + checkIPAllowlist: false }), secretsController.updateSecretByNameRaw ); @@ -147,7 +142,8 @@ router.delete( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: true + requireE2EEOff: true, + checkIPAllowlist: false }), secretsController.deleteSecretByNameRaw ); @@ -172,7 +168,8 @@ router.get( locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false + requireE2EEOff: false, + checkIPAllowlist: false }), secretsController.getSecrets ); @@ -207,7 +204,8 @@ router.post( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false + requireE2EEOff: false, + checkIPAllowlist: false }), secretsController.createSecret ); @@ -233,7 +231,8 @@ router.get( locationWorkspaceId: "query", locationEnvironment: "query", requiredPermissions: [PERMISSION_READ_SECRETS], - requireBlindIndicesEnabled: true + requireBlindIndicesEnabled: true, + checkIPAllowlist: false }), secretsController.getSecretByName ); @@ -263,7 +262,8 @@ router.patch( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false + requireE2EEOff: false, + checkIPAllowlist: false }), secretsController.updateSecretByName ); @@ -290,7 +290,8 @@ router.delete( locationEnvironment: "body", requiredPermissions: [PERMISSION_WRITE_SECRETS], requireBlindIndicesEnabled: true, - requireE2EEOff: false + requireE2EEOff: false, + checkIPAllowlist: false }), secretsController.deleteSecretByName ); diff --git a/backend/src/routes/v3/signup.ts b/backend/src/routes/v3/signup.ts index eb3ff9023d..52b3a8fa05 100644 --- a/backend/src/routes/v3/signup.ts +++ b/backend/src/routes/v3/signup.ts @@ -21,7 +21,8 @@ router.post( body("salt").exists().isString().trim().notEmpty(), body("verifier").exists().isString().trim().notEmpty(), body("organizationName").exists().isString().trim().notEmpty(), - body("providerAuthToken").isString().trim().optional({nullable: true}), + body("providerAuthToken").isString().trim().optional({ nullable: true }), + body("attributionSource").optional().isString().trim(), validateRequest, signupController.completeAccountSignup, ); diff --git a/backend/src/services/BotOrgService.ts b/backend/src/services/BotOrgService.ts new file mode 100644 index 0000000000..070a440581 --- /dev/null +++ b/backend/src/services/BotOrgService.ts @@ -0,0 +1,12 @@ +import { Types } from "mongoose"; +import { getSymmetricKeyHelper } from "../helpers/botOrg"; + +// TODO: DOCstrings + +class BotOrgService { + static async getSymmetricKey(organizationId: Types.ObjectId) { + return await getSymmetricKeyHelper(organizationId); + } +} + +export default BotOrgService; \ No newline at end of file diff --git a/backend/src/services/index.ts b/backend/src/services/index.ts index a0c1f8a5b1..5b6d42f264 100644 --- a/backend/src/services/index.ts +++ b/backend/src/services/index.ts @@ -2,6 +2,7 @@ import DatabaseService from "./DatabaseService"; // import { logTelemetryMessage, getPostHogClient } from './TelemetryService'; import TelemetryService from "./TelemetryService"; import BotService from "./BotService"; +import BotOrgService from "./BotOrgService"; import EventService from "./EventService"; import IntegrationService from "./IntegrationService"; import TokenService from "./TokenService"; @@ -12,9 +13,10 @@ export { TelemetryService, DatabaseService, BotService, + BotOrgService, EventService, IntegrationService, TokenService, SecretService, GithubSecretScanningService -}; \ No newline at end of file +} diff --git a/backend/src/types/express/index.d.ts b/backend/src/types/express/index.d.ts index f3b2700da2..c7713a3276 100644 --- a/backend/src/types/express/index.d.ts +++ b/backend/src/types/express/index.d.ts @@ -20,6 +20,7 @@ declare global { workspace: any; membership: any; targetMembership: any; + isUserCompleted: boolean; providerAuthToken: any; organization: any; membershipOrg: any; diff --git a/backend/src/utils/aes-gcm.ts b/backend/src/utils/aes-gcm.ts index 4457616a6f..21734611b9 100644 --- a/backend/src/utils/aes-gcm.ts +++ b/backend/src/utils/aes-gcm.ts @@ -4,8 +4,6 @@ const ALGORITHM = "aes-256-gcm"; const BLOCK_SIZE_BYTES = 16; export default class AesGCM { - constructor() {} - static encrypt( text: string, secret: string diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts index 6970292c4c..ded2f3eb3e 100644 --- a/backend/src/utils/auth.ts +++ b/backend/src/utils/auth.ts @@ -1,11 +1,14 @@ import express from "express"; import passport from "passport"; +import { Types } from "mongoose"; import { AuthData } from "../interfaces/middleware"; import { AuthProvider, + MembershipOrg, + Organization, ServiceAccount, ServiceTokenData, - User, + User } from "../models"; import { createToken } from "../helpers/auth"; import { @@ -14,11 +17,15 @@ import { getJwtProviderAuthLifetime, getJwtProviderAuthSecret, } from "../config"; +import { getSSOConfigHelper } from "../ee/helpers/organizations"; +import { InternalServerError, OrganizationNotFoundError } from "./errors"; +import { INVITED, MEMBER } from "../variables"; +import { getSiteURL } from "../config"; // eslint-disable-next-line @typescript-eslint/no-var-requires const GoogleStrategy = require("passport-google-oauth20").Strategy; - -// TODO: find a more optimal folder structure to store these types of functions +// eslint-disable-next-line @typescript-eslint/no-var-requires +const { MultiSamlStrategy } = require("@node-saml/passport-saml"); /** * Returns an object containing the id of the authentication data payload @@ -39,7 +46,6 @@ const getAuthDataPayloadIdObj = (authData: AuthData) => { } }; - /** * Returns an object containing the user associated with the authentication data payload * @param {AuthData} authData - authentication data object @@ -56,7 +62,7 @@ const getAuthDataPayloadUserObj = (authData: AuthData) => { } if (authData.authPayload instanceof ServiceTokenData) { - return { user: authData.authPayload.user }; + return { user: authData.authPayload.user };0 } } @@ -68,47 +74,148 @@ const initializePassport = async () => { passReqToCallback: true, clientID: googleClientId, clientSecret: googleClientSecret, - callbackURL: "/api/v1/auth/callback/google", + callbackURL: "/api/v1/sso/google", scope: ["profile", " email"], }, async ( req: express.Request, accessToken: string, refreshToken: string, profile: any, - cb: any + done: any ) => { try { const email = profile.emails[0].value; + const firstName = profile.name.givenName; + const lastName = profile.name.familyName; + let user = await User.findOne({ - authProvider: AuthProvider.GOOGLE, - authId: profile.id, - }).select("+publicKey") + email + }).select("+publicKey"); + + if (user && user.authProvider !== AuthProvider.GOOGLE) { + done(InternalServerError()); + } if (!user) { user = await new User({ email, authProvider: AuthProvider.GOOGLE, authId: profile.id, + firstName, + lastName }).save(); } + const isUserCompleted = !!user.publicKey; const providerAuthToken = createToken({ payload: { userId: user._id.toString(), email: user.email, + firstName, + lastName, authProvider: user.authProvider, - isUserCompleted: !!user.publicKey, + isUserCompleted, + ...(req.query.state ? { + callbackPort: req.query.state as string + } : {}) }, expiresIn: await getJwtProviderAuthLifetime(), secret: await getJwtProviderAuthSecret(), }); + req.isUserCompleted = isUserCompleted; req.providerAuthToken = providerAuthToken; - cb(null, profile); + done(null, profile); } catch (err) { - cb(null, false); + done(null, false); } })); + + passport.use("saml", new MultiSamlStrategy( + { + passReqToCallback: true, + getSamlOptions: async (req: any, done: any) => { + const { ssoIdentifier } = req.params; + + const ssoConfig = await getSSOConfigHelper({ + ssoConfigId: new Types.ObjectId(ssoIdentifier) + }); + + const samlConfig = ({ + path: "/api/v1/auth/callback/saml", + callbackURL: `${await getSiteURL()}/api/v1/auth/callback/saml`, + entryPoint: ssoConfig.entryPoint, + issuer: ssoConfig.issuer, + cert: ssoConfig.cert, + audience: ssoConfig.audience + }); + + req.ssoConfig = ssoConfig; + + done(null, samlConfig); + }, + }, + async (req: any, profile: any, done: any) => { + if (!req.ssoConfig.isActive) return done(InternalServerError()); + + const organization = await Organization.findById(req.ssoConfig.organization); + + if (!organization) return done(OrganizationNotFoundError()); + + const email = profile.email; + const firstName = profile.firstName; + const lastName = profile.lastName; + + let user = await User.findOne({ + email + }).select("+publicKey"); + + if (user && user.authProvider !== AuthProvider.OKTA_SAML) { + done(InternalServerError()); + } + + if (!user) { + user = await new User({ + email, + authProvider: AuthProvider.OKTA_SAML, + authId: profile.id, + firstName, + lastName + }).save(); + + await new MembershipOrg({ + inviteEmail: email, + user: user._id, + organization: organization?._id, + role: MEMBER, + status: INVITED + }).save(); + } + + const isUserCompleted = !!user.publicKey; + const providerAuthToken = createToken({ + payload: { + userId: user._id.toString(), + email: user.email, + firstName, + lastName, + organizationName: organization?.name, + authProvider: user.authProvider, + isUserCompleted, + ...(req.body.RelayState ? { + callbackPort: req.body.RelayState as string + } : {}) + }, + expiresIn: await getJwtProviderAuthLifetime(), + secret: await getJwtProviderAuthSecret(), + }); + + req.isUserCompleted = isUserCompleted; + req.providerAuthToken = providerAuthToken; + + done(null, profile); + } + )); } export { diff --git a/backend/src/utils/errors.ts b/backend/src/utils/errors.ts index 196eefdfe3..42cc20509b 100644 --- a/backend/src/utils/errors.ts +++ b/backend/src/utils/errors.ts @@ -46,7 +46,7 @@ export const BadRequestError = (error?: Partial) => new Req stack: error?.stack, }); -export const ResourceNotFound = (error?: Partial) => new RequestError({ +export const ResourceNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.INFO, statusCode: error?.statusCode ?? 404, type: error?.type ?? "resource_not_found", diff --git a/backend/src/utils/ip/index.ts b/backend/src/utils/ip/index.ts new file mode 100644 index 0000000000..17c8ce5a6c --- /dev/null +++ b/backend/src/utils/ip/index.ts @@ -0,0 +1 @@ +export * from "./ip"; \ No newline at end of file diff --git a/backend/src/utils/ip/ip.ts b/backend/src/utils/ip/ip.ts new file mode 100644 index 0000000000..ac3b17149b --- /dev/null +++ b/backend/src/utils/ip/ip.ts @@ -0,0 +1,101 @@ +import net from "net"; +import { IPType } from "../../ee/models"; +import { InternalServerError } from "../errors"; + +/** + * Return details of IP [ip]: + * - If [ip] is a specific IP address then return the IPv4/IPv6 address + * - If [ip] is a subnet then return the network IPv4/IPv6 address and prefix + * @param {String} ip - ip whose details to return + * @returns + */ +export const extractIPDetails = (ip: string) => { + if (net.isIPv4(ip)) return ({ + ipAddress: ip, + type: IPType.IPV4 + }); + + if (net.isIPv6(ip)) return ({ + ipAddress: ip, + type: IPType.IPV6 + }); + + const [ipNet, prefix] = ip.split("/"); + + let type; + switch (net.isIP(ipNet)) { + case 4: + type = IPType.IPV4; + break; + case 6: + type = IPType.IPV6; + break; + default: + throw InternalServerError({ + message: "Failed to extract IP details" + }); + } + + return ({ + ipAddress: ipNet, + type, + prefix: parseInt(prefix, 10) + }); +} + +/** + * Checks if a given string is a valid CIDR block. + * + * The function checks if the input string is a valid IPv4 or IPv6 address in CIDR notation. + * + * CIDR notation includes a network address followed by a slash ('/') and a prefix length. + * For IPv4, the prefix length must be between 0 and 32. For IPv6, it must be between 0 and 128. + * If the input string is not a valid CIDR block, the function returns `false`. + * + * @param {string} cidr - string in CIDR notation + * @returns {boolean} Returns `true` if the string is a valid CIDR block, `false` otherwise. + * +*/ +export const isValidCidr = (cidr: string): boolean => { + const [ip, prefix] = cidr.split("/"); + + const prefixNum = parseInt(prefix, 10); + + // ensure prefix exists and is a number within the appropriate range for each IP version + if (!prefix || isNaN(prefixNum) || + (net.isIPv4(ip) && (prefixNum < 0 || prefixNum > 32)) || + (net.isIPv6(ip) && (prefixNum < 0 || prefixNum > 128))) { + return false; + } + + // ensure the IP portion of the CIDR block is a valid IPv4 or IPv6 address + if (!net.isIPv4(ip) && !net.isIPv6(ip)) { + return false; + } + + return true; +} + +/** + * Checks if a given string is a valid IPv4/IPv6 address or a valid CIDR block. + * + * If the string contains a slash ('/'), it treats the input as a CIDR block and checks its validity. + * Otherwise, it treats the string as a standalone IP address (either IPv4 or IPv6) and checks its validity. + * + * @param {string} input - The string to be checked. It could be an IP address or a CIDR block. + * @returns {boolean} Returns `true` if the string is a valid IP address (either IPv4 or IPv6) or a valid CIDR block, `false` otherwise. + * +*/ +export const isValidIpOrCidr = (ip: string): boolean => { + // if the string contains a slash, treat it as a CIDR block + if (ip.includes("/")) { + return isValidCidr(ip); + } + + // otherwise, treat it as a standalone IP address + if (net.isIPv4(ip) || net.isIPv6(ip)) { + return true; + } + + return false; +} \ No newline at end of file diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts index 801a75e6fa..cc3399d293 100644 --- a/backend/src/utils/setup/backfillData.ts +++ b/backend/src/utils/setup/backfillData.ts @@ -3,13 +3,21 @@ import crypto from "crypto"; import { Types } from "mongoose"; import { encryptSymmetric128BitHexKeyUTF8 } from "../crypto"; import { EESecretService } from "../../ee/services"; -import { ISecretVersion, SecretSnapshot, SecretVersion } from "../../ee/models"; +import { + IPType, + ISecretVersion, + SecretSnapshot, + SecretVersion, + TrustedIP +} from "../../ee/models"; import { BackupPrivateKey, Bot, + BotOrg, ISecret, Integration, IntegrationAuth, + Organization, Secret, SecretBlindIndexData, ServiceTokenData, @@ -137,6 +145,101 @@ export const backfillBots = async () => { await Bot.insertMany(botsToInsert); }; +/** + * Backfill organization bots to ensure that every organization has a bot + */ +export const backfillBotOrgs = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const organizationIdsWithBot = await BotOrg.distinct("organization"); + const organizationIdsToAddBot = await Organization.distinct("_id", { + _id: { + $nin: organizationIdsWithBot + } + }); + + if (organizationIdsToAddBot.length === 0) return; + + const botsToInsert = await Promise.all( + organizationIdsToAddBot.map(async (organizationToAddBot) => { + const { publicKey, privateKey } = generateKeyPair(); + + const key = client.createSymmetricKey(); + + if (rootEncryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv: privateKeyIV, + tag: privateKeyTag + } = client.encryptSymmetric(privateKey, rootEncryptionKey); + + const { + ciphertext: encryptedSymmetricKey, + iv: symmetricKeyIV, + tag: symmetricKeyTag + } = client.encryptSymmetric(key, rootEncryptionKey); + + return new BotOrg({ + name: "Infisical Bot", + organization: organizationToAddBot, + publicKey, + encryptedSymmetricKey, + symmetricKeyIV, + symmetricKeyTag, + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, + encryptedPrivateKey, + privateKeyIV, + privateKeyTag, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_BASE64 + }); + } else if (encryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv: privateKeyIV, + tag: privateKeyTag + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: privateKey, + key: encryptionKey + }); + + const { + ciphertext: encryptedSymmetricKey, + iv: symmetricKeyIV, + tag: symmetricKeyTag + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: key, + key: encryptionKey + }); + + return new BotOrg({ + name: "Infisical Bot", + organization: organizationToAddBot, + publicKey, + encryptedSymmetricKey, + symmetricKeyIV, + symmetricKeyTag, + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, + encryptedPrivateKey, + privateKeyIV, + privateKeyTag, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 + }); + } + + throw InternalServerError({ + message: "Failed to backfill organization bots due to missing encryption key" + }); + }) + ); + + await BotOrg.insertMany(botsToInsert); +}; + /** * Backfill secret blind index data to ensure that every workspace * has a secret blind index data @@ -452,3 +555,79 @@ export const backfillServiceTokenMultiScope = async () => { console.log("Migration: Service token migration v2 complete"); }; + +/** + * Backfill each workspace without any registered trusted IPs to + * have default trusted ip of 0.0.0.0/0 + */ +export const backfillTrustedIps = async () => { + const workspaceIdsWithTrustedIps = await TrustedIP.distinct("workspace"); + const workspaceIdsToAddTrustedIp = await Workspace.distinct("_id", { + _id: { + $nin: workspaceIdsWithTrustedIps + } + }); + + if (workspaceIdsToAddTrustedIp.length > 0) { + const operations: { + updateOne: { + filter: { + workspace: Types.ObjectId; + ipAddress: string; + }, + update: { + workspace: Types.ObjectId; + ipAddress: string; + type: string; + prefix: number; + isActive: boolean; + comment: string; + }, + upsert: boolean; + } + }[] = []; + + workspaceIdsToAddTrustedIp.forEach((workspaceId) => { + // default IPv4 trusted CIDR + operations.push({ + updateOne: { + filter: { + workspace: workspaceId, + ipAddress: "0.0.0.0" + }, + update: { + workspace: workspaceId, + ipAddress: "0.0.0.0", + type: IPType.IPV4.toString(), + prefix: 0, + isActive: true, + comment: "" + }, + upsert: true + } + }); + + // default IPv6 trusted CIDR + operations.push({ + updateOne: { + filter: { + workspace: workspaceId, + ipAddress: "::" + }, + update: { + workspace: workspaceId, + ipAddress: "::", + type: IPType.IPV6.toString(), + prefix: 0, + isActive: true, + comment: "" + }, + upsert: true + } + }); + }); + + await TrustedIP.bulkWrite(operations); + console.log("Backfill: Trusted IPs complete"); + } +} diff --git a/backend/src/utils/setup/index.ts b/backend/src/utils/setup/index.ts index 00f41fe676..2f88b29130 100644 --- a/backend/src/utils/setup/index.ts +++ b/backend/src/utils/setup/index.ts @@ -7,6 +7,7 @@ import { createTestUserForDevelopment } from "../addDevelopmentUser"; // eslint-disable-next-line @typescript-eslint/no-var-requires import { validateEncryptionKeysConfig } from "./validateConfig"; import { + backfillBotOrgs, backfillBots, backfillEncryptionMetadata, backfillIntegration, @@ -14,9 +15,14 @@ import { backfillSecretFolders, backfillSecretVersions, backfillServiceToken, - backfillServiceTokenMultiScope + backfillServiceTokenMultiScope, + backfillTrustedIps } from "./backfillData"; -import { reencryptBotPrivateKeys, reencryptSecretBlindIndexDataSalts } from "./reencryptData"; +import { + reencryptBotOrgKeys, + reencryptBotPrivateKeys, + reencryptSecretBlindIndexDataSalts +} from "./reencryptData"; import { getClientIdGoogle, getClientSecretGoogle, @@ -72,16 +78,19 @@ export const setup = async () => { // backfilling data to catch up with new collections and updated fields await backfillSecretVersions(); await backfillBots(); + await backfillBotOrgs(); await backfillSecretBlindIndexData(); await backfillEncryptionMetadata(); await backfillSecretFolders(); await backfillServiceToken(); await backfillIntegration(); await backfillServiceTokenMultiScope(); + await backfillTrustedIps(); // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY // to base64 256-bit ROOT_ENCRYPTION_KEY await reencryptBotPrivateKeys(); + await reencryptBotOrgKeys(); await reencryptSecretBlindIndexDataSalts(); // initializing Sentry diff --git a/backend/src/utils/setup/reencryptData.ts b/backend/src/utils/setup/reencryptData.ts index 7ea5db2026..1a782ab8fb 100644 --- a/backend/src/utils/setup/reencryptData.ts +++ b/backend/src/utils/setup/reencryptData.ts @@ -1,6 +1,8 @@ import { Bot, + BotOrg, IBot, + IBotOrg, ISecretBlindIndexData, SecretBlindIndexData, } from "../../models"; @@ -17,7 +19,7 @@ import { } from "../../variables"; /** - * Re-encrypt bot private keys from hex 128-bit ENCRYPTION_KEY + * Re-encrypt bot private keys from under hex 128-bit ENCRYPTION_KEY * to base64 256-bit ROOT_ENCRYPTION_KEY */ export const reencryptBotPrivateKeys = async () => { @@ -70,6 +72,79 @@ export const reencryptBotPrivateKeys = async () => { } } +/** + * Re-encrypt organization bot keys (symmetric and private) from under hex 128-bit ENCRYPTION_KEY + * to base64 256-bit ROOT_ENCRYPTION_KEY + */ +export const reencryptBotOrgKeys = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if (encryptionKey && rootEncryptionKey) { + // 1: re-encrypt organization bot keys under ROOT_ENCRYPTION_KEY + const botOrgs = await BotOrg.find({ + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_UTF8, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_UTF8 + }).select("+encryptedPrivateKey iv tag algorithm keyEncoding"); + + if (botOrgs.length === 0) return; + + const operationsBotOrg = await Promise.all( + botOrgs.map(async (botOrg: IBotOrg) => { + const privateKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: botOrg.encryptedPrivateKey, + iv: botOrg.privateKeyIV, + tag: botOrg.privateKeyTag, + key: encryptionKey + }); + + const { + ciphertext: encryptedPrivateKey, + iv: privateKeyIV, + tag: privateKeyTag, + } = client.encryptSymmetric(privateKey, rootEncryptionKey); + + const symmetricKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: botOrg.encryptedSymmetricKey, + iv: botOrg.symmetricKeyIV, + tag: botOrg.symmetricKeyTag, + key: encryptionKey + }); + + const { + ciphertext: encryptedSymmetricKey, + iv: symmetricKeyIV, + tag: symmetricKeyTag, + } = client.encryptSymmetric(symmetricKey, rootEncryptionKey); + + return ({ + updateOne: { + filter: { + _id: botOrg._id, + }, + update: { + encryptedSymmetricKey, + symmetricKeyIV, + symmetricKeyTag, + symmetricKeyAlgorithm: ALGORITHM_AES_256_GCM, + symmetricKeyKeyEncoding: ENCODING_SCHEME_BASE64, + encryptedPrivateKey, + privateKeyIV, + privateKeyTag, + privateKeyAlgorithm: ALGORITHM_AES_256_GCM, + privateKeyKeyEncoding: ENCODING_SCHEME_BASE64, + }, + }, + }) + }) + ); + + await BotOrg.bulkWrite(operationsBotOrg); + } +} + /** * Re-encrypt secret blind index data salts from hex 128-bit ENCRYPTION_KEY * to base64 256-bit ROOT_ENCRYPTION_KEY diff --git a/backend/src/validation/workspace.ts b/backend/src/validation/workspace.ts index cdc2771f40..618ccb02fd 100644 --- a/backend/src/validation/workspace.ts +++ b/backend/src/validation/workspace.ts @@ -1,14 +1,15 @@ +import net from "net"; import { Types } from "mongoose"; import { - IServiceAccount, - IServiceTokenData, - IUser, SecretBlindIndexData, ServiceAccount, ServiceTokenData, User, Workspace, } from "../models"; +import { + TrustedIP +} from "../ee/models"; import { validateServiceAccountClientForWorkspace } from "./serviceAccount"; import { validateUserClientForWorkspace } from "./user"; import { validateServiceTokenDataClientForWorkspace } from "./serviceTokenData"; @@ -24,6 +25,8 @@ import { AUTH_MODE_SERVICE_TOKEN, } from "../variables"; import { BotService } from "../services"; +import { AuthData } from "../interfaces/middleware"; +import { extractIPDetails } from "../utils/ip"; /** * Validate authenticated clients for workspace with id [workspaceId] based @@ -43,17 +46,16 @@ export const validateClientForWorkspace = async ({ requiredPermissions, requireBlindIndicesEnabled, requireE2EEOff, + checkIPAllowlist }: { - authData: { - authMode: string; - authPayload: IUser | IServiceAccount | IServiceTokenData; - }; + authData: AuthData; workspaceId: Types.ObjectId; environment?: string; acceptedRoles: Array<"admin" | "member">; requiredPermissions?: string[]; requireBlindIndicesEnabled: boolean; requireE2EEOff: boolean; + checkIPAllowlist: boolean; }) => { const workspace = await Workspace.findById(workspaceId); @@ -82,6 +84,8 @@ export const validateClientForWorkspace = async ({ message: "Failed workspace authorization due to end-to-end encryption not being disabled", }); } + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { const membership = await validateUserClientForWorkspace({ @@ -107,6 +111,40 @@ export const validateClientForWorkspace = async ({ } if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + if (checkIPAllowlist) { + const trustedIps = await TrustedIP.find({ + workspace: workspaceId + }); + + if (trustedIps.length > 0) { + // case: check the IP address of the inbound request against trusted IPs + + const blockList = new net.BlockList(); + + for (const trustedIp of trustedIps) { + if (trustedIp.prefix !== undefined) { + blockList.addSubnet( + trustedIp.ipAddress, + trustedIp.prefix, + trustedIp.type + ); + } else { + blockList.addAddress( + trustedIp.ipAddress, + trustedIp.type + ); + } + } + + const { type } = extractIPDetails(authData.authIP); + const check = blockList.check(authData.authIP, type); + + if (!check) throw UnauthorizedRequestError({ + message: "Failed workspace authorization" + }); + } + } + await validateServiceTokenDataClientForWorkspace({ serviceTokenData: authData.authPayload, workspaceId, diff --git a/backend/src/variables/integration.ts b/backend/src/variables/integration.ts index 3c8bea7bea..a649763c0a 100644 --- a/backend/src/variables/integration.ts +++ b/backend/src/variables/integration.ts @@ -1,5 +1,6 @@ import { getClientIdAzure, + getClientIdBitBucket, getClientIdGitHub, getClientIdGitLab, getClientIdHeroku, @@ -24,10 +25,15 @@ export const INTEGRATION_CIRCLECI = "circleci"; export const INTEGRATION_TRAVISCI = "travisci"; export const INTEGRATION_SUPABASE = "supabase"; export const INTEGRATION_CHECKLY = "checkly"; +export const INTEGRATION_TERRAFORM_CLOUD = "terraform-cloud"; export const INTEGRATION_HASHICORP_VAULT = "hashicorp-vault"; export const INTEGRATION_CLOUDFLARE_PAGES = "cloudflare-pages"; +export const INTEGRATION_BITBUCKET = "bitbucket"; export const INTEGRATION_CODEFRESH = "codefresh"; export const INTEGRATION_WINDMILL = "windmill"; +export const INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM = "digital-ocean-app-platform"; +export const INTEGRATION_CLOUD_66 = "cloud-66"; +export const INTEGRATION_NORTHFLANK = "northflank"; export const INTEGRATION_SET = new Set([ INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_HEROKU, @@ -42,10 +48,15 @@ export const INTEGRATION_SET = new Set([ INTEGRATION_TRAVISCI, INTEGRATION_SUPABASE, INTEGRATION_CHECKLY, + INTEGRATION_TERRAFORM_CLOUD, INTEGRATION_HASHICORP_VAULT, INTEGRATION_CLOUDFLARE_PAGES, INTEGRATION_CODEFRESH, - INTEGRATION_WINDMILL + INTEGRATION_WINDMILL, + INTEGRATION_BITBUCKET, + INTEGRATION_DIGITAL_OCEAN_APP_PLATFORM, + INTEGRATION_CLOUD_66, + INTEGRATION_NORTHFLANK ]); // integration types @@ -60,6 +71,7 @@ export const INTEGRATION_NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/toke export const INTEGRATION_GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token"; export const INTEGRATION_GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token"; +export const INTEGRATION_BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token" // integration apps endpoints export const INTEGRATION_HEROKU_API_URL = "https://api.heroku.com"; @@ -74,9 +86,14 @@ export const INTEGRATION_TRAVISCI_API_URL = "https://api.travis-ci.com"; export const INTEGRATION_SUPABASE_API_URL = "https://api.supabase.com"; export const INTEGRATION_LARAVELFORGE_API_URL = "https://forge.laravel.com"; export const INTEGRATION_CHECKLY_API_URL = "https://api.checklyhq.com"; +export const INTEGRATION_TERRAFORM_CLOUD_API_URL = "https://app.terraform.io"; export const INTEGRATION_CLOUDFLARE_PAGES_API_URL = "https://api.cloudflare.com"; +export const INTEGRATION_BITBUCKET_API_URL = "https://api.bitbucket.org"; export const INTEGRATION_CODEFRESH_API_URL = "https://g.codefresh.io/api"; export const INTEGRATION_WINDMILL_API_URL = "https://app.windmill.dev/api"; +export const INTEGRATION_DIGITAL_OCEAN_API_URL = "https://api.digitalocean.com"; +export const INTEGRATION_CLOUD_66_API_URL = "https://app.cloud66.com/api"; +export const INTEGRATION_NORTHFLANK_API_URL = "https://api.northflank.com"; export const getIntegrationOptions = async () => { const INTEGRATION_OPTIONS = [ @@ -198,6 +215,15 @@ export const getIntegrationOptions = async () => { clientId: await getClientIdGitLab(), docsLink: "", }, + { + name: "Terraform Cloud", + slug: "terraform-cloud", + image: "Terraform Cloud.png", + isAvailable: true, + type: "pat", + cliendId: "", + docsLink: "", + }, { name: "Travis CI", slug: "travisci", @@ -252,6 +278,15 @@ export const getIntegrationOptions = async () => { clientId: "", docsLink: "" }, + { + name: "BitBucket", + slug: "bitbucket", + image: "BitBucket.png", + isAvailable: true, + type: "oauth", + clientId: await getClientIdBitBucket(), + docsLink: "" + }, { name: "Codefresh", slug: "codefresh", @@ -268,9 +303,35 @@ export const getIntegrationOptions = async () => { isAvailable: true, type: "pat", clientId: "", + docsLink: "", + }, + { + name: "Digital Ocean App Platform", + slug: "digital-ocean-app-platform", + image: "Digital Ocean.png", + isAvailable: true, + type: "pat", + clientId: "", + docsLink: "", + }, + { + name: "Cloud 66", + slug: "cloud-66", + image: "Cloud 66.png", + isAvailable: true, + type: "pat", + clientId: "", + docsLink: "", + }, + { + name: "Northflank", + slug: "northflank", + image: "Northflank.png", + isAvailable: true, + type: "pat", + clientId: "", docsLink: "" }, - ] return INTEGRATION_OPTIONS; diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index 02fe163276..906723df83 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -143,13 +143,13 @@ var runCmd = &cobra.Command{ err = executeMultipleCommandWithEnvs(command, len(secretsByKey), env) if err != nil { - util.HandleError(err, "Unable to execute your chained command") + fmt.Println(err) } } else { err = executeSingleCommandWithEnvs(args, len(secretsByKey), env) if err != nil { - util.HandleError(err, "Unable to execute your single command") + fmt.Println(err) } } }, diff --git a/docs/api-reference/overview/examples/e2ee-disabled.mdx b/docs/api-reference/overview/examples/e2ee-disabled.mdx index 9864a1ff5d..1a9e575524 100644 --- a/docs/api-reference/overview/examples/e2ee-disabled.mdx +++ b/docs/api-reference/overview/examples/e2ee-disabled.mdx @@ -7,8 +7,7 @@ in plaintext. Effectively, this means each such secret operation only requires 1 - Retrieve all secrets for an Infisical project and environment. - + Retrieve all secrets for an Infisical project and environment. ```bash @@ -18,7 +17,12 @@ in plaintext. Effectively, this means each such secret operation only requires 1 ``` - + #### + + When using a [service token](../../../documentation/platform/token) with access to a single environment and path, you don't need to provide request parameters because the server will automatically scope the request to the defined environment/secrets path of the service token used. + For all other cases, request parameters are required. + + #### The ID of the workspace diff --git a/docs/changelog/overview.mdx b/docs/changelog/overview.mdx index 1394d12df3..d4982938f8 100644 --- a/docs/changelog/overview.mdx +++ b/docs/changelog/overview.mdx @@ -6,19 +6,26 @@ The changelog below reflects new product developments and updates on a monthly b ## July 2023 -- Released [secret referencing and importing](https://infisical.com/docs/documentation/platform/secret-reference) across folders and environments. -- Added the [intergation with Laravel Forge](https://infisical.com/docs/integrations/cloud/laravel-forge). +- Released [secret referencing and importing](https://infisical.com/docs/documentation/platform/secret-reference) across folders and environments. - Redesigned the project/organization experience. +- Added native [Laravel Forge integration](https://infisical.com/docs/integrations/cloud/laravel-forge). +- Added native [Codefresh integration](https://infisical.com/docs/integrations/cicd/codefresh) +- Added native [Bitbucket integration](https://infisical.com/docs/integrations/cicd/bitbucket) +- Added native [DigitalOcean App Platform integration](https://infisical.com/docs/integrations/cloud/digital-ocean-app-platform) +- Added native [Cloud66 integration](https://infisical.com/docs/integrations/cloud/cloud-66) +- Added support for Google SSO. +- Added support for [Okta SAML 2.0 authentication](https://infisical.com/docs/documentation/platform/saml) +- Released [folders / path-based secret storage](https://infisical.com/docs/documentation/platform/folder) +- Released [webhooks](https://infisical.com/docs/documentation/platform/webhooks) ## June 2023 - Released the [Terraform Provider](https://infisical.com/docs/integrations/frameworks/terraform#5-run-terraform). - Updated the usage and billing page. Added the free trial for the professional tier. - Added the intergation with [Checkly](https://infisical.com/docs/integrations/cloud/checkly), [Hashicorp Vault](https://infisical.com/docs/integrations/cloud/hashicorp-vault), and [Cloudflare Pages](https://infisical.com/docs/integrations/cloud/cloudflare-pages). -- Comleted a penetration test with a `very good` result. +- Completed a penetration test with a `very good` result. - Added support for multi-line secrets. - ## May 2023 - Released secret scanning capability for the CLI. @@ -26,7 +33,7 @@ The changelog below reflects new product developments and updates on a monthly b - Completed penetration test. - Released new landing page. - Started SOC 2 (Type II) compliance certification preparation. -- Released new deployment options for Fly.io, Digital Ocean and Render. +- Released new deployment options for Fly.io, Digital Ocean and Render. ## April 2023 diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx index ed3a78a976..434a39c515 100644 --- a/docs/cli/overview.mdx +++ b/docs/cli/overview.mdx @@ -3,7 +3,8 @@ title: 'Install' description: "Infisical's CLI is one of the best way to manage environments and secrets. Install it here" --- -The Infisical CLI can be used to access secrets across various environments, whether it's local development, CI/CD, staging, or production. +The Infisical CLI is powerful command line tool that can be used to retrieve, modify, export and inject secrets into any process or application as environment variables. +You can use it across various environments, whether it's local development, CI/CD, staging, or production. ## Installation @@ -57,7 +58,10 @@ The Infisical CLI can be used to access secrets across various environments, whe ```bash apk update && sudo apk add infisical ``` - + ### + + If you are installing the CLI in production environments, we highly recommend to set the version of the CLI to a specific version. This will help keep your CLI version consistent across reinstalls. [View versions](https://cloudsmith.io/~infisical/repos/infisical-cli/packages/) + Add Infisical repository @@ -71,7 +75,10 @@ The Infisical CLI can be used to access secrets across various environments, whe ```bash sudo yum install infisical ``` - + ### + + If you are installing the CLI in production environments, we highly recommend to set the version of the CLI to a specific version. This will help keep your CLI version consistent across reinstalls. [View versions](https://cloudsmith.io/~infisical/repos/infisical-cli/packages/) + Add Infisical repository @@ -86,7 +93,10 @@ The Infisical CLI can be used to access secrets across various environments, whe ```bash sudo apt-get update && sudo apt-get install -y infisical ``` - + ### + + If you are installing the CLI in production environments, we highly recommend to set the version of the CLI to a specific version. This will help keep your CLI version consistent across reinstalls. [View versions](https://cloudsmith.io/~infisical/repos/infisical-cli/packages/) + Use the `yay` package manager to install from the [Arch User Repository](https://aur.archlinux.org/packages/infisical-bin) @@ -95,6 +105,9 @@ The Infisical CLI can be used to access secrets across various environments, whe yay -S infisical-bin ``` + ### + + If you are installing the CLI in production environments, we highly recommend to set the version of the CLI to a specific version. This will help keep your CLI version consistent across reinstalls. [View versions](https://cloudsmith.io/~infisical/repos/infisical-cli/packages/) + - diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index 54a3c56dd4..4e3d212fee 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -8,7 +8,7 @@ The distinguishing factor, however, is the authentication method used. - To use the Infisical CLI in your development environment, simply run the following command and follow the interactive guide. + To use the Infisical CLI in your development environment, simply run the command below and follow the interactive guide. ```bash infisical login diff --git a/docs/contributing/developing.mdx b/docs/contributing/developing.mdx index 1c7708c99f..bc1bc8dd5a 100644 --- a/docs/contributing/developing.mdx +++ b/docs/contributing/developing.mdx @@ -82,4 +82,28 @@ Password: `testInfisical1` ```bash # To stop environment use Control+C (on Mac) CTRL+C (on Win) or docker-compose -f docker-compose.dev.yml down +``` + +## Starting Infisical docs locally + +We use [Mintlify](https://mintlify.com/) for our docs. + +#### Install Mintlify CLI. + +```bash +npm i -g mintlify +``` + +or + +```bash +yarn global add mintlify +``` + +#### Running the docs +Go to `docs` directory and run `mintlify dev`. This will start up the docs on `localhost:3000` + +```bash +# From the root directory +cd docs; mintlify dev; ``` \ No newline at end of file diff --git a/docs/documentation/getting-started/introduction.mdx b/docs/documentation/getting-started/introduction.mdx index 85ba1e59cb..1f04e17631 100644 --- a/docs/documentation/getting-started/introduction.mdx +++ b/docs/documentation/getting-started/introduction.mdx @@ -17,7 +17,7 @@ Start syncing environment variables with [Infisical Cloud](https://app.infisical Store secrets like API keys, database credentials, environment variables with Infisical -## Integrate with Infisical +## Access secrets @@ -31,11 +31,11 @@ Start syncing environment variables with [Infisical Cloud](https://app.infisical > Fetch secrets with any programming language on demand - + Inject secrets into Docker containers + You must be a project `admin` to manage your project's IP whitelist. + + +![IP whitelist](../../images/project-ip-whitelist.png) + +## Creating a trusted IP entry + +To create a trusted IP entry, head over to the **IP Whitelist** tab in your project. When creating an entry, +you can specify either a specific IP address like `192.0.2.1` or a CIDR range like `2001:db8::/32`; both IPv4 and IPv6 +formats are accepted. + +![IP whitelist add](../../images/project-ip-whitelist-add.png) diff --git a/docs/documentation/platform/saml.mdx b/docs/documentation/platform/saml.mdx new file mode 100644 index 0000000000..6f58f79004 --- /dev/null +++ b/docs/documentation/platform/saml.mdx @@ -0,0 +1,100 @@ +--- +title: "SSO" +description: "Log in to Infisical via SSO protocols" +--- + + + Infisical currently only supports SAML SSO authentication with [Okta as the + identity provider (IDP)](https://www.okta.com/). We're expanding support for + other IDPs in the coming months, so stay tuned with this issue + [here](https://github.com/Infisical/infisical/issues/442). + + +You can configure your organization in Infisical to have members authenticate with the platform via protocols like [SAML 2.0](https://en.wikipedia.org/wiki/SAML_2.0). + +To note, configuring SSO retains the end-to-end encrypted architecture of Infisical because we decouple the **authentication** and **decryption** steps. In all login with SSO implementations, +your IDP cannot and will not have access to the decryption key needed to decrypt your secrets. + +## Configuration + +Head over to your organization Settings > Authentication > SAML SSO Configuration. + +Next, press "Set up SAML SSO" in the SAML SSO and follow the instructions +below to configure SSO for your identity provider: + + + Note that only members with the `owner` or `admin` roles in an organization + can configure SSO for it. + + + + + 1. In the Okta Admin Portal, select Applications > Applications from the + navigation. On the Applications screen, select the Create App Integration + button. + + ![SAML Okta create app integration](../../images/saml-okta-1.png) + + 2. In the Create a New Application Integration dialog, select the SAML 2.0 radio button: + + ![SAML Okta create SAML 2.0 integration](../../images/saml-okta-2.png) + + 3. On the General Settings screen, give the application a unique, Infisical-specific name and select Next. + + 4. On the Configure SAML screen, configure the following fields: + + - Single sign on URL: `https://app.infisical.com/api/v1/sso/saml2/:identifier`; we'll update the `:identifier` part later in step 6. + - Audience URI (SP Entity ID): `https://app.infisical.com` + + ![SAML Okta configure IDP fields](../../images/saml-okta-3.png) + + + If you're self-hosting Infisical, then you will want to replace `https://app.infisical.com` with your own domain. + + + 4. Also on the Configure SAML screen, configure the Attribute Statements to map: + + - `id -> user.id`, + - `email -> user.email`, + - `firstName -> user.firstName` + - `lastName -> user.lastName` + + ![SAML Okta attribute statements](../../images/saml-okta-4.png) + + Once configured, select the Next button to proceed to the Feedback screen and select Finish. + + 5. Get IDP values + + Once your application is created, select the Sign On tab for the app and select the View Setup Instructions button located on the right side of the screen: + + Copy the Identity Provider Single Sign-On URL, the Identity Provider Issuer, and the X.509 Certificate to be pasted into your Infisical SAML SSO configuration details with the following map: + + - `Audience -> Okta Audience URI (SP Entity ID)` + - `Entrypoint -> Okta Identity Provider Single Sign-On URL` + - `Issuer -> Identity Provider Issuer` + - `Certificate -> X.509 Certificate`. + + ![SAML Okta IDP values](../../images/saml-okta-5.png) + + ![SAML Okta paste values into Infisical](../../images/saml-okta-6.png) + + 6. Create the SSO configuration and copy your SSO identifier in Infisical; update `:identifier` from step 4 earlier to be this value. + + ![SAML Okta assignments](../../images/saml-okta-7.png) + + 7. Assignments + + Finally, Navigate to the Assignments tab and select the Assign button: + + You can assign access to the application on a user-by-user basis using the Assign to People option, or in-bulk using the Assign to Groups option. + + ![SAML Okta assignment](../../images/saml-okta-8.png) + + At this point, you have configured everything you need within the context of the Okta Admin Portal. + + 8. Return to Infisical and enable SAML SSO. + + Enabling SAML SSO enforces all members in your organization to only be able to log into Infisical via Okta. + + + diff --git a/docs/documentation/platform/secret-reference.mdx b/docs/documentation/platform/secret-reference.mdx index 4192e16060..380facd948 100644 --- a/docs/documentation/platform/secret-reference.mdx +++ b/docs/documentation/platform/secret-reference.mdx @@ -45,8 +45,8 @@ To add an import, simply click on the `Add import` button and provide the enviro ![secret import change order](../../images/secret-import-add.png) The hierarchy of importing secrets is governed by a "last-one-wins" rule. This means the sequence in which you import matters - the final folder imported will override secrets from any prior folders. -Moreover, any secrets you define directly in your environment will take precedence over secrets from any imported folders. +Additionally, any secrets you define directly in your environment will override any secrets that are imported with the same name. -You can modify this sequence by dragging and rearranging the folders using the `Change Order` drag handle. +You can modify the order of folders to control overrides using the `Change Order` drag handle. ![secret import change order](../../images/secret-import-change-order.png) diff --git a/docs/images/integrations-bitbucket-auth.png b/docs/images/integrations-bitbucket-auth.png new file mode 100644 index 0000000000..ccdfcf1e00 Binary files /dev/null and b/docs/images/integrations-bitbucket-auth.png differ diff --git a/docs/images/integrations-bitbucket-create.png b/docs/images/integrations-bitbucket-create.png new file mode 100644 index 0000000000..f46993d658 Binary files /dev/null and b/docs/images/integrations-bitbucket-create.png differ diff --git a/docs/images/integrations-bitbucket.png b/docs/images/integrations-bitbucket.png new file mode 100644 index 0000000000..fbaafc95ad Binary files /dev/null and b/docs/images/integrations-bitbucket.png differ diff --git a/docs/images/integrations-cloud-66-access-token.png b/docs/images/integrations-cloud-66-access-token.png new file mode 100644 index 0000000000..a3532a6b45 Binary files /dev/null and b/docs/images/integrations-cloud-66-access-token.png differ diff --git a/docs/images/integrations-cloud-66-copy-pat.png b/docs/images/integrations-cloud-66-copy-pat.png new file mode 100644 index 0000000000..41d9e14af2 Binary files /dev/null and b/docs/images/integrations-cloud-66-copy-pat.png differ diff --git a/docs/images/integrations-cloud-66-create.png b/docs/images/integrations-cloud-66-create.png new file mode 100644 index 0000000000..24b14c3982 Binary files /dev/null and b/docs/images/integrations-cloud-66-create.png differ diff --git a/docs/images/integrations-cloud-66-dashboard.png b/docs/images/integrations-cloud-66-dashboard.png new file mode 100644 index 0000000000..4598fc9153 Binary files /dev/null and b/docs/images/integrations-cloud-66-dashboard.png differ diff --git a/docs/images/integrations-cloud-66-done.png b/docs/images/integrations-cloud-66-done.png new file mode 100644 index 0000000000..0541374b65 Binary files /dev/null and b/docs/images/integrations-cloud-66-done.png differ diff --git a/docs/images/integrations-cloud-66-infisical-dashboard.png b/docs/images/integrations-cloud-66-infisical-dashboard.png new file mode 100644 index 0000000000..e54eea7267 Binary files /dev/null and b/docs/images/integrations-cloud-66-infisical-dashboard.png differ diff --git a/docs/images/integrations-cloud-66-paste-pat.png b/docs/images/integrations-cloud-66-paste-pat.png new file mode 100644 index 0000000000..276da0e0d6 Binary files /dev/null and b/docs/images/integrations-cloud-66-paste-pat.png differ diff --git a/docs/images/integrations-cloud-66-pat-setup.png b/docs/images/integrations-cloud-66-pat-setup.png new file mode 100644 index 0000000000..0d54641fce Binary files /dev/null and b/docs/images/integrations-cloud-66-pat-setup.png differ diff --git a/docs/images/integrations-cloud-66-pat.png b/docs/images/integrations-cloud-66-pat.png new file mode 100644 index 0000000000..fd34343741 Binary files /dev/null and b/docs/images/integrations-cloud-66-pat.png differ diff --git a/docs/images/integrations-codefresh-auth.png b/docs/images/integrations-codefresh-auth.png new file mode 100644 index 0000000000..a9d907ba2c Binary files /dev/null and b/docs/images/integrations-codefresh-auth.png differ diff --git a/docs/images/integrations-codefresh-create.png b/docs/images/integrations-codefresh-create.png new file mode 100644 index 0000000000..6b98c7cf4b Binary files /dev/null and b/docs/images/integrations-codefresh-create.png differ diff --git a/docs/images/integrations-codefresh-dashboard.png b/docs/images/integrations-codefresh-dashboard.png new file mode 100644 index 0000000000..79b809d916 Binary files /dev/null and b/docs/images/integrations-codefresh-dashboard.png differ diff --git a/docs/images/integrations-codefresh-token.png b/docs/images/integrations-codefresh-token.png new file mode 100644 index 0000000000..d145f6472c Binary files /dev/null and b/docs/images/integrations-codefresh-token.png differ diff --git a/docs/images/integrations-codefresh.png b/docs/images/integrations-codefresh.png new file mode 100644 index 0000000000..f3b3ffa587 Binary files /dev/null and b/docs/images/integrations-codefresh.png differ diff --git a/docs/images/integrations-do-dashboard.png b/docs/images/integrations-do-dashboard.png new file mode 100644 index 0000000000..af9a06d071 Binary files /dev/null and b/docs/images/integrations-do-dashboard.png differ diff --git a/docs/images/integrations-do-enter-token.png b/docs/images/integrations-do-enter-token.png new file mode 100644 index 0000000000..48a436278e Binary files /dev/null and b/docs/images/integrations-do-enter-token.png differ diff --git a/docs/images/integrations-do-select-projects.png b/docs/images/integrations-do-select-projects.png new file mode 100644 index 0000000000..cb1878f5ff Binary files /dev/null and b/docs/images/integrations-do-select-projects.png differ diff --git a/docs/images/integrations-do-success.png b/docs/images/integrations-do-success.png new file mode 100644 index 0000000000..3866c4a7d4 Binary files /dev/null and b/docs/images/integrations-do-success.png differ diff --git a/docs/images/integrations-do-token-modal.png b/docs/images/integrations-do-token-modal.png new file mode 100644 index 0000000000..47e8a27fe8 Binary files /dev/null and b/docs/images/integrations-do-token-modal.png differ diff --git a/docs/images/integrations-northflank-auth.png b/docs/images/integrations-northflank-auth.png new file mode 100644 index 0000000000..460ad40d95 Binary files /dev/null and b/docs/images/integrations-northflank-auth.png differ diff --git a/docs/images/integrations-northflank-create.png b/docs/images/integrations-northflank-create.png new file mode 100644 index 0000000000..8afdb3c0db Binary files /dev/null and b/docs/images/integrations-northflank-create.png differ diff --git a/docs/images/integrations-northflank-dashboard.png b/docs/images/integrations-northflank-dashboard.png new file mode 100644 index 0000000000..80c887808b Binary files /dev/null and b/docs/images/integrations-northflank-dashboard.png differ diff --git a/docs/images/integrations-northflank-token.png b/docs/images/integrations-northflank-token.png new file mode 100644 index 0000000000..1e9b84f94f Binary files /dev/null and b/docs/images/integrations-northflank-token.png differ diff --git a/docs/images/integrations-northflank.png b/docs/images/integrations-northflank.png new file mode 100644 index 0000000000..ee388b2456 Binary files /dev/null and b/docs/images/integrations-northflank.png differ diff --git a/docs/images/integrations-terraformcloud-auth.png b/docs/images/integrations-terraformcloud-auth.png new file mode 100644 index 0000000000..930fdfafa8 Binary files /dev/null and b/docs/images/integrations-terraformcloud-auth.png differ diff --git a/docs/images/integrations-terraformcloud-create.png b/docs/images/integrations-terraformcloud-create.png new file mode 100644 index 0000000000..7c0ee12ee6 Binary files /dev/null and b/docs/images/integrations-terraformcloud-create.png differ diff --git a/docs/images/integrations-terraformcloud-dashboard.png b/docs/images/integrations-terraformcloud-dashboard.png new file mode 100644 index 0000000000..d73c8c2653 Binary files /dev/null and b/docs/images/integrations-terraformcloud-dashboard.png differ diff --git a/docs/images/integrations-terraformcloud-tokens.png b/docs/images/integrations-terraformcloud-tokens.png new file mode 100644 index 0000000000..604c70132b Binary files /dev/null and b/docs/images/integrations-terraformcloud-tokens.png differ diff --git a/docs/images/integrations-terraformcloud-workspaceid.png b/docs/images/integrations-terraformcloud-workspaceid.png new file mode 100644 index 0000000000..32558566fe Binary files /dev/null and b/docs/images/integrations-terraformcloud-workspaceid.png differ diff --git a/docs/images/integrations-terraformcloud-workspaces.png b/docs/images/integrations-terraformcloud-workspaces.png new file mode 100644 index 0000000000..08366778ee Binary files /dev/null and b/docs/images/integrations-terraformcloud-workspaces.png differ diff --git a/docs/images/integrations-terraformcloud.png b/docs/images/integrations-terraformcloud.png new file mode 100644 index 0000000000..02a6ca2dfc Binary files /dev/null and b/docs/images/integrations-terraformcloud.png differ diff --git a/docs/images/integrations.png b/docs/images/integrations.png index 368a10c379..af2a451254 100644 Binary files a/docs/images/integrations.png and b/docs/images/integrations.png differ diff --git a/docs/images/project-ip-whitelist-add.png b/docs/images/project-ip-whitelist-add.png new file mode 100644 index 0000000000..c045daa4c9 Binary files /dev/null and b/docs/images/project-ip-whitelist-add.png differ diff --git a/docs/images/project-ip-whitelist.png b/docs/images/project-ip-whitelist.png new file mode 100644 index 0000000000..d4c449064f Binary files /dev/null and b/docs/images/project-ip-whitelist.png differ diff --git a/docs/images/saml-okta-1.png b/docs/images/saml-okta-1.png new file mode 100644 index 0000000000..8ffac381b2 Binary files /dev/null and b/docs/images/saml-okta-1.png differ diff --git a/docs/images/saml-okta-2.png b/docs/images/saml-okta-2.png new file mode 100644 index 0000000000..717737af9a Binary files /dev/null and b/docs/images/saml-okta-2.png differ diff --git a/docs/images/saml-okta-3.png b/docs/images/saml-okta-3.png new file mode 100644 index 0000000000..eccc8d2779 Binary files /dev/null and b/docs/images/saml-okta-3.png differ diff --git a/docs/images/saml-okta-4.png b/docs/images/saml-okta-4.png new file mode 100644 index 0000000000..e3c413a6f7 Binary files /dev/null and b/docs/images/saml-okta-4.png differ diff --git a/docs/images/saml-okta-5.png b/docs/images/saml-okta-5.png new file mode 100644 index 0000000000..4acc846f9d Binary files /dev/null and b/docs/images/saml-okta-5.png differ diff --git a/docs/images/saml-okta-6.png b/docs/images/saml-okta-6.png new file mode 100644 index 0000000000..82300afdbc Binary files /dev/null and b/docs/images/saml-okta-6.png differ diff --git a/docs/images/saml-okta-7.png b/docs/images/saml-okta-7.png new file mode 100644 index 0000000000..2bd4a84e95 Binary files /dev/null and b/docs/images/saml-okta-7.png differ diff --git a/docs/images/saml-okta-8.png b/docs/images/saml-okta-8.png new file mode 100644 index 0000000000..bf9f983019 Binary files /dev/null and b/docs/images/saml-okta-8.png differ diff --git a/docs/integrations/cicd/bitbucket.mdx b/docs/integrations/cicd/bitbucket.mdx new file mode 100644 index 0000000000..ff33c9f9bb --- /dev/null +++ b/docs/integrations/cicd/bitbucket.mdx @@ -0,0 +1,31 @@ +--- +title: "Bitbucket" +description: "How to sync secrets from Infisical to Bitbucket" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Authorize Infisical for Bitbucket + +Press on the Bitbucket tile and grant Infisical access to your Bitbucket account. + +![integrations bitbucket authorization](../../images/integrations-bitbucket-auth.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +## Start integration + +Select which Infisical environment secrets you want to sync to which Bitbucket repo and press start integration to start syncing secrets to the repo. + +![integrations bitbucket](../../images/integrations-bitbucket.png) diff --git a/docs/integrations/cicd/codefresh.mdx b/docs/integrations/cicd/codefresh.mdx new file mode 100644 index 0000000000..e71552a092 --- /dev/null +++ b/docs/integrations/cicd/codefresh.mdx @@ -0,0 +1,37 @@ +--- +title: "Codefresh" +description: "How to sync secrets from Infisical to Codefresh" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Authorize Infisical for Codefresh + +Obtain an API key in User Settings > API Keys + +![integrations codefresh dashboard](../../images/integrations-codefresh-dashboard.png) +![integrations codefresh token](../../images/integrations-codefresh-token.png) + +Press on the Codefresh tile and input your Codefresh API key to grant Infisical access to your Codefresh account. + +![integrations codefresh authorization](../../images/integrations-codefresh-auth.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +## Start integration + +Select which Infisical environment secrets you want to sync to which Codefresh service and press create integration to start syncing secrets to Codefresh. + +![create integration codefresh](../../images/integrations-codefresh-create.png) +![integrations codefresh](../../images/integrations-codefresh.png) diff --git a/docs/integrations/cloud/cloud-66.mdx b/docs/integrations/cloud/cloud-66.mdx new file mode 100644 index 0000000000..86c28440e8 --- /dev/null +++ b/docs/integrations/cloud/cloud-66.mdx @@ -0,0 +1,55 @@ +--- +title: "Cloud 66" +description: "How to sync secrets from Infisical to Cloud 66" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Enter your Cloud 66 Access Token + +In Cloud 66 Dashboard, click on the top right icon > Account Settings > Access Token +![integrations cloud 66 dashboard](../../images/integrations-cloud-66-dashboard.png) +![integrations cloud 66 access token](../../images/integrations-cloud-66-access-token.png) + +Create new Personal Access Token. +![integrations cloud 66 personal access token](../../images/integrations-cloud-66-pat.png) + +Name it **infisical** and check **Public** and **Admin**. Then click "Create Token" +![integrations cloud 66 personal access token setup](../../images/integrations-cloud-66-pat-setup.png) + +Copy and save your token. +![integrations cloud 66 copy API token](../../images/integrations-cloud-66-copy-pat.png) + +### Go to Infisical Integration Page + +Click on the Cloud 66 tile and enter your API token to grant Infisical access to your Cloud 66 account. +![integrations cloud 66 tile in infisical dashboard](../../images/integrations-cloud-66-infisical-dashboard.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +Enter your Cloud 66 Personal Access Token here. Then click "Connect to Cloud 66". +![integrations cloud 66 tile in infisical dashboard](../../images/integrations-cloud-66-paste-pat.png) + + +## Start integration + +Select which Infisical environment secrets you want to sync to which Cloud 66 stacks and press create integration to start syncing secrets to Cloud 66. +![integrations laravel forge](../../images/integrations-cloud-66-create.png) + + + Any existing environment variables in Cloud 66 will be deleted when you start syncing. Make sure to add all the secrets into the Infisical dashboard first before doing any integrations. + + +Done! +![integrations laravel forge](../../images/integrations-cloud-66-done.png) diff --git a/docs/integrations/cloud/digital-ocean-app-platform.mdx b/docs/integrations/cloud/digital-ocean-app-platform.mdx new file mode 100644 index 0000000000..10dd7751db --- /dev/null +++ b/docs/integrations/cloud/digital-ocean-app-platform.mdx @@ -0,0 +1,39 @@ +--- +title: "Digital Ocean App Platform" +description: "How to sync secrets from Infisical to Digital Ocean App Platform" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) + +## Get your Digital Ocean Personal Access Tokens + +On Digital Ocean dashboard, navigate to **API > Tokens** and click on "Generate New Token" +![integrations digital ocean dashboard](../../images/integrations-do-dashboard.png) + +Name it **infisical**, choose **No expiry**, and make sure to check **Write (optional)**. Then click on "Generate Token" and copy your API token. +![integrations digital ocean token modal](../../images/integrations-do-token-modal.png) + +## Navigate to your project's integrations tab + +Click on the **Digital Ocean App Platform** tile and enter your API token to grant Infisical access to your Digital Ocean account. +![integrations](../../images/integrations.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +Then enter your Digital Ocean Personal Access Token here. Then click "Connect to Digital Ocean App Platform". +![integrations infisical dashboard digital ocean integration](../../images/integrations-do-enter-token.png) + +## Start integration + +Select which Infisical environment secrets you want to sync to which Digital Ocean App and click "Create Integration". +![integrations digital ocean select projects](../../images/integrations-do-select-projects.png) + +Done! +![integrations digital ocean integration success](../../images/integrations-do-success.png) diff --git a/docs/integrations/cloud/northflank.mdx b/docs/integrations/cloud/northflank.mdx new file mode 100644 index 0000000000..8b4f7eeb9a --- /dev/null +++ b/docs/integrations/cloud/northflank.mdx @@ -0,0 +1,38 @@ +--- +title: "Northflank" +description: "How to sync secrets from Infisical to Northflank" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) +- Have a [Northflank](https://northflank.com) project with a secret group ready + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Enter your Northflank API Token + +Obtain a Northflank API token in Account settings > API > Tokens + +![integrations northflank dashboard](../../images/integrations-northflank-dashboard.png) +![integrations northflank token](../../images/integrations-northflank-token.png) + +Press on the Northflank tile and input your Northflank API token to grant Infisical access to your Northflank account. + +![integrations northflank authorization](../../images/integrations-northflank-auth.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +## Start integration + +Select which Infisical environment secrets you want to sync to which Northflank project and secret group. Finally, press create integration to start syncing secrets to Northflank. + +![integrations northflank](../../images/integrations-northflank-create.png) +![integrations northflank](../../images/integrations-northflank.png) diff --git a/docs/integrations/cloud/terraform-cloud.mdx b/docs/integrations/cloud/terraform-cloud.mdx new file mode 100644 index 0000000000..9000fe1943 --- /dev/null +++ b/docs/integrations/cloud/terraform-cloud.mdx @@ -0,0 +1,42 @@ +--- +title: "Terraform Cloud" +description: "How to sync secrets from Infisical to Terraform Cloud" +--- + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Enter your Terraform Cloud API Token and Workspace Id + +Obtain a Terraform Cloud API Token in User Settings > Tokens + +![integrations terraform cloud dashboard](../../images/integrations-terraformcloud-dashboard.png) +![integrations terraform cloud tokens](../../images/integrations-terraformcloud-tokens.png) + +Obtain your Terraform Cloud Workspace Id in Projects & Workspaces > Workspace > ID + +![integrations terraform cloud projects & workspaces](../../images/integrations-terraformcloud-workspaces.png) +![integrations terraform cloud workspace id](../../images/integrations-terraformcloud-workspaceid.png) + +Press on the Terraform Cloud tile and input your Terraform Cloud API Token and Workspace Id to grant Infisical access to your Terraform Cloud account. + +![integrations terraform cloud authorization](../../images/integrations-terraformcloud-auth.png) + + + If this is your project's first cloud integration, then you'll have to grant + Infisical access to your project's environment variables. Although this step + breaks E2EE, it's necessary for Infisical to sync the environment variables to + the cloud platform. + + +## Start integration + +Select which Infisical environment secrets and Terraform Cloud variable type you want to sync to which Terraform Cloud workspace/project and press create integration to start syncing secrets to Terraform Cloud. + +![integrations terraform cloud](../../images/integrations-terraformcloud-create.png) +![integrations terraform cloud](../../images/integrations-terraformcloud.png) diff --git a/docs/integrations/frameworks/react.mdx b/docs/integrations/frameworks/react.mdx index 48ad5d74f4..ce50be1c82 100644 --- a/docs/integrations/frameworks/react.mdx +++ b/docs/integrations/frameworks/react.mdx @@ -26,3 +26,7 @@ infisical run -- # Example infisical run -- npm run dev ``` + + + React environment variables must be prefixed with `REACT_APP_` to show up within the application + diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx index b054a52cd1..95e77d78a9 100644 --- a/docs/integrations/overview.mdx +++ b/docs/integrations/overview.mdx @@ -20,14 +20,18 @@ Missing an integration? [Throw in a request](https://github.com/Infisical/infisi | [Render](/integrations/cloud/render) | Cloud | Available | | [Laravel Forge](/integrations/cloud/laravel-forge) | Cloud | Available | | [Railway](/integrations/cloud/railway) | Cloud | Available | +| [Terraform Cloud](/integrations/cloud/terraform-cloud) | Cloud | Available | | [Fly.io](/integrations/cloud/flyio) | Cloud | Available | | [Supabase](/integrations/cloud/supabase) | Cloud | Available | +| [Northflank](/integrations/cloud/northflank) | Cloud | Available | | [Cloudflare Pages](/integrations/cloud/cloudflare-pages) | Cloud | Available | | [Checkly](/integrations/cloud/checkly) | Cloud | Available | | [HashiCorp Vault](/integrations/cloud/hashicorp-vault) | Cloud | Available | | [AWS Parameter Store](/integrations/cloud/aws-parameter-store) | Cloud | Available | | [AWS Secret Manager](/integrations/cloud/aws-secret-manager) | Cloud | Available | | [Azure Key Vault](/integrations/cloud/azure-key-vault) | Cloud | Available | +| [BitBucket](/integrations/cicd/bitbucket) | CI/CD | Available | +| [Codefresh](/integrations/cicd/codefresh) | CI/CD | Available | | [GitHub Actions](/integrations/cicd/githubactions) | CI/CD | Available | | [GitLab](/integrations/cicd/gitlab) | CI/CD | Available | | [CircleCI](/integrations/cicd/circleci) | CI/CD | Available | diff --git a/docs/integrations/platforms/docker-compose.mdx b/docs/integrations/platforms/docker-compose.mdx index e768b0e840..238e3dd71c 100644 --- a/docs/integrations/platforms/docker-compose.mdx +++ b/docs/integrations/platforms/docker-compose.mdx @@ -11,11 +11,11 @@ Prerequisites: Follow this [guide](./docker) to configure the Infisical CLI for each service that you wish to inject environment variables into; you'll have to update the Dockerfile of each service. -## Generate Infisical Tokens +## Generate service token Generate a unique [Infisical Token](/documentation/platform/token) for each service. -## Add Infisical Tokens to your Docker Compose file +## Feed service token to your Docker Compose file For each service you want to inject secrets into, set an environment variable called `INFISICAL_TOKEN` equal to a unique identifier variable. diff --git a/docs/integrations/platforms/docker-intro.mdx b/docs/integrations/platforms/docker-intro.mdx new file mode 100644 index 0000000000..5f23584c85 --- /dev/null +++ b/docs/integrations/platforms/docker-intro.mdx @@ -0,0 +1,25 @@ +--- +title: "Docker" +description: "Learn how to feed secrets from Infisical into your docker application" +--- +There are many methods to inject Infisical secrets to docker-based applications. +Regardless of which method you choose, these methods will inject secrets from Infisical as environment variables into your Docker container. + + + Install and run your app start command with Infisical CLI + + + + Feed secrets via `--env-file` flag in docker run command + + + Inject secrets to multiple services using Docker Compose + + + + +The main difference between the "Docker Entrypoint" and "Docker run" approach is where the Infisical CLI is installed. +In most production settings, it's typically inconvenient to have the Infisical CLI installed and executed externally. +As a result, we suggest using the "Docker Entrypoint" method for production purposes. +However, if this limitation doesn't apply to you, select the method that best fits your needs. + \ No newline at end of file diff --git a/docs/integrations/platforms/docker-pass-envs.mdx b/docs/integrations/platforms/docker-pass-envs.mdx new file mode 100644 index 0000000000..d6451de714 --- /dev/null +++ b/docs/integrations/platforms/docker-pass-envs.mdx @@ -0,0 +1,48 @@ +--- +title: "Docker Run" +description: "Pass secrets to your docker container at run time" +--- + +This method allows you to feed secrets from Infisical into your container using the `--env-file` flag of `docker run` command. +Rather than giving the flag a file path to your env file, you'll use the Infisical CLI to create a virtual file path. + +For this method to function as expected, you must have a bash shell (for processing substitution) and the [Infisical CLI](../../cli/overview) installed in the environment where you will be running the `docker run` command. + +## 1. Authentication + +If you are already logged in via the CLI you can skip this step. Otherwise, head to your project settings in Infisical Cloud to generate an [Infisical Token](/documentation/platform/token). The service token will allow you to authenticate and fetch secrets from Infisical. +Once you have created a service token with the required permissions, you'll need to feed the token to the CLI. + +#### Pass as flag +You may use the --token flag to set the token + +```bash +infisical export --token=<> +``` + +#### Pass via shell environment variable +The CLI is configured to look for an environment variable named `INFISICAL_TOKEN`. If set, it'll attempt to use it for authentication. + +```bash +export INFISICAL_TOKEN=<> +``` + + + In production scenarios, please to avoid using the `infisical login` command and instead use a [service token](/documentation/platform/token). + + +## 2. Run your docker command with Infisical +Next, use the --env-file flag of the `docker run` command with Infisical CLI to point to your secrets. +Under the hood, this command will fetch secrets from Infisical and serve them as a file to the `--env-file` flag. + +```bash +# In this example, executing a docker run command will initiate an empty Alpine container and display the environment variables passed to it by Infisical. +docker run --rm --env-file <(infisical export --format=dotenv) alpine printenv +``` + +To view all options of the `export` command, click [here](../../cli/commands/export) + + + + When using the --env-file option, Docker does not have the capability to support secrets that span multiple lines. + diff --git a/docs/integrations/platforms/docker.mdx b/docs/integrations/platforms/docker.mdx index 629a813177..e9682b7853 100644 --- a/docs/integrations/platforms/docker.mdx +++ b/docs/integrations/platforms/docker.mdx @@ -1,11 +1,10 @@ --- -title: "Docker" +title: "Docker Entrypoint" description: "How to use Infisical to inject environment variables into a Docker container." --- -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) +This approach allows you to inject secrets from Infisical directly into your application. +This is achieved by installing the Infisical CLI into your docker image and modifying your start command to execute with Infisical. ## Add the Infisical CLI to your Dockerfile @@ -33,6 +32,10 @@ Prerequisites: ``` +#### + + We recommend you to set the version of the CLI to a specific version. This will help keep your CLI version consistent across reinstalls. [View versions](https://cloudsmith.io/~infisical/repos/infisical-cli/packages/) + ## Modify the start command in your Dockerfile @@ -48,18 +51,17 @@ CMD ["infisical", "run", "--", "npm", "run", "start"] CMD ["infisical", "run", "--command", "npm run start && ..."] ``` -## Generate an Infisical Token +## Generate an service token -Head to your project settings in Infisical Cloud to generate an [Infisical Token](/documentation/platform/token). +Head to your project settings in the Infisical dashboard to generate an [service token](/documentation/platform/token). +This service token will allow you to authenticate and fetch secrets from Infisical. +Once you have created a service token with the required permissions, you’ll need to feed the token to the CLI installed in your docker container. -## Feed Docker your Infisical Token +## Feed service token to docker container +The last step is to give the Infisical CLI installed in your Docker container access to the service token. This will allow the CLI to fetch and inject the secrets into your application. + +To feed the service token to the container, use the INFISICAL_TOKEN environment variable as shown below. ```bash docker run --env INFISICAL_TOKEN=[token] [DOCKER-IMAGE]... ``` - - - -The Infisical CLI uses the detected `INFISICAL_TOKEN` environment variable to authenticate, retrieve, and inject the environment variables which the token is authorized for. - - diff --git a/docs/integrations/platforms/kubernetes.mdx b/docs/integrations/platforms/kubernetes.mdx index 01e011f796..3d26536ba9 100644 --- a/docs/integrations/platforms/kubernetes.mdx +++ b/docs/integrations/platforms/kubernetes.mdx @@ -66,12 +66,12 @@ metadata: spec: # The host that should be used to pull secrets from. If left empty, the value specified in Global configuration will be used hostAPI: https://app.infisical.com/api - resyncInterval: + resyncInterval: 60 authentication: serviceToken: serviceTokenSecretReference: secretName: service-token - secretNamespace: option + secretNamespace: default secretsScope: envSlug: dev secretsPath: "/" diff --git a/docs/mint.json b/docs/mint.json index a749524ef8..65a500fea3 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -91,8 +91,8 @@ "documentation/getting-started/introduction", "documentation/getting-started/platform", "documentation/getting-started/sdks", - "documentation/getting-started/docker", - "documentation/getting-started/kubernetes", + "integrations/platforms/kubernetes", + "integrations/platforms/docker-intro", "documentation/getting-started/api" ] }, @@ -118,8 +118,10 @@ "documentation/platform/pit-recovery", "documentation/platform/secret-versioning", "documentation/platform/audit-logs", + "documentation/platform/token", + "documentation/platform/ip-allowlisting", "documentation/platform/mfa", - "documentation/platform/token" + "documentation/platform/saml" ] }, { @@ -135,7 +137,6 @@ "self-hosting/deployment-options/standalone-infisical", "self-hosting/deployment-options/fly.io", "self-hosting/deployment-options/render", - "self-hosting/deployment-options/laravel-forge", "self-hosting/deployment-options/digital-ocean-marketplace" ] }, @@ -187,7 +188,9 @@ { "group": "Docker", "pages": [ + "integrations/platforms/docker-intro", "integrations/platforms/docker", + "integrations/platforms/docker-pass-envs", "integrations/platforms/docker-compose" ] }, @@ -205,6 +208,12 @@ "integrations/cloud/aws-secret-manager" ] }, + { + "group": "Digital Ocean", + "pages": [ + "integrations/cloud/digital-ocean-app-platform" + ] + }, "integrations/cloud/heroku", "integrations/cloud/vercel", "integrations/cloud/netlify", @@ -213,14 +222,19 @@ "integrations/cloud/flyio", "integrations/cloud/laravel-forge", "integrations/cloud/supabase", + "integrations/cloud/northflank", + "integrations/cloud/terraform-cloud", "integrations/cloud/cloudflare-pages", "integrations/cloud/checkly", "integrations/cloud/hashicorp-vault", "integrations/cloud/azure-key-vault", + "integrations/cloud/cloud-66", "integrations/cicd/githubactions", "integrations/cicd/gitlab", "integrations/cicd/circleci", - "integrations/cicd/travisci" + "integrations/cicd/travisci", + "integrations/cicd/bitbucket", + "integrations/cicd/codefresh" ] }, { @@ -320,7 +334,8 @@ "pages": [ "security/overview", "security/data-model", - "security/mechanics" + "security/mechanics", + "security/service-tokens" ] }, { diff --git a/docs/security/service-tokens.mdx b/docs/security/service-tokens.mdx new file mode 100644 index 0000000000..b70f527ebf --- /dev/null +++ b/docs/security/service-tokens.mdx @@ -0,0 +1,22 @@ +--- +title: "Service Tokens" +description: "Understanding service tokens and their best practices" +--- + +## Background + +Many clients use service tokens to authenticate and read/write secrets from/to Infisical. + +Each service token consist of two parts used for authentication and decryption, separated by `.`. Consider the token `st.abc.def.ghi`. Here, `st.abc.def` can be used to authenticate with the API, by including it in the `Authorization` header under `Bearer st.abc.def`, and retrieve (encrypted) secrets as well as a project key back. Meanwhile, `ghi`, a hex-string, can be used to decrypt the project key used to decrypt the secrets. + +Note that when using service tokens via select client methods like SDK or CLI, cryptographic operations are abstracted for you that is the token is parsed and encryption/decryption operations are handled. If using service tokens with the REST API and end-to-end encryption enabled, then you will have to handle the encryption/decryption operations yourself. + +## Recommendations + +1. Issuance: When creating a new service token, it’s important to consider the [principle of least privilege(PoLP)](https://en.wikipedia.org/wiki/Principle_of_least_privilege) when setting its scope and expiration date. For example, if the client using the token only requires access to a staging environment, then you should scope the token to that environment only; you can further scope tokens to path(s) within environment(s) if you happen to use [path-based secret storage](/documentation/platform/folder). Likewise, if the client does not intend to access secrets indefinitely, then you may consider setting a finite lifetime for the token such as 6 months or 1 year from now. Finally, you should consider carefully whether or not your client requires the ability to read and/or write secrets from/to Infisical. + +2. Network access: We recommend configuring the IP whitelist settings of each project to allow either single IP addresses or CIDR-notated range of addresses to read/write secrets to Infisical. With this feature, you can specify the IP range of your client servers to restrict access to your project in Infisical. + +3. Storage: Since service tokens grant access to your secrets, we recommend storing service tokens securely across your development cycle whether it be in a `.env` file in local development or as an environment variable of your deployment platform. + +4. Rotation: We recommend periodically rotating the service token, even in the absence of compromise. Since service tokens are capable of decrypting project keys used to decrypt secrets, all of which use AES-256-GCM encryption, they should be rotated before approximately 2^32 encryptions have been performed; this follows the guidance set forth by NIST publication 800-38D. Note that Infisical keeps track of the number of times that service tokens are used and will alert you when you have reached 90% of the recommended capacity. diff --git a/docs/self-hosting/configuration/email.mdx b/docs/self-hosting/configuration/email.mdx index 15797d73bd..160e4f205d 100644 --- a/docs/self-hosting/configuration/email.mdx +++ b/docs/self-hosting/configuration/email.mdx @@ -10,7 +10,7 @@ However, the following functionality will be disabled. - Sending invite links via email for projects to teammates - Sending alerts such as suspicious login attempts -## General configuration +## Configuration If you choose to setup email service, you need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars): diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index fddf6f82ed..1db8822602 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -107,6 +107,14 @@ Other environment variables are listed below to increase the functionality of yo OAuth2 slug for Vercel integration + + + OAuth2 client ID for BitBucket integration + + + + OAuth2 client secret for BitBucket integration + To integrate with external auth providers, provide value for the related keys diff --git a/frontend/public/data/frequentConstants.ts b/frontend/public/data/frequentConstants.ts index 0b4fb65c85..3352999f6d 100644 --- a/frontend/public/data/frequentConstants.ts +++ b/frontend/public/data/frequentConstants.ts @@ -3,25 +3,30 @@ interface Mapping { } const integrationSlugNameMapping: Mapping = { - 'azure-key-vault': 'Azure Key Vault', - 'aws-parameter-store': 'AWS Parameter Store', - 'aws-secret-manager': 'AWS Secret Manager', - 'heroku': 'Heroku', - 'vercel': 'Vercel', - 'netlify': 'Netlify', - 'github': 'GitHub', - 'gitlab': 'GitLab', - 'render': 'Render', - 'laravel-forge': "Laravel Forge", - 'railway': 'Railway', - 'flyio': 'Fly.io', - 'circleci': 'CircleCI', - 'travisci': 'TravisCI', - 'supabase': 'Supabase', - 'checkly': 'Checkly', - 'hashicorp-vault': 'Vault', - 'cloudflare-pages': 'Cloudflare Pages', - 'codefresh': 'Codefresh', + "azure-key-vault": "Azure Key Vault", + "aws-parameter-store": "AWS Parameter Store", + "aws-secret-manager": "AWS Secret Manager", + heroku: "Heroku", + vercel: "Vercel", + netlify: "Netlify", + github: "GitHub", + gitlab: "GitLab", + render: "Render", + "laravel-forge": "Laravel Forge", + railway: "Railway", + flyio: "Fly.io", + circleci: "CircleCI", + travisci: "TravisCI", + supabase: "Supabase", + checkly: "Checkly", + 'terraform-cloud': 'Terraform Cloud', + "hashicorp-vault": "Vault", + "cloudflare-pages": "Cloudflare Pages", + "codefresh": "Codefresh", + "digital-ocean-app-platform": "Digital Ocean App Platform", + bitbucket: "BitBucket", + "cloud-66": "Cloud 66", + northflank: "Northflank", 'windmill': 'Windmill' } diff --git a/frontend/public/images/integrations/BitBucket.png b/frontend/public/images/integrations/BitBucket.png new file mode 100644 index 0000000000..7fe9b525ce Binary files /dev/null and b/frontend/public/images/integrations/BitBucket.png differ diff --git a/frontend/public/images/integrations/Cloud 66.png b/frontend/public/images/integrations/Cloud 66.png new file mode 100644 index 0000000000..20d8410804 Binary files /dev/null and b/frontend/public/images/integrations/Cloud 66.png differ diff --git a/frontend/public/images/integrations/Northflank.png b/frontend/public/images/integrations/Northflank.png new file mode 100644 index 0000000000..f2d94060b4 Binary files /dev/null and b/frontend/public/images/integrations/Northflank.png differ diff --git a/frontend/public/images/integrations/Terraform Cloud.png b/frontend/public/images/integrations/Terraform Cloud.png new file mode 100644 index 0000000000..c0000e98c8 Binary files /dev/null and b/frontend/public/images/integrations/Terraform Cloud.png differ diff --git a/frontend/public/locales/en/translations.json b/frontend/public/locales/en/translations.json index e4c671ca4f..a70a7dd8b3 100644 --- a/frontend/public/locales/en/translations.json +++ b/frontend/public/locales/en/translations.json @@ -227,7 +227,7 @@ }, "password": { "password": "Password", - "change": "Change password", + "change": "Change Password", "current": "Current password", "current-wrong": "The current password may be wrong", "new": "New password", diff --git a/frontend/public/lotties/system-outline-126-verified.json b/frontend/public/lotties/system-outline-126-verified.json new file mode 100644 index 0000000000..e612e81612 --- /dev/null +++ b/frontend/public/lotties/system-outline-126-verified.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":61,"w":500,"h":500,"nm":"126-verified-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-verified","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,250.003,0],"ix":2,"l":2},"a":{"a":0,"k":[250.004,250.003,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[6.109,-6.116],[-6.115,-6.108],[0,0],[-4.002,0],[-3.055,3.051],[0,0],[6.107,6.115],[6.115,-6.107],[0,0]],"o":[[-6.115,-6.107],[-6.107,6.116],[0,0],[3.056,3.052],[4.002,0],[0,0],[6.115,-6.108],[-6.109,-6.116],[0,0],[0,0]],"v":[[-69.803,-8.539],[-91.936,-8.526],[-91.922,13.607],[-39.704,65.762],[-28.644,70.339],[-17.584,65.762],[91.922,-43.616],[91.936,-65.749],[69.803,-65.762],[-28.644,32.57]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588238537,0.074509806931,0.192156866193,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[263.158,242.187],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[73.521,-47.165],[0,0],[0,0],[11.506,86.895],[0,0],[-39.84,20.453],[-33.146,-7.159]],"o":[[-11.51,86.919],[0,0],[0,0],[-73.503,-47.153],[0,0],[33.146,-7.159],[39.84,20.453],[0,0]],"v":[[149.277,-67.68],[15.49,143.298],[0,153.266],[-15.509,143.287],[-149.274,-67.655],[-154.479,-107.449],[0,-153.936],[154.479,-107.449]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[8.073,1.615],[32.173,20.107],[5.074,-3.172],[35.445,-7.092],[-1.068,-8.164],[0,0],[-81.252,-52.124],[0,0],[-2.944,0],[-2.579,1.66],[0,0],[-12.724,96.093],[0,0]],"o":[[-35.445,-7.092],[-5.074,-3.172],[-32.173,20.107],[-8.073,1.615],[0,0],[12.72,96.068],[0,0],[2.579,1.66],[2.944,0],[0,0],[81.27,-52.136],[0,0],[1.068,-8.164]],"v":[[174.946,-135.138],[8.294,-185.147],[-8.294,-185.147],[-174.946,-135.138],[-187.394,-117.763],[-180.307,-63.572],[-32.428,169.62],[-8.469,185.036],[0,187.526],[8.469,185.036],[32.409,169.632],[180.31,-63.596],[187.394,-117.763]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588238537,0.074509806931,0.192156866193,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[250.004,250.003],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":60,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary.design","cl":"primary design","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[13.16,-7.817,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[137.654,-115.818],[-28.644,54.689],[-80.863,2.534]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.070588238537,0.074509806931,0.192156866193,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[0]},{"t":39,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":25,"s":[0]},{"t":39,"s":[26.2]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":25,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.584],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":15.695,"s":[77]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":36.752,"s":[-25]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":52.188,"s":[8]},{"t":60,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.281,"y":1},"o":{"x":0.333,"y":0},"t":15.695,"s":[249.783,113.999,0],"to":[0,8.667,0],"ti":[0,4.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[249.783,165.999,0],"to":[0,-4.667,0],"ti":[0,8.667,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":42.541,"s":[249.783,85.999,0],"to":[0,-8.667,0],"ti":[0,-4.667,0]},{"t":52.1875,"s":[249.783,113.999,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-0.215,-136.005,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.807},"o":{"x":0.333,"y":0},"t":15.695,"s":[{"i":[[0,0],[0,0],[8.87,-28.834],[42.606,0],[0,0],[0,0],[0,0],[-42.127,45.088],[0,0],[-40.99,1.371]],"o":[[0,0],[16.136,17.513],[-9.413,30.597],[0,0],[0,0],[0,0],[-77.329,0.092],[0,0],[0,0],[39.509,-0.629]],"v":[[64.622,-188.295],[64.244,-188.35],[78.727,-109.993],[-0.255,-53.189],[0.097,-53.125],[0.089,-53.125],[-0.314,-53.189],[-63.37,-190.092],[-63.377,-190.045],[-0.007,-218.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.193},"t":21.746,"s":[{"i":[[0,0],[0,0],[12.256,-30.674],[42.668,-8.454],[0,0],[0,0],[0,0],[-25.502,59.236],[0,0],[-73.493,5.608]],"o":[[0,0],[9.535,24.634],[-14.097,34.46],[0,0],[0,0],[0,0],[-77.329,-15.207],[0,0],[0,0],[67.007,-0.392]],"v":[[94.002,-151.387],[95.117,-150.643],[93.331,-61.263],[7.167,11.228],[0.136,8.492],[0.129,8.492],[-7.561,11.227],[-94.511,-151.847],[-94.64,-152.329],[-0.005,-204.437]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":30,"s":[{"i":[[0,0],[0,0],[19.891,-34.822],[42.806,-27.519],[0,0],[0,0],[0,0],[15.895,90.546],[0,0],[-41.666,26.039]],"o":[[0,0],[-6.33,40.555],[-24.661,43.173],[0,0],[0,0],[0,0],[-77.33,-49.714],[0,0],[0,0],[41.667,26.039]],"v":[[183.699,-122.675],[175.269,-68.668],[126.269,48.638],[23.905,156.51],[0.007,171.873],[0,171.875],[-23.904,156.508],[-175.51,-64.584],[-184.963,-118.431],[0,-171.875]],"c":true}]},{"t":42.541015625,"s":[{"i":[[0,0],[0,0],[19.891,-34.822],[42.806,-27.519],[0,0],[0,0],[0,0],[11.993,91.145],[0,0],[-41.666,26.039]],"o":[[0,0],[-5.353,40.695],[-24.661,43.173],[0,0],[0,0],[0,0],[-77.33,-49.714],[0,0],[0,0],[41.667,26.039]],"v":[[171.875,-119.795],[164.746,-65.6],[126.269,48.638],[23.905,156.51],[0.007,171.873],[0,171.875],[-23.904,156.508],[-164.743,-65.592],[-171.875,-119.795],[0,-171.875]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.070588238537,0.074509806931,0.192156866193,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":16,"op":60,"st":-253,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[250,441,0],"to":[0,-54.5,0],"ti":[0,54.5,0]},{"t":15.6953125,"s":[250,114,0]}],"ix":2,"l":2},"a":{"a":0,"k":[0,-136,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[-10.416,0],[-0.936,-10.176],[0,-0.626],[11.046,0],[0,11.046],[-0.057,0.615]],"o":[[10.42,0],[0.056,0.611],[0,11.046],[-11.046,0],[0,-0.63],[0.942,-10.17]],"v":[[0,-100],[20.103,-81.856],[20,0],[0,20],[-20,0],[-20.102,-81.867]],"c":true}]},{"t":15.6953125,"s":[{"i":[[-43.112,0],[-4.042,-42.069],[0,-2.711],[45.84,0],[0,45.84],[-0.257,2.66]],"o":[[43.129,0],[0.254,2.644],[0,45.84],[-45.84,0],[0,-2.728],[4.065,-42.046]],"v":[[0,-83],[82.616,-8.036],[83,0],[0,83],[-83,0],[-82.611,-8.085]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.070588238537,0.074509806931,0.192156866193,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,-136],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":16,"st":0,"bm":0}]},{"id":"comp_1","nm":"hover-verified","fr":60,"layers":[{"ddd":0,"ind":1,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,250.003,0],"ix":2,"l":2},"a":{"a":0,"k":[250.004,250.003,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[6.109,-6.116],[-6.115,-6.108],[0,0],[-4.002,0],[-3.055,3.051],[0,0],[6.107,6.115],[6.115,-6.107],[0,0]],"o":[[-6.115,-6.107],[-6.107,6.116],[0,0],[3.056,3.052],[4.002,0],[0,0],[6.115,-6.108],[-6.109,-6.116],[0,0],[0,0]],"v":[[-69.803,-8.539],[-91.936,-8.526],[-91.922,13.607],[-39.704,65.762],[-28.644,70.339],[-17.584,65.762],[91.922,-43.616],[91.936,-65.749],[69.803,-65.762],[-28.644,32.57]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[263.158,242.187],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[73.521,-47.165],[0,0],[0,0],[11.506,86.895],[0,0],[-39.84,20.453],[-33.146,-7.159]],"o":[[-11.51,86.919],[0,0],[0,0],[-73.503,-47.153],[0,0],[33.146,-7.159],[39.84,20.453],[0,0]],"v":[[149.277,-67.68],[15.49,143.298],[0,153.266],[-15.509,143.287],[-149.274,-67.655],[-154.479,-107.449],[0,-153.936],[154.479,-107.449]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[8.073,1.615],[32.173,20.107],[5.074,-3.172],[35.445,-7.092],[-1.068,-8.164],[0,0],[-81.252,-52.124],[0,0],[-2.944,0],[-2.579,1.66],[0,0],[-12.724,96.093],[0,0]],"o":[[-35.445,-7.092],[-5.074,-3.172],[-32.173,20.107],[-8.073,1.615],[0,0],[12.72,96.068],[0,0],[2.579,1.66],[2.944,0],[0,0],[81.27,-52.136],[0,0],[1.068,-8.164]],"v":[[174.946,-135.138],[8.294,-185.147],[-8.294,-185.147],[-174.946,-135.138],[-187.394,-117.763],[-180.307,-63.572],[-32.428,169.62],[-8.469,185.036],[0,187.526],[8.469,185.036],[32.409,169.632],[180.31,-63.596],[187.394,-117.763]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[250.004,250.003],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":60,"op":300,"st":1,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,250.003,0],"ix":2,"l":2},"a":{"a":0,"k":[250.004,250.003,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[6.109,-6.116],[-6.115,-6.108],[0,0],[-4.002,0],[-3.055,3.051],[0,0],[6.107,6.115],[6.115,-6.107],[0,0]],"o":[[-6.115,-6.107],[-6.107,6.116],[0,0],[3.056,3.052],[4.002,0],[0,0],[6.115,-6.108],[-6.109,-6.116],[0,0],[0,0]],"v":[[-69.803,-8.539],[-91.936,-8.526],[-91.922,13.607],[-39.704,65.762],[-28.644,70.339],[-17.584,65.762],[91.922,-43.616],[91.936,-65.749],[69.803,-65.762],[-28.644,32.57]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[263.158,242.187],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[73.521,-47.165],[0,0],[0,0],[11.506,86.895],[0,0],[-39.84,20.453],[-33.146,-7.159]],"o":[[-11.51,86.919],[0,0],[0,0],[-73.503,-47.153],[0,0],[33.146,-7.159],[39.84,20.453],[0,0]],"v":[[149.277,-67.68],[15.49,143.298],[0,153.266],[-15.509,143.287],[-149.274,-67.655],[-154.479,-107.449],[0,-153.936],[154.479,-107.449]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[8.073,1.615],[32.173,20.107],[5.074,-3.172],[35.445,-7.092],[-1.068,-8.164],[0,0],[-81.252,-52.124],[0,0],[-2.944,0],[-2.579,1.66],[0,0],[-12.724,96.093],[0,0]],"o":[[-35.445,-7.092],[-5.074,-3.172],[-32.173,20.107],[-8.073,1.615],[0,0],[12.72,96.068],[0,0],[2.579,1.66],[2.944,0],[0,0],[81.27,-52.136],[0,0],[1.068,-8.164]],"v":[[174.946,-135.138],[8.294,-185.147],[-8.294,-185.147],[-174.946,-135.138],[-187.394,-117.763],[-180.307,-63.572],[-32.428,169.62],[-8.469,185.036],[0,187.526],[8.469,185.036],[32.409,169.632],[180.31,-63.596],[187.394,-117.763]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[250.004,250.003],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 2","np":3,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.131],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.628],"y":[0]},"t":30,"s":[27]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":46,"s":[-11]},{"t":60,"s":[0]}],"ix":10},"p":{"a":0,"k":[249.998,250.004,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.131,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0],[77.333,-49.716],[0,0],[0,0],[0,0],[11.993,91.145],[0,0],[-41.666,26.039]],"o":[[0,0],[-11.99,91.149],[0,0],[0,0],[0,0],[-77.33,-49.714],[0,0],[0,0],[41.667,26.039]],"v":[[171.875,-119.795],[164.746,-65.6],[23.905,156.51],[0.007,171.873],[0,171.875],[-23.904,156.508],[-164.743,-65.592],[-171.875,-119.795],[0,-171.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.628,"y":0},"t":21,"s":[{"i":[[0,0],[0,0],[99.436,-63.925],[0,0],[0,0],[0,0],[15.421,117.196],[0,0],[-53.575,33.481]],"o":[[0,0],[-15.417,117.201],[0,0],[0,0],[0,0],[-99.432,-63.922],[0,0],[0,0],[53.576,33.481]],"v":[[191.412,-122.573],[182.245,-52.889],[1.15,232.704],[-29.579,252.458],[-29.588,252.46],[-60.324,232.701],[-241.417,-52.879],[-250.588,-122.573],[-29.588,-189.539]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":41.801,"s":[{"i":[[0,0],[0,0],[56.69,-36.445],[0,0],[0,0],[0,0],[8.792,66.816],[0,0],[-30.544,19.088]],"o":[[0,0],[-8.79,66.819],[0,0],[0,0],[0,0],[-56.688,-36.443],[0,0],[0,0],[30.545,19.088]],"v":[[125.996,-87.818],[120.77,-48.09],[17.524,114.733],[0.005,125.995],[0,125.996],[-17.523,114.731],[-120.768,-48.083],[-125.996,-87.818],[0,-125.996]],"c":true}]},{"t":60,"s":[{"i":[[0,0],[0,0],[77.333,-49.716],[0,0],[0,0],[0,0],[11.993,91.145],[0,0],[-41.666,26.039]],"o":[[0,0],[-11.99,91.149],[0,0],[0,0],[0,0],[-77.33,-49.714],[0,0],[0,0],[41.667,26.039]],"v":[[171.875,-119.795],[164.746,-65.6],[23.905,156.51],[0.007,171.873],[0,171.875],[-23.904,156.508],[-164.743,-65.592],[-171.875,-119.795],[0,-171.875]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":60,"st":-239,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","parent":3,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[0.006,-0.001,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.157,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[153.363,-119.689],[-14.644,46.689],[-66.863,-5.466]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.6,"y":0},"t":21,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[167.916,-123.188],[-50.252,92.864],[-118.061,25.138]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":42,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[114.144,-89.081],[-10.899,34.749],[-49.764,-4.068]],"c":false}]},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0]],"v":[[153.363,-119.689],[-14.644,46.689],[-66.863,-5.466]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('126-verified-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":31.3,"ix":5},"lc":2,"lj":2,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[100]},{"t":20,"s":[100],"h":1},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[0]},{"t":60,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[26.2]},{"t":20,"s":[100],"h":1},{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":28,"s":[0]},{"t":60,"s":[26.2]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":1,"op":60,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"lordicon.com Outlines","cl":"com","sr":1,"ks":{"o":{"a":0,"k":20,"ix":11,"x":"var $bm_rt;\nvar checkbox = thisComp.layer('02092020').effect('02092020002')('Checkbox');\nif (checkbox == 1) {\n $bm_rt = 20;\n} else {\n $bm_rt = 0;\n}\n;"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[249.934,481.369,0],"ix":2,"l":2},"a":{"a":0,"k":[79.934,0.369,0],"ix":1,"l":2},"s":{"a":0,"k":[265.159,265.159,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[1.415,0],[11.014,0],[11.014,-2.523],[4.656,-2.523],[4.656,-14.809],[1.415,-14.809]],"c":true},"ix":2},"nm":"l","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"l","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-3.938],[-1.62,-1.723],[-1.949,0],[-1.641,1.846],[0,2.154],[1.579,1.805],[1.579,0]],"o":[[0,1.354],[1.354,1.415],[1.231,0],[1.21,-1.354],[0,-1.456],[-1.456,-1.641],[-5.333,0]],"v":[[11.167,-7.199],[12.992,-1.661],[18.243,0.369],[23.514,-1.743],[25.381,-7.548],[23.494,-13.127],[18.284,-15.137]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,1.415],[-0.841,1.026],[-1.19,0],[-0.615,-1.825],[0,-0.718],[0.492,-0.738],[1.292,0],[0.451,0.615]],"o":[[0,-1.682],[0.595,-0.759],[1.518,0],[0.308,0.902],[0,2.359],[-0.595,0.923],[-1.477,0],[-0.882,-1.149]],"v":[[14.49,-7.302],[15.577,-11.609],[18.305,-12.86],[21.689,-10.235],[22.058,-7.589],[21.053,-3.343],[18.284,-1.969],[15.597,-3.159]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"o","np":5,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[-0.287,-0.841],[-0.144,-0.82],[0,0],[0.164,0.656],[0.226,1.743],[2.236,0.205],[0,2.769],[0.923,0.8],[1.641,-0.021],[0,0]],"o":[[0,0],[0,0],[0,0],[0.533,0],[0.205,0.574],[0,0],[-0.164,-0.246],[-0.103,-0.41],[-0.267,-1.928],[0.718,-0.205],[0,-0.964],[-1.19,-1.026],[0,0],[0,0]],"v":[[27.381,0],[30.622,0],[30.622,-5.989],[33.411,-5.989],[35.011,-5.148],[35.811,0],[39.318,0],[38.867,-1.067],[38.416,-3.938],[35.749,-7.343],[38.847,-10.973],[37.554,-13.824],[33.063,-14.829],[27.381,-14.829]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.492,-0.349],[0,-1.005],[0.226,-0.164],[0.369,0],[0,0]],"o":[[0,0],[1.005,0],[0.287,0.185],[0,1.046],[-0.513,0.41],[0,0],[0,0]],"v":[[30.519,-12.491],[32.652,-12.491],[34.744,-12.142],[35.524,-10.481],[34.703,-8.758],[33.083,-8.348],[30.519,-8.348]],"c":true},"ix":2},"nm":"r","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"r","np":5,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[-0.554,0.103],[0,4.553],[1.866,1.374],[0.82,0],[0,0]],"o":[[0,0],[1.497,0],[2.81,-0.513],[0,-2.113],[-1.784,-1.313],[0,0],[0,0]],"v":[[41.068,0],[45.683,0],[48.349,-0.164],[53.6,-7.609],[51.077,-13.434],[45.97,-14.768],[41.068,-14.788]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,0],[-0.656,-0.185],[0,-2.092],[1.251,-1.251],[1.354,0],[0.349,0.021]],"o":[[1.825,-0.082],[1.99,0.554],[0,0.718],[-0.923,0.923],[-0.369,0],[0,0]],"v":[[44.288,-12.388],[47.611,-12.183],[50.318,-7.609],[48.985,-3.425],[45.539,-2.4],[44.288,-2.441]],"c":true},"ix":2},"nm":"d","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"d","np":5,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[55.669,0],[58.849,0],[58.849,-14.87],[55.669,-14.87]],"c":true},"ix":2},"nm":"i","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"i","np":3,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[3.241,0],[0,-4.697],[-5.107,0],[-1.313,1.354],[-0.062,0.882],[0,0],[1.333,0],[0,0.882],[-2.359,0],[-0.062,-0.513]],"o":[[0,-2.954],[-4.164,0],[0,3.671],[1.354,0],[1.19,-1.231],[0,0],[-0.062,1.969],[-3.097,0],[0,-3.056],[2.154,0],[0,0]],"v":[[73.104,-9.989],[67.587,-14.911],[60.798,-7.097],[67.566,0.349],[71.894,-1.313],[73.227,-4.799],[69.884,-4.799],[67.218,-1.99],[64.121,-7.076],[67.464,-12.593],[69.864,-9.989]],"c":true},"ix":2},"nm":"c","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"c","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-3.938],[-1.62,-1.723],[-1.949,0],[-1.641,1.846],[0,2.154],[1.579,1.805],[1.579,0]],"o":[[0,1.354],[1.354,1.415],[1.231,0],[1.21,-1.354],[0,-1.456],[-1.456,-1.641],[-5.333,0]],"v":[[74.546,-7.199],[76.372,-1.661],[81.622,0.369],[86.894,-1.743],[88.76,-7.548],[86.873,-13.127],[81.663,-15.137]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,1.415],[-0.841,1.026],[-1.19,0],[-0.615,-1.825],[0,-0.718],[0.492,-0.738],[1.292,0],[0.451,0.615]],"o":[[0,-1.682],[0.595,-0.759],[1.518,0],[0.308,0.902],[0,2.359],[-0.595,0.923],[-1.477,0],[-0.882,-1.149]],"v":[[77.869,-7.302],[78.956,-11.609],[81.684,-12.86],[85.068,-10.235],[85.437,-7.589],[84.432,-3.343],[81.663,-1.969],[78.977,-3.159]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"o","np":5,"cix":2,"bm":0,"ix":7,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[91.007,0],[94.001,0],[94.001,-12.306],[99.744,0],[104.113,0],[104.113,-14.829],[101.159,-14.829],[101.159,-3.159],[95.601,-14.829],[91.007,-14.829]],"c":true},"ix":2},"nm":"n","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"n","np":3,"cix":2,"bm":0,"ix":8,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[106.893,0],[109.497,0],[109.497,-2.728],[106.893,-2.728]],"c":true},"ix":2},"nm":".","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":".","np":3,"cix":2,"bm":0,"ix":9,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[3.241,0],[0,-4.697],[-5.107,0],[-1.313,1.354],[-0.062,0.882],[0,0],[1.333,0],[0,0.882],[-2.359,0],[-0.062,-0.513]],"o":[[0,-2.954],[-4.164,0],[0,3.671],[1.354,0],[1.19,-1.231],[0,0],[-0.062,1.969],[-3.097,0],[0,-3.056],[2.154,0],[0,0]],"v":[[124.04,-9.989],[118.523,-14.911],[111.734,-7.097],[118.502,0.349],[122.83,-1.313],[124.163,-4.799],[120.82,-4.799],[118.154,-1.99],[115.057,-7.076],[118.4,-12.593],[120.8,-9.989]],"c":true},"ix":2},"nm":"c","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"c","np":3,"cix":2,"bm":0,"ix":10,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-3.938],[-1.62,-1.723],[-1.949,0],[-1.641,1.846],[0,2.154],[1.579,1.805],[1.579,0]],"o":[[0,1.354],[1.354,1.415],[1.231,0],[1.21,-1.354],[0,-1.456],[-1.456,-1.641],[-5.333,0]],"v":[[125.482,-7.199],[127.308,-1.661],[132.558,0.369],[137.829,-1.743],[139.696,-7.548],[137.809,-13.127],[132.599,-15.137]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[0,1.415],[-0.841,1.026],[-1.19,0],[-0.615,-1.825],[0,-0.718],[0.492,-0.738],[1.292,0],[0.451,0.615]],"o":[[0,-1.682],[0.595,-0.759],[1.518,0],[0.308,0.902],[0,2.359],[-0.595,0.923],[-1.477,0],[-0.882,-1.149]],"v":[[128.805,-7.302],[129.892,-11.609],[132.62,-12.86],[136.004,-10.235],[136.373,-7.589],[135.368,-3.343],[132.599,-1.969],[129.912,-3.159]],"c":true},"ix":2},"nm":"o","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"mm","mm":1,"nm":"Merge Paths 1","mn":"ADBE Vector Filter - Merge","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"o","np":5,"cix":2,"bm":0,"ix":11,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[141.696,0],[144.67,0],[144.67,-12.716],[148.629,0],[151.254,0],[155.295,-12.716],[155.295,0],[158.453,0],[158.453,-14.829],[153.408,-14.829],[150.024,-4.041],[146.885,-14.829],[141.696,-14.829]],"c":true},"ix":2},"nm":"m","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0,0,0,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"m","np":3,"cix":2,"bm":0,"ix":12,"mn":"ADBE Vector Group","hd":false}],"ip":2.5,"op":25,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":3,"nm":"02092020","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-105,15,0],"ix":2,"l":2},"a":{"a":0,"k":[60,60,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"ef":[{"ty":5,"nm":"02092020002","np":3,"mn":"ADBE Checkbox Control","ix":1,"en":1,"ef":[{"ty":7,"nm":"Checkbox","mn":"ADBE Checkbox Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":3,"nm":"Color & Stroke Change","sr":1,"ks":{"o":{"a":0,"k":0,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-55,-102,0],"ix":2,"l":2,"x":"var $bm_rt;\n$bm_rt = effect('Axis')('Point');"},"a":{"a":0,"k":[50,50,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2,"x":"var $bm_rt;\nvar temp;\ntemp = effect('Scale')('Slider');\n$bm_rt = [\n temp,\n temp\n];"}},"ao":0,"ef":[{"ty":5,"nm":"Primary","np":3,"mn":"ADBE Color Control","ix":1,"en":1,"ef":[{"ty":2,"nm":"Color","mn":"ADBE Color Control-0001","ix":1,"v":{"a":0,"k":[1,1,1],"ix":1}}]},{"ty":5,"nm":"Axis","np":3,"mn":"ADBE Point Control","ix":2,"en":1,"ef":[{"ty":3,"nm":"Point","mn":"ADBE Point Control-0001","ix":1,"v":{"a":0,"k":[250,250],"ix":1}}]},{"ty":5,"nm":"Scale","np":3,"mn":"ADBE Slider Control","ix":3,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":100,"ix":1}}]},{"ty":5,"nm":"State-Intro","np":3,"mn":"ADBE Slider Control","ix":4,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]},{"ty":5,"nm":"State-Hover","np":3,"mn":"ADBE Slider Control","ix":5,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":1,"ix":1}}]}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"in-verified","parent":3,"refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\n$bm_rt = $bm_mul(thisComp.layer('Color & Stroke Change').effect('State-Intro')('Slider'), 100);"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[250,250,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":500,"h":500,"ip":0,"op":71,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"hover-verified","parent":3,"refId":"comp_1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11,"x":"var $bm_rt;\n$bm_rt = $bm_mul(thisComp.layer('Color & Stroke Change').effect('State-Hover')('Slider'), 100);"},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[50,50,0],"ix":2,"l":2},"a":{"a":0,"k":[250,250,0],"ix":1,"l":2},"s":{"a":0,"k":[100,100,100],"ix":6,"l":2}},"ao":0,"w":500,"h":500,"ip":0,"op":71,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx b/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx index 87004e0e8b..e8049066b3 100644 --- a/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx +++ b/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx @@ -127,7 +127,7 @@ const AddProjectMemberDialog = ({ ) : ( - */} -
-
- setEmail(e.target.value)} - type="email" - placeholder="Enter your email..." - isRequired - autoComplete="username" - className="h-12" - /> -
-
-
-
- setPassword(e.target.value)} - type="password" - placeholder="Enter your password..." - isRequired - autoComplete="current-password" - id="current-password" - className="h-12 select:-webkit-autofill:focus" - /> -
-
- {!isLoading && loginError && } -
- -
-
-
- or -
-
-
- -
-
- Don't have an acount yet? - - {t("login.create-account")} - -
-
- Forgot password? - - Recover your account - -
- -} diff --git a/frontend/src/components/login/PasswordInputStep.tsx b/frontend/src/components/login/PasswordInputStep.tsx deleted file mode 100644 index 0633024f1b..0000000000 --- a/frontend/src/components/login/PasswordInputStep.tsx +++ /dev/null @@ -1,122 +0,0 @@ -import React, { useState } from "react"; -import { useTranslation } from "react-i18next"; -import Link from "next/link"; -import { useRouter } from "next/router"; - -import Error from "@app/components/basic/Error"; -import attemptLogin from "@app/components/utilities/attemptLogin"; -import getOrganizations from "@app/pages/api/organization/getOrgs"; - -import SecurityClient from "../utilities/SecurityClient"; -import { Button, Input } from "../v2"; - -export default function PasswordInputStep({ - email, - password, - providerAuthToken, - setPassword, - setProviderAuthToken, - setStep -}: { - email: string; - password: string; - providerAuthToken: string; - setPassword: (password: string) => void; - setProviderAuthToken: (value: string) => void; - setStep: (step: number) => void; -}) { - const router = useRouter(); - const [isLoading, setIsLoading] = useState(false); - const [loginError, setLoginError] = useState(false); - - const { t } = useTranslation(); - - const handleLogin = async () => { - try { - setIsLoading(true); - const loginAttempt = await attemptLogin({ - email, - password, - providerAuthToken, - }); - - if (loginAttempt && loginAttempt.success) { - // case: login was successful - - if (loginAttempt.mfaEnabled) { - // case: login requires MFA step - setStep(2); - setIsLoading(false); - return; - } - - // case: login does not require MFA step - const userOrgs = await getOrganizations(); - const userOrg = userOrgs[0]._id; - router.push(`/org/${userOrg?._id}/overview`); - } - } catch (err) { - setLoginError(true); - } - - setIsLoading(false); - }; - - return ( -
e.preventDefault()}> -
-

- What’s your Infisical Password? -

-
-
- setPassword(e.target.value)} - type="password" - placeholder="Enter your password..." - isRequired - autoComplete="current-password" - id="current-password" - className="h-12" - /> -
-
- {!isLoading && loginError && } -
- -
-
- - Infisical Master Password serves as a decryption mechanism so that even Google is not able to access your secrets. - - - {t("login.forgot-password")} - -
-
- -
-
-
- ); -} diff --git a/frontend/src/components/signup/InitialSignupStep.tsx b/frontend/src/components/signup/InitialSignupStep.tsx index 0bcefbdd9a..b734050983 100644 --- a/frontend/src/components/signup/InitialSignupStep.tsx +++ b/frontend/src/components/signup/InitialSignupStep.tsx @@ -1,9 +1,9 @@ import { useTranslation } from "react-i18next"; import Link from "next/link"; import { useRouter } from "next/router"; +import { faGoogle } from "@fortawesome/free-brands-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -// import { faGoogle } from '@fortawesome/free-brands-svg-icons'; -// import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Button } from "../v2"; export default function InitialSignupStep({ @@ -16,23 +16,24 @@ export default function InitialSignupStep({ return

{t("signup.initial-title")}

- {/*
+
-
*/} -
+
+
+ +
+ ) : ( +
+ ); +} + +BitBucketCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx b/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx new file mode 100644 index 0000000000..43a58bc6f1 --- /dev/null +++ b/frontend/src/pages/integrations/bitbucket/oauth2/callback.tsx @@ -0,0 +1,34 @@ +import { useEffect } from "react"; +import { useRouter } from "next/router"; +import queryString from "query-string"; + +import AuthorizeIntegration from "../../../api/integrations/authorizeIntegration"; + +export default function BitBucketOAuth2CallbackPage() { + const router = useRouter(); + const { code, state } = queryString.parse(router.asPath.split("?")[1]); + + useEffect(() => { + (async () => { + try { + // validate state + if (state !== localStorage.getItem("latestCSRFToken")) return; + localStorage.removeItem("latestCSRFToken"); + + const integrationAuth = await AuthorizeIntegration({ + workspaceId: localStorage.getItem("projectData.id") as string, + code: code as string, + integration: "bitbucket" + }); + + router.push(`/integrations/bitbucket/create?integrationAuthId=${integrationAuth._id}`); + } catch (err) { + console.error(err); + } + })(); + }, []); + + return
; +} + +BitBucketOAuth2CallbackPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/cloud-66/authorize.tsx b/frontend/src/pages/integrations/cloud-66/authorize.tsx new file mode 100644 index 0000000000..8c6434936d --- /dev/null +++ b/frontend/src/pages/integrations/cloud-66/authorize.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; +import { useRouter } from "next/router"; + +import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; +import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; + +export default function Cloud66CreateIntegrationPage() { + const router = useRouter(); + const [apiKey, setApiKey] = useState(""); + const [apiKeyErrorText, setApiKeyErrorText] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleButtonClick = async () => { + try { + setApiKeyErrorText(""); + if (apiKey.length === 0) { + setApiKeyErrorText("Access token cannot be blank"); + return; + } + + setIsLoading(true); + + const integrationAuth = await saveIntegrationAccessToken({ + workspaceId: localStorage.getItem("projectData.id"), + integration: "cloud-66", + accessId: null, + accessToken: apiKey, + url: null, + namespace: null + }); + + setIsLoading(false); + + router.push(`/integrations/cloud-66/create?integrationAuthId=${integrationAuth._id}`); + } catch (err) { + console.error(err); + } + }; + + return ( +
+ + Cloud 66 Integration + + setApiKey(e.target.value)} /> + + + +
+ ); +} + +Cloud66CreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/cloud-66/create.tsx b/frontend/src/pages/integrations/cloud-66/create.tsx new file mode 100644 index 0000000000..dbf5664644 --- /dev/null +++ b/frontend/src/pages/integrations/cloud-66/create.tsx @@ -0,0 +1,155 @@ +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +import queryString from "query-string"; + +import { + Button, + Card, + CardTitle, + FormControl, + Input, + Select, + SelectItem +} from "../../../components/v2"; +import { + useGetIntegrationAuthApps, + useGetIntegrationAuthById, +} from "../../../hooks/api/integrationAuth"; +import { useGetWorkspaceById } from "../../../hooks/api/workspace"; +import createIntegration from "../../api/integrations/createIntegration"; + +export default function Cloud66CreateIntegrationPage() { + const router = useRouter(); + + const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); + + const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); + const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); + const { data: integrationAuthApps } = useGetIntegrationAuthApps({ + integrationAuthId: (integrationAuthId as string) ?? "" + }); + + const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); + const [targetApp, setTargetApp] = useState(""); + const [secretPath, setSecretPath] = useState("/"); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (workspace) { + setSelectedSourceEnvironment(workspace.environments[0].slug); + } + }, [workspace]); + + useEffect(() => { + if (integrationAuthApps) { + if (integrationAuthApps.length > 0) { + setTargetApp(integrationAuthApps[0].name); + } else { + setTargetApp("none"); + } + } + }, [integrationAuthApps]); + + const handleButtonClick = async () => { + try { + if (!integrationAuth?._id) return; + + setIsLoading(true); + + await createIntegration({ + integrationAuthId: integrationAuth?._id, + isActive: true, + app: targetApp, + appId: + integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp) + ?.appId ?? null, + sourceEnvironment: selectedSourceEnvironment, + targetEnvironment: null, + targetEnvironmentId: null, + targetService: null, + targetServiceId: null, + owner: null, + path: null, + region: null, + secretPath + }); + + setIsLoading(false); + + router.push(`/integrations/${localStorage.getItem("projectData.id")}`); + } catch (err) { + console.error(err); + } + }; + + return integrationAuth && + workspace && + selectedSourceEnvironment && + integrationAuthApps && + targetApp ? ( +
+ + Cloud 66 Integration + + + + + setSecretPath(evt.target.value)} + placeholder="Provide a path, default is /" + /> + + + + + + +
+ ) : ( +
+ ); +} + +Cloud66CreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx b/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx new file mode 100644 index 0000000000..9c3912b2e1 --- /dev/null +++ b/frontend/src/pages/integrations/digital-ocean-app-platform/authorize.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; +import { useRouter } from "next/router"; + +import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; +import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; + +export default function DigitalOceanAppPlatformCreateIntegrationPage() { + const router = useRouter(); + const [apiKey, setApiKey] = useState(""); + const [apiKeyErrorText, setApiKeyErrorText] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleButtonClick = async () => { + try { + setApiKeyErrorText(""); + if (apiKey.length === 0) { + setApiKeyErrorText("API Key cannot be blank"); + return; + } + + setIsLoading(true); + + const integrationAuth = await saveIntegrationAccessToken({ + workspaceId: localStorage.getItem("projectData.id"), + integration: "digital-ocean-app-platform", + accessId: null, + accessToken: apiKey, + url: null, + namespace: null + }); + + setIsLoading(false); + + router.push(`/integrations/digital-ocean-app-platform/create?integrationAuthId=${integrationAuth._id}`); + } catch (err) { + console.error(err); + } + }; + + return ( +
+ + Digital Ocean App Platform Integration + + setApiKey(e.target.value)} /> + + + +
+ ); +} + +DigitalOceanAppPlatformCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx b/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx new file mode 100644 index 0000000000..925729c94c --- /dev/null +++ b/frontend/src/pages/integrations/digital-ocean-app-platform/create.tsx @@ -0,0 +1,155 @@ +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +import queryString from "query-string"; + +import { + Button, + Card, + CardTitle, + FormControl, + Input, + Select, + SelectItem +} from "../../../components/v2"; +import { + useGetIntegrationAuthApps, + useGetIntegrationAuthById +} from "../../../hooks/api/integrationAuth"; +import { useGetWorkspaceById } from "../../../hooks/api/workspace"; +import createIntegration from "../../api/integrations/createIntegration"; + +export default function DigitalOceanAppPlatformCreateIntegrationPage() { + const router = useRouter(); + + const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); + + const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); + const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); + const { data: integrationAuthApps } = useGetIntegrationAuthApps({ + integrationAuthId: (integrationAuthId as string) ?? "" + }); + + const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); + const [targetApp, setTargetApp] = useState(""); + const [secretPath, setSecretPath] = useState("/"); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (workspace) { + setSelectedSourceEnvironment(workspace.environments[0].slug); + } + }, [workspace]); + + useEffect(() => { + if (integrationAuthApps) { + if (integrationAuthApps.length > 0) { + setTargetApp(integrationAuthApps[0].name); + } else { + setTargetApp("none"); + } + } + }, [integrationAuthApps]); + + const handleButtonClick = async () => { + try { + if (!integrationAuth?._id) return; + + setIsLoading(true); + + await createIntegration({ + integrationAuthId: integrationAuth?._id, + isActive: true, + app: targetApp, + appId: + integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp) + ?.appId ?? null, + sourceEnvironment: selectedSourceEnvironment, + targetEnvironment: null, + targetEnvironmentId: null, + targetService: null, + targetServiceId: null, + owner: null, + path: null, + region: null, + secretPath + }); + + setIsLoading(false); + + router.push(`/integrations/${localStorage.getItem("projectData.id")}`); + } catch (err) { + console.error(err); + } + }; + + return integrationAuth && + workspace && + selectedSourceEnvironment && + integrationAuthApps && + targetApp ? ( +
+ + Digital Ocean App Platform Integration + + + + + setSecretPath(evt.target.value)} + placeholder="Provide a path, default is /" + /> + + + + + + +
+ ) : ( +
+ ); +} + +DigitalOceanAppPlatformCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/northflank/authorize.tsx b/frontend/src/pages/integrations/northflank/authorize.tsx new file mode 100644 index 0000000000..8e2baa3cb1 --- /dev/null +++ b/frontend/src/pages/integrations/northflank/authorize.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; +import { useRouter } from "next/router"; + +import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; +import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; + +export default function NorthflankCreateIntegrationPage() { + const router = useRouter(); + const [apiKey, setApiKey] = useState(""); + const [apiKeyErrorText, setApiKeyErrorText] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleButtonClick = async () => { + try { + setApiKeyErrorText(""); + if (apiKey.length === 0) { + setApiKeyErrorText("API Key cannot be blank"); + return; + } + + setIsLoading(true); + + const integrationAuth = await saveIntegrationAccessToken({ + workspaceId: localStorage.getItem("projectData.id"), + integration: "northflank", + accessToken: apiKey, + accessId: null, + url: null, + namespace: null + }); + + setIsLoading(false); + + router.push(`/integrations/northflank/create?integrationAuthId=${integrationAuth._id}`); + } catch (err) { + console.error(err); + } + }; + + return ( +
+ + Northflank Integration + + setApiKey(e.target.value)} /> + + + +
+ ); +} + +NorthflankCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/northflank/create.tsx b/frontend/src/pages/integrations/northflank/create.tsx new file mode 100644 index 0000000000..4ebcf95ec7 --- /dev/null +++ b/frontend/src/pages/integrations/northflank/create.tsx @@ -0,0 +1,202 @@ +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +import queryString from "query-string"; + +import { + Button, + Card, + CardTitle, + FormControl, + Input, + Select, + SelectItem +} from "../../../components/v2"; +import { + useGetIntegrationAuthApps, + useGetIntegrationAuthById, + useGetIntegrationAuthNorthflankSecretGroups +} from "../../../hooks/api/integrationAuth"; +import { useGetWorkspaceById } from "../../../hooks/api/workspace"; +import createIntegration from "../../api/integrations/createIntegration"; + +export default function NorthflankCreateIntegrationPage() { + const router = useRouter(); + + const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); + const [secretPath, setSecretPath] = useState("/"); + const [targetAppId, setTargetAppId] = useState(""); + const [targetSecretGroupId, setTargetSecretGroupId] = useState(null); + + const [isLoading, setIsLoading] = useState(false); + + const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); + + const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); + const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); + const { data: integrationAuthApps } = useGetIntegrationAuthApps({ + integrationAuthId: (integrationAuthId as string) ?? "" + }); + const { data: integrationAuthSecretGroups } = useGetIntegrationAuthNorthflankSecretGroups({ + integrationAuthId: (integrationAuthId as string) ?? "", + appId: targetAppId + }); + + useEffect(() => { + if (workspace) { + setSelectedSourceEnvironment(workspace.environments[0].slug); + } + }, [workspace]); + + useEffect(() => { + if (integrationAuthApps) { + if (integrationAuthApps.length > 0) { + // setTargetApp(integrationAuthApps[0].name); + setTargetAppId(integrationAuthApps[0].appId as string); + } else { + // setTargetApp("none"); + setTargetAppId("none"); + } + } + }, [integrationAuthApps]); + + useEffect(() => { + if (integrationAuthSecretGroups) { + if (integrationAuthSecretGroups.length > 0) { + // case: project has at least 1 secret group in Northflank + setTargetSecretGroupId(integrationAuthSecretGroups[0].groupId); + } else { + // case: project has no secret groups in Northflank + setTargetSecretGroupId("none"); + } + } + + }, [integrationAuthSecretGroups]); + + const handleButtonClick = async () => { + try { + if (!integrationAuth?._id) return; + + setIsLoading(true); + + await createIntegration({ + integrationAuthId: integrationAuth?._id, + isActive: true, + app: integrationAuthApps?.find( + (integrationAuthApp) => integrationAuthApp.appId === targetAppId + )?.name ?? null, + appId: targetAppId, + sourceEnvironment: selectedSourceEnvironment, + targetEnvironment: null, + targetEnvironmentId: null, + targetService: null, + targetServiceId: targetSecretGroupId, + owner: null, + path: null, + region: null, + secretPath + }); + + setIsLoading(false); + + router.push(`/integrations/${localStorage.getItem("projectData.id")}`); + } catch (err) { + console.error(err); + } + }; + + return integrationAuth && + workspace && + selectedSourceEnvironment && + integrationAuthApps && + targetAppId ? ( +
+ + Northflank Integration + + + + + setSecretPath(evt.target.value)} + placeholder="Provide a path, default is /" + /> + + + + + {targetSecretGroupId && integrationAuthSecretGroups && ( + + + + )} + + +
+ ) : ( +
+ ); +} + +NorthflankCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/terraform-cloud/authorize.tsx b/frontend/src/pages/integrations/terraform-cloud/authorize.tsx new file mode 100644 index 0000000000..c569bdccab --- /dev/null +++ b/frontend/src/pages/integrations/terraform-cloud/authorize.tsx @@ -0,0 +1,80 @@ +import { useState } from "react"; +import { useRouter } from "next/router"; + +import { Button, Card, CardTitle, FormControl, Input } from "../../../components/v2"; +import saveIntegrationAccessToken from "../../api/integrations/saveIntegrationAccessToken"; + +export default function TerraformCloudCreateIntegrationPage() { + const router = useRouter(); + const [apiKey, setApiKey] = useState(""); + const [apiKeyErrorText, setApiKeyErrorText] = useState(""); + const [workspacesId, setWorkSpacesId] = useState(""); + const [workspacesIdErrorText, setWorkspacesIdErrorText] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleButtonClick = async () => { + try { + setApiKeyErrorText(""); + setWorkspacesIdErrorText(""); + + if (apiKey.length === 0) { + setApiKeyErrorText("API Token cannot be blank"); + return; + } + + if (workspacesId.length === 0) { + setWorkspacesIdErrorText("Workspace Id cannot be blank"); + return; + } + + setIsLoading(true); + + const integrationAuth = await saveIntegrationAccessToken({ + workspaceId: localStorage.getItem("projectData.id"), + integration: "terraform-cloud", + accessId: workspacesId, + accessToken: apiKey, + url: null, + namespace: null + }); + + setIsLoading(false); + + router.push(`/integrations/terraform-cloud/create?integrationAuthId=${integrationAuth._id}`); + } catch (err) { + console.error(err); + } + }; + + return ( +
+ + Terraform Cloud Integration + + setApiKey(e.target.value)} /> + + + setWorkSpacesId(e.target.value)} /> + + + +
+ ); +} + +TerraformCloudCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/integrations/terraform-cloud/create.tsx b/frontend/src/pages/integrations/terraform-cloud/create.tsx new file mode 100644 index 0000000000..47c33948c3 --- /dev/null +++ b/frontend/src/pages/integrations/terraform-cloud/create.tsx @@ -0,0 +1,189 @@ +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +import queryString from "query-string"; + +import { + Button, + Card, + CardTitle, + FormControl, + Input, + Select, + SelectItem +} from "../../../components/v2"; +import { + useGetIntegrationAuthApps, + useGetIntegrationAuthById +} from "../../../hooks/api/integrationAuth"; +import { useGetWorkspaceById } from "../../../hooks/api/workspace"; +import createIntegration from "../../api/integrations/createIntegration"; + +const variableTypes = [ + { name: "env" }, + { name: "terraform" } +]; + +export default function TerraformCloudCreateIntegrationPage() { + const router = useRouter(); + + const { integrationAuthId } = queryString.parse(router.asPath.split("?")[1]); + + const { data: workspace } = useGetWorkspaceById(localStorage.getItem("projectData.id") ?? ""); + const { data: integrationAuth } = useGetIntegrationAuthById((integrationAuthId as string) ?? ""); + const { data: integrationAuthApps } = useGetIntegrationAuthApps({ + integrationAuthId: (integrationAuthId as string) ?? "" + }); + + const [selectedSourceEnvironment, setSelectedSourceEnvironment] = useState(""); + const [targetApp, setTargetApp] = useState(""); + const [secretPath, setSecretPath] = useState("/"); + const [variableType, setVariableType] = useState(""); + const [variableTypeErrorText, setVariableTypeErrorText] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + useEffect(() => { + if (workspace) { + setSelectedSourceEnvironment(workspace.environments[0].slug); + setVariableType(variableTypes[0].name); + } + }, [workspace]); + + useEffect(() => { + if (integrationAuthApps) { + if (integrationAuthApps.length > 0) { + setTargetApp(integrationAuthApps[0].name); + } else { + setTargetApp("none"); + } + } + }, [integrationAuthApps]); + + const handleButtonClick = async () => { + try { + if (!integrationAuth?._id) return; + + setVariableTypeErrorText(""); + if (variableType.length === 0 ) { + setVariableTypeErrorText("Variable Type cannot be blank!") + return; + } + + setIsLoading(true); + + await createIntegration({ + integrationAuthId: integrationAuth?._id, + isActive: true, + app: targetApp, + appId: + integrationAuthApps?.find((integrationAuthApp) => integrationAuthApp.name === targetApp) + ?.appId ?? null, + sourceEnvironment: selectedSourceEnvironment, + targetEnvironment: null, + targetEnvironmentId: null, + targetService: variableType, + targetServiceId: null, + owner: null, + path: null, + region: null, + secretPath + }); + + setIsLoading(false); + + router.push(`/integrations/${localStorage.getItem("projectData.id")}`); + } catch (err) { + console.error(err); + } + }; + + + return integrationAuth && + workspace && + selectedSourceEnvironment && + integrationAuthApps && + targetApp ? ( +
+ + Terraform Cloud Integration + + + + + setSecretPath(evt.target.value)} + placeholder="Provide a path, default is /" + /> + + + + + + + + + +
+ ) : ( +
+ ); +} + +TerraformCloudCreateIntegrationPage.requireAuth = true; diff --git a/frontend/src/pages/login.tsx b/frontend/src/pages/login.tsx deleted file mode 100644 index d0eae97de8..0000000000 --- a/frontend/src/pages/login.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { useEffect, useState } from "react"; -import { useTranslation } from "react-i18next"; -import Head from "next/head"; -import Image from "next/image"; -import Link from "next/link"; -import { useRouter } from "next/router"; -import axios from "axios" - -// import ListBox from '@app/components/basic/Listbox'; -import InitialLoginStep from "@app/components/login/InitialLoginStep"; -import MFAStep from "@app/components/login/MFAStep"; -import PasswordInputStep from "@app/components/login/PasswordInputStep"; -import { fetchUserDetails } from "@app/hooks/api/users/queries"; -import { useProviderAuth } from "@app/hooks/useProviderAuth"; -import { getAuthToken, isLoggedIn } from "@app/reactQuery"; - -import getOrganizations from "./api/organization/getOrgs"; - -export default function Login() { - const router = useRouter(); - const [email, setEmail] = useState(""); - const [password, setPassword] = useState(""); - const [step, setStep] = useState(1); - const { t } = useTranslation(); - - // const lang = router.locale ?? 'en'; - const { - providerAuthToken, - email: providerEmail, - setProviderAuthToken, - isProviderUserCompleted - } = useProviderAuth(); - - if (providerAuthToken && isProviderUserCompleted === false) { - router.push(`/signup?providerAuthToken=${encodeURIComponent(providerAuthToken)}`); - } - - // const setLanguage = async (to: string) => { - // router.push('/login', '/login', { locale: to }); - // localStorage.setItem('lang', to); - // }; - - useEffect(() => { - // TODO(akhilmhdh): workspace will be controlled by a workspace context - const redirectToDashboard = async () => { - try { - const userOrgs = await getOrganizations(); - // userWorkspace = userWorkspaces[0] && userWorkspaces[0]._id; - const userOrg = userOrgs[0] && userOrgs[0]._id; - - // user details - const userDetails = await fetchUserDetails() - // send details back to client - - const queryParams = new URLSearchParams(window.location.search) - if (queryParams && queryParams.get("callback_port")) { - const callbackPort = queryParams.get("callback_port") - - // send post request to cli with details - const cliUrl = `http://localhost:${callbackPort}` - const instance = axios.create() - await instance.post(cliUrl, { email: userDetails.email, privateKey: localStorage.getItem("PRIVATE_KEY"), JTWToken: getAuthToken() }) - } - router.push(`/org/${userOrg}/overview`); - } catch (error) { - console.log("Error - Not logged in yet"); - } - }; - if (isLoggedIn()) { - redirectToDashboard(); - } - }, []); - - const renderView = (loginStep: number) => { - if (providerAuthToken && step === 1) { - return ( - - ); - } - - if (loginStep === 1) { - return ; - } - - if (step === 2) { - return ( - - ); - } - - return
; - }; - - return ( -
- - {t("common.head-title", { title: t("login.title") })} - - - - - - -
- Infisical logo -
- - {renderView(step)} - {/*
-
- -
-
*/} -
- ); -} diff --git a/frontend/src/pages/login/index.tsx b/frontend/src/pages/login/index.tsx new file mode 100644 index 0000000000..cf1d96d1f5 --- /dev/null +++ b/frontend/src/pages/login/index.tsx @@ -0,0 +1,28 @@ +import { useTranslation } from "react-i18next"; +import Head from "next/head"; +import Image from "next/image"; +import Link from "next/link"; + +import { Login } from "@app/views/Login"; + +export default function LoginPage() { + const { t } = useTranslation(); + + return ( +
+ + {t("common.head-title", { title: t("login.title") })} + + + + + + +
+ Infisical logo +
+ + +
+ ); +} diff --git a/frontend/src/pages/login/sso/index.tsx b/frontend/src/pages/login/sso/index.tsx new file mode 100644 index 0000000000..95bffab700 --- /dev/null +++ b/frontend/src/pages/login/sso/index.tsx @@ -0,0 +1,31 @@ +import { useTranslation } from "react-i18next"; +import Head from "next/head"; +import Image from "next/image"; +import Link from "next/link"; +import { useRouter } from "next/router" + +import { LoginSSO } from "@app/views/Login"; + +export default function LoginSSOPage() { + const { t } = useTranslation(); + const router = useRouter(); + const token = router.query.token as string; + + return ( +
+ + {t("common.head-title", { title: t("login.title") })} + + + + + + +
+ Infisical logo +
+ + +
+ ); +} \ No newline at end of file diff --git a/frontend/src/pages/org/[id]/overview/index.tsx b/frontend/src/pages/org/[id]/overview/index.tsx index 45b9a17437..693af4d6fc 100644 --- a/frontend/src/pages/org/[id]/overview/index.tsx +++ b/frontend/src/pages/org/[id]/overview/index.tsx @@ -5,7 +5,6 @@ import { useEffect, useState } from "react"; import { Controller, useForm } from "react-hook-form"; import { useTranslation } from "react-i18next"; import Head from "next/head"; -import Link from "next/link"; import { useRouter } from "next/router"; import { IconProp } from "@fortawesome/fontawesome-svg-core"; import { faSlack } from "@fortawesome/free-brands-svg-icons"; @@ -325,9 +324,12 @@ export default function Organization() { {orgWorkspaces.filter(ws => ws?.name?.toLowerCase().includes(searchFilter.toLowerCase())).map(workspace =>
{workspace.name}
{(workspace.environments?.length || 0)} environments
- -
Explore
- +
)}
{orgWorkspaces.length === 0 && ( diff --git a/frontend/src/pages/project/[id]/allowlist/index.tsx b/frontend/src/pages/project/[id]/allowlist/index.tsx new file mode 100644 index 0000000000..9014cf0e91 --- /dev/null +++ b/frontend/src/pages/project/[id]/allowlist/index.tsx @@ -0,0 +1,21 @@ +import { useTranslation } from "react-i18next"; +import Head from "next/head"; + +import { IPAllowlistPage } from "@app/views/Project/IPAllowListPage"; + +const ProjectAllowlist = () => { + const { t } = useTranslation(); + return ( + <> + + {t("common.head-title", { title: t("settings.project.title") })} + + + + + ); +} + +export default ProjectAllowlist; + +ProjectAllowlist.requireAuth = true; \ No newline at end of file diff --git a/frontend/src/pages/project/[id]/members/index.tsx b/frontend/src/pages/project/[id]/members/index.tsx index e3284ae9e5..471c1bca7e 100644 --- a/frontend/src/pages/project/[id]/members/index.tsx +++ b/frontend/src/pages/project/[id]/members/index.tsx @@ -183,7 +183,9 @@ export default function Users() {
-
-
- -
-
-
- ); -} diff --git a/frontend/src/pages/signup.tsx b/frontend/src/pages/signup/index.tsx similarity index 89% rename from frontend/src/pages/signup.tsx rename to frontend/src/pages/signup/index.tsx index 603ec9fd12..ff8c41e618 100644 --- a/frontend/src/pages/signup.tsx +++ b/frontend/src/pages/signup/index.tsx @@ -13,10 +13,8 @@ import TeamInviteStep from "@app/components/signup/TeamInviteStep"; import UserInfoStep from "@app/components/signup/UserInfoStep"; import SecurityClient from "@app/components/utilities/SecurityClient"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; -import { useProviderAuth } from "@app/hooks/useProviderAuth"; - -import checkEmailVerificationCode from "./api/auth/CheckEmailVerificationCode"; -import getOrganizations from "./api/organization/getOrgs"; +import checkEmailVerificationCode from "@app/pages/api/auth/CheckEmailVerificationCode"; +import getOrganizations from "@app/pages/api/organization/getOrgs"; /** * @returns the signup page @@ -35,15 +33,6 @@ export default function SignUp() { const [isSignupWithEmail, setIsSignupWithEmail] = useState(false); const [isCodeInputCheckLoading, setIsCodeInputCheckLoading] = useState(false); const { t } = useTranslation(); - const { email: providerEmail, providerAuthToken, isProviderUserCompleted } = useProviderAuth(); - - if (providerAuthToken && isProviderUserCompleted) { - router.push(`/login?providerAuthToken=${encodeURIComponent(providerAuthToken)}`); - } - - if (providerAuthToken && step < 3) { - setStep(3); - } useEffect(() => { const tryAuth = async () => { @@ -121,7 +110,7 @@ export default function SignUp() { return ( ); } @@ -139,7 +128,7 @@ export default function SignUp() { return ( diff --git a/frontend/src/pages/signup/sso/index.tsx b/frontend/src/pages/signup/sso/index.tsx new file mode 100644 index 0000000000..5d964f38df --- /dev/null +++ b/frontend/src/pages/signup/sso/index.tsx @@ -0,0 +1,28 @@ +import { useTranslation } from "react-i18next"; +import Head from "next/head"; +import Image from "next/image"; +import { useRouter } from "next/router" + +import { SignupSSO } from "@app/views/Signup"; + +export default function SignupSSOPage() { + const { t } = useTranslation(); + const router = useRouter(); + const token = router.query.token as string; + + return ( +
+ + {t("common.head-title", { title: t("signup.title") })} + + + + + +
+ Infisical Logo +
+ +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx b/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx index d74c88893b..1f845b6448 100644 --- a/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx +++ b/frontend/src/views/IntegrationsPage/IntegrationPage.utils.tsx @@ -35,7 +35,7 @@ export const redirectForProviderAuth = (integrationOption: TCloudIntegration) => // generate CSRF token for OAuth2 code-token exchange integrations const state = crypto.randomBytes(16).toString("hex"); localStorage.setItem("latestCSRFToken", state); - + let link = ""; switch (integrationOption.slug) { case "azure-key-vault": @@ -86,15 +86,30 @@ export const redirectForProviderAuth = (integrationOption: TCloudIntegration) => case "railway": link = `${window.location.origin}/integrations/railway/authorize`; break; + case "terraform-cloud": + link = `${window.location.origin}/integrations/terraform-cloud/authorize`; + break; case "hashicorp-vault": link = `${window.location.origin}/integrations/hashicorp-vault/authorize`; break; case "cloudflare-pages": link = `${window.location.origin}/integrations/cloudflare-pages/authorize`; break; + case "bitbucket": + link = `https://bitbucket.org/site/oauth2/authorize?client_id=${integrationOption.clientId}&response_type=code&redirect_uri=${window.location.origin}/integrations/bitbucket/oauth2/callback&state=${state}`; + break; case "codefresh": link = `${window.location.origin}/integrations/codefresh/authorize`; break; + case "digital-ocean-app-platform": + link = `${window.location.origin}/integrations/digital-ocean-app-platform/authorize`; + break; + case "cloud-66": + link = `${window.location.origin}/integrations/cloud-66/authorize`; + break; + case "northflank": + link = `${window.location.origin}/integrations/northflank/authorize`; + break; case "windmill": link = `${window.location.origin}/integrations/windmill/authorize`; break; diff --git a/frontend/src/views/IntegrationsPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx b/frontend/src/views/IntegrationsPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx index 4ce1bd083b..7f458d5e59 100644 --- a/frontend/src/views/IntegrationsPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx +++ b/frontend/src/views/IntegrationsPage/components/CloudIntegrationSection/CloudIntegrationSection.tsx @@ -32,7 +32,7 @@ export const CloudIntegrationSection = ({ const isEmpty = !isLoading && !cloudIntegrations?.length; const sortedCloudIntegrations = cloudIntegrations.sort((a, b) => a.name.localeCompare(b.name)); - + return (
@@ -67,18 +67,9 @@ export const CloudIntegrationSection = ({ width={70} alt="integration logo" /> - {cloudIntegration.name.split(" ").length > 2 ? ( -
-
{cloudIntegration.name.split(" ")[0]}
-
- {cloudIntegration.name.split(" ")[1]} {cloudIntegration.name.split(" ")[2]} -
-
- ) : ( -
- {cloudIntegration.name} -
- )} +
+ {cloudIntegration.name} +
{cloudIntegration.isAvailable && Boolean(integrationAuths?.[cloudIntegration.slug]) && (
diff --git a/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx b/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx index fd8f72887f..a058edf9aa 100644 --- a/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx +++ b/frontend/src/views/IntegrationsPage/components/IntegrationsSection/IntegrationsSection.tsx @@ -105,7 +105,8 @@ export const IntegrationsSection = ({ {(integration.integration === "vercel" || integration.integration === "netlify" || integration.integration === "railway" || - integration.integration === "gitlab") && ( + integration.integration === "gitlab" || + integration.integration === "bitbucket") && (
diff --git a/frontend/src/views/Login/Login.tsx b/frontend/src/views/Login/Login.tsx new file mode 100644 index 0000000000..d7ddf60783 --- /dev/null +++ b/frontend/src/views/Login/Login.tsx @@ -0,0 +1,89 @@ +import { useEffect, useState } from "react"; +import { useRouter } from "next/router"; +import axios from "axios" + +import { fetchUserDetails } from "@app/hooks/api/users/queries"; +import getOrganizations from "@app/pages/api/organization/getOrgs"; +import { getAuthToken, isLoggedIn } from "@app/reactQuery"; + +import { + InitialStep, + MFAStep, + SAMLSSOStep +} from "./components"; + +export const Login = () => { + const router = useRouter(); + const [step, setStep] = useState(0); + const [email, setEmail] = useState(""); + const [password, setPassword] = useState(""); + + const queryParams = new URLSearchParams(window.location.search) + + useEffect(() => { + // TODO(akhilmhdh): workspace will be controlled by a workspace context + const redirectToDashboard = async () => { + try { + const userOrgs = await getOrganizations(); + // userWorkspace = userWorkspaces[0] && userWorkspaces[0]._id; + const userOrg = userOrgs[0] && userOrgs[0]._id; + + // user details + const userDetails = await fetchUserDetails() + // send details back to client + + if (queryParams && queryParams.get("callback_port")) { + const callbackPort = queryParams.get("callback_port") + + // send post request to cli with details + const cliUrl = `http://localhost:${callbackPort}` + const instance = axios.create() + await instance.post(cliUrl, { email: userDetails.email, privateKey: localStorage.getItem("PRIVATE_KEY"), JTWToken: getAuthToken() }) + } + router.push(`/org/${userOrg}/overview`); + } catch (error) { + console.log("Error - Not logged in yet"); + } + }; + if (isLoggedIn()) { + redirectToDashboard(); + } + }, []); + + const renderView = () => { + switch (step) { + case 0: + return ( + + ); + case 1: + return ( + + ); + case 2: + return ( + + ); + + default: + return
; + } + } + + return ( +
+ {renderView()} +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/LoginSSO.tsx b/frontend/src/views/Login/LoginSSO.tsx new file mode 100644 index 0000000000..548bee3aec --- /dev/null +++ b/frontend/src/views/Login/LoginSSO.tsx @@ -0,0 +1,65 @@ +import { useEffect, useState } from "react"; +import jwt_decode from "jwt-decode"; + +import { + MFAStep, + PasswordStep +} from "./components"; + +type Props = { + providerAuthToken: string; +} + +export const LoginSSO = ({ providerAuthToken }: Props) => { + const [step, setStep] = useState(0); + const [password, setPassword] = useState(""); + + const { + email, + isUserCompleted, + callbackPort + } = jwt_decode(providerAuthToken) as any; + + useEffect(() => { + if (isUserCompleted) { + setStep(1); + } + }, []); + + const renderView = () => { + switch (step) { + case 0: + return ( +
+ ); + case 1: + return ( + + ); + case 2: + return ( + + ); + default: + return
; + } + } + + return ( +
+ {renderView()} +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/components/InitialStep/InitialStep.tsx b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx new file mode 100644 index 0000000000..3f436e88eb --- /dev/null +++ b/frontend/src/views/Login/components/InitialStep/InitialStep.tsx @@ -0,0 +1,217 @@ +import { FormEvent, useState } from "react"; +import { useTranslation } from "react-i18next"; +import Link from "next/link"; +import { useRouter } from "next/router"; +import { faGoogle } from "@fortawesome/free-brands-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import axios from "axios" + +import Error from "@app/components/basic/Error"; +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import attemptCliLogin from "@app/components/utilities/attemptCliLogin"; +import attemptLogin from "@app/components/utilities/attemptLogin"; +import { Button, Input } from "@app/components/v2"; +import getOrganizations from "@app/pages/api/organization/getOrgs"; + +type Props = { + setStep: (step: number) => void; + email: string; + setEmail: (email: string) => void; + password: string; + setPassword: (email: string) => void; +} + +export const InitialStep = ({ + setStep, + email, + setEmail, + password, + setPassword +}: Props) => { + const router = useRouter(); + const { createNotification } = useNotificationContext(); + const { t } = useTranslation(); + const [isLoading, setIsLoading] = useState(false); + const [loginError, setLoginError] = useState(false); + const [loginEmailChosen, setLoginEmailChosen] = useState(false); + + const queryParams = new URLSearchParams(window.location.search); + + const handleLogin = async (e: FormEvent) => { + e.preventDefault() + try { + if (!email || !password) { + return; + } + + setIsLoading(true); + if (queryParams && queryParams.get("callback_port")) { + const callbackPort = queryParams.get("callback_port") + + // attemptCliLogin + const isCliLoginSuccessful = await attemptCliLogin({ + email, + password, + }) + + if (isCliLoginSuccessful && isCliLoginSuccessful.success) { + + if (isCliLoginSuccessful.mfaEnabled) { + // case: login requires MFA step + setStep(1); + setIsLoading(false); + return; + } + // case: login was successful + const cliUrl = `http://localhost:${callbackPort}` + + // send request to server endpoint + const instance = axios.create() + const cliResp = await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse }) + console.log(cliResp) + + // cli page + router.push("/cli-redirect"); + + // on success, router.push to cli Login Successful page + + } + } else { + const isLoginSuccessful = await attemptLogin({ + email, + password, + }); + if (isLoginSuccessful && isLoginSuccessful.success) { + // case: login was successful + + if (isLoginSuccessful.mfaEnabled) { + // case: login requires MFA step + setStep(1); + setIsLoading(false); + return; + } + const userOrgs = await getOrganizations(); + const userOrg = userOrgs[0] && userOrgs[0]._id; + + // case: login does not require MFA step + createNotification({ + text: "Successfully logged in", + type: "success" + }); + router.push(`/org/${userOrg}/overview`); + } + } + + + } catch (err) { + setLoginError(true); + createNotification({ + text: "Login unsuccessful. Double-check your credentials and try again.", + type: "error" + }); + } + + setIsLoading(false); + } + + return ( +
+

Login to Infisical

+
+ +
+ {loginEmailChosen && <> +
+
+
+
+ setEmail(e.target.value)} + type="email" + placeholder="Enter your email..." + isRequired + autoComplete="username" + className="h-12" + /> +
+
+ setPassword(e.target.value)} + type="password" + placeholder="Enter your password..." + isRequired + autoComplete="current-password" + id="current-password" + className="h-12 select:-webkit-autofill:focus" + /> +
+
+ +
+ {!isLoading && loginError && } +
+
+
} + {!loginEmailChosen &&
+ +
} +
+ +
+
+ Don't have an acount yet? + + {t("login.create-account")} + +
+
+ Forgot password? + + Recover your account + +
+ + ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/components/InitialStep/index.tsx b/frontend/src/views/Login/components/InitialStep/index.tsx new file mode 100644 index 0000000000..466fbe1d7a --- /dev/null +++ b/frontend/src/views/Login/components/InitialStep/index.tsx @@ -0,0 +1 @@ +export { InitialStep } from "./InitialStep"; \ No newline at end of file diff --git a/frontend/src/components/login/MFAStep.tsx b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx similarity index 85% rename from frontend/src/components/login/MFAStep.tsx rename to frontend/src/views/Login/components/MFAStep/MFAStep.tsx index d75442d8eb..fe4a0fd012 100644 --- a/frontend/src/components/login/MFAStep.tsx +++ b/frontend/src/views/Login/components/MFAStep/MFAStep.tsx @@ -1,18 +1,17 @@ -/* eslint-disable react/jsx-props-no-spreading */ import React, { useState } from "react"; import ReactCodeInput from "react-code-input"; import { useTranslation } from "react-i18next"; import { useRouter } from "next/router"; import axios from "axios" +import Error from "@app/components/basic/Error"; // which to notification +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import attemptCliLoginMfa from "@app/components/utilities/attemptCliLoginMfa" import attemptLoginMfa from "@app/components/utilities/attemptLoginMfa"; +import { Button } from "@app/components/v2"; import { useSendMfaToken } from "@app/hooks/api/auth"; import getOrganizations from "@app/pages/api/organization/getOrgs"; -import Error from "../basic/Error"; -import { Button } from "../v2"; - // The style for the verification code input const props = { inputStyle: { @@ -33,6 +32,13 @@ const props = { } } as const; +type Props = { + email: string; + password: string; + providerAuthToken?: string; + callbackPort?: string | null; +} + interface VerifyMfaTokenError { response: { data: { @@ -45,23 +51,13 @@ interface VerifyMfaTokenError { }; } -/** - * 2nd step of login - users enter their MFA code - * @param {Object} obj - * @param {String} obj.email - email of user - * @param {String} obj.password - password of user - * @param {Function} obj.setStep - function to set the login flow step - * @returns - */ -export default function MFAStep({ +export const MFAStep = ({ email, password, providerAuthToken, -}: { - email: string; - password: string; - providerAuthToken?: string; -}): JSX.Element { + callbackPort +}: Props) => { + const { createNotification } = useNotificationContext(); const router = useRouter(); const [isLoading, setIsLoading] = useState(false); const [isLoadingResend, setIsLoadingResend] = useState(false); @@ -75,13 +71,15 @@ export default function MFAStep({ const handleLoginMfa = async () => { try { if (mfaCode.length !== 6) { + createNotification({ + text: "Please enter a 6-digit MFA code and try again", + type: "error" + }); return; } setIsLoading(true); - const queryParams = new URLSearchParams(window.location.search) - if (queryParams && queryParams.get("callback_port")){ - const callbackPort = queryParams.get("callback_port") + if (callbackPort){ // attemptCliLogin const isCliLoginSuccessful = await attemptCliLoginMfa({ @@ -116,12 +114,25 @@ export default function MFAStep({ const userOrg = userOrgs[0] && userOrgs[0]._id; // case: login does not require MFA step + createNotification({ + text: "Successfully logged in", + type: "success" + }); router.push(`/org/${userOrg}/overview`); + } else { + createNotification({ + text: "Failed to log in", + type: "error" + }); } } } catch (err) { const error = err as VerifyMfaTokenError; + createNotification({ + text: "Failed to log in", + type: "error" + }); if (error?.response?.status === 500) { window.location.reload(); @@ -147,8 +158,8 @@ export default function MFAStep({ } }; - return ( -
+ return ( +

{t("mfa.step2-message")}

{email}

@@ -204,6 +215,6 @@ export default function MFAStep({

{t("signup.step2-spam-alert")}

- - ); -} + + ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/components/MFAStep/index.tsx b/frontend/src/views/Login/components/MFAStep/index.tsx new file mode 100644 index 0000000000..633981543f --- /dev/null +++ b/frontend/src/views/Login/components/MFAStep/index.tsx @@ -0,0 +1 @@ +export { MFAStep } from "./MFAStep"; \ No newline at end of file diff --git a/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx b/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx new file mode 100644 index 0000000000..6076e76bb1 --- /dev/null +++ b/frontend/src/views/Login/components/PasswordStep/PasswordStep.tsx @@ -0,0 +1,161 @@ +import { useState } from "react"; +import { useTranslation } from "react-i18next"; +import Link from "next/link"; +import { useRouter } from "next/router" +import axios from "axios" + +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import attemptCliLogin from "@app/components/utilities/attemptCliLogin"; +import attemptLogin from "@app/components/utilities/attemptLogin"; +import { Button, Input } from "@app/components/v2"; +import getOrganizations from "@app/pages/api/organization/getOrgs"; + +type Props = { + providerAuthToken: string; + callbackPort?: string; + email: string; + password: string; + setPassword: (password: string) => void; + setStep: (step: number) => void; +} + +export const PasswordStep = ({ + providerAuthToken, + callbackPort, + email, + password, + setPassword, + setStep +}: Props) => { + const { createNotification } = useNotificationContext(); + const [isLoading, setIsLoading] = useState(false); + const { t } = useTranslation(); + const router = useRouter(); + + const handleLogin = async () => { + try { + setIsLoading(true); + + if (callbackPort) { + // attemptCliLogin + const isCliLoginSuccessful = await attemptCliLogin({ + email, + password, + providerAuthToken + }) + + if (isCliLoginSuccessful && isCliLoginSuccessful.success) { + + if (isCliLoginSuccessful.mfaEnabled) { + // case: login requires MFA step + setStep(2); + setIsLoading(false); + return; + } + // case: login was successful + const cliUrl = `http://localhost:${callbackPort}` + + // send request to server endpoint + const instance = axios.create() + await instance.post(cliUrl, { ...isCliLoginSuccessful.loginResponse }) + + // cli page + router.push("/cli-redirect"); + + // on success, router.push to cli Login Successful page + } + } else { + const loginAttempt = await attemptLogin({ + email, + password, + providerAuthToken, + }); + + if (loginAttempt && loginAttempt.success) { + // case: login was successful + + if (loginAttempt.mfaEnabled) { + // TODO: deal with MFA + // case: login requires MFA step + setIsLoading(false); + setStep(2); + return; + } + + // case: login does not require MFA step + const userOrgs = await getOrganizations(); + const userOrg = userOrgs[0]._id; + setIsLoading(false); + createNotification({ + text: "Successfully logged in", + type: "success" + }); + router.push(`/org/${userOrg?._id}/overview`); + } + } + } catch (err) { + setIsLoading(false); + createNotification({ + text: "Login unsuccessful. Double-check your master password and try again.", + type: "error" + }); + console.error(err); + } + }; + + return ( +
e.preventDefault()} + className="h-full mx-auto w-full max-w-md px-6 pt-8" + > +

+ What’s your Infisical Password? +

+
+
+ setPassword(e.target.value)} + type="password" + placeholder="Enter your password..." + isRequired + autoComplete="current-password" + id="current-password" + className="h-12" + /> +
+
+
+ +
+
+ + Infisical Master Password serves as a decryption mechanism so that even Google is not able to access your secrets. + + + {t("login.forgot-password")} + +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/components/PasswordStep/index.tsx b/frontend/src/views/Login/components/PasswordStep/index.tsx new file mode 100644 index 0000000000..fb89c29a55 --- /dev/null +++ b/frontend/src/views/Login/components/PasswordStep/index.tsx @@ -0,0 +1 @@ +export { PasswordStep } from "./PasswordStep"; \ No newline at end of file diff --git a/frontend/src/views/Login/components/SAMLSSOStep/SAMLSSOStep.tsx b/frontend/src/views/Login/components/SAMLSSOStep/SAMLSSOStep.tsx new file mode 100644 index 0000000000..8ff363d36e --- /dev/null +++ b/frontend/src/views/Login/components/SAMLSSOStep/SAMLSSOStep.tsx @@ -0,0 +1,65 @@ +import { useState } from "react"; +import { useTranslation } from "react-i18next"; + +import { Button, Input } from "@app/components/v2"; + +type Props = { + setStep: (step: number) => void; +} + +export const SAMLSSOStep = ({ + setStep +}: Props) => { + const [ssoIdentifier, setSSOIdentifier] = useState(""); + const { t } = useTranslation(); + + const queryParams = new URLSearchParams(window.location.search); + + return ( +
+

+ What's your SSO Identifier? +

+
+
+ setSSOIdentifier(e.target.value)} + type="text" + placeholder="Enter your SSO identifier..." + isRequired + autoComplete="email" + id="email" + className="h-12" + /> +
+
+
+ +
+
+ +
+
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Login/components/SAMLSSOStep/index.tsx b/frontend/src/views/Login/components/SAMLSSOStep/index.tsx new file mode 100644 index 0000000000..d3d2105bda --- /dev/null +++ b/frontend/src/views/Login/components/SAMLSSOStep/index.tsx @@ -0,0 +1 @@ +export { SAMLSSOStep } from "./SAMLSSOStep"; \ No newline at end of file diff --git a/frontend/src/views/Login/components/index.tsx b/frontend/src/views/Login/components/index.tsx new file mode 100644 index 0000000000..e86cce83de --- /dev/null +++ b/frontend/src/views/Login/components/index.tsx @@ -0,0 +1,6 @@ +export { InitialStep } from "./InitialStep"; +export { MFAStep } from "./MFAStep"; +export { SAMLSSOStep } from "./SAMLSSOStep"; + +// SSO-specific step +export { PasswordStep } from "./PasswordStep"; \ No newline at end of file diff --git a/frontend/src/views/Login/index.tsx b/frontend/src/views/Login/index.tsx new file mode 100644 index 0000000000..2c4c1f9539 --- /dev/null +++ b/frontend/src/views/Login/index.tsx @@ -0,0 +1,2 @@ +export { Login } from "./Login"; +export { LoginSSO } from "./LoginSSO"; diff --git a/frontend/src/views/Org/MembersPage/components/OrgMembersTable/OrgMembersTable.tsx b/frontend/src/views/Org/MembersPage/components/OrgMembersTable/OrgMembersTable.tsx index a995661c93..3a39560ca3 100644 --- a/frontend/src/views/Org/MembersPage/components/OrgMembersTable/OrgMembersTable.tsx +++ b/frontend/src/views/Org/MembersPage/components/OrgMembersTable/OrgMembersTable.tsx @@ -6,6 +6,7 @@ import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { yupResolver } from "@hookform/resolvers/yup"; import * as yup from "yup"; +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; import { Button, DeleteActionModal, @@ -26,9 +27,11 @@ import { Th, THead, Tr, - UpgradePlanModal} from "@app/components/v2"; -import { useWorkspace } from "@app/context"; + UpgradePlanModal +} from "@app/components/v2"; +import { useOrganization , useWorkspace } from "@app/context"; import { usePopUp, useToggle } from "@app/hooks"; +import { useGetSSOConfig } from "@app/hooks/api"; import { useFetchServerStatus } from "@app/hooks/api/serverDetails"; import { OrgUser, Workspace } from "@app/hooks/api/types"; @@ -69,6 +72,9 @@ export const OrgMembersTable = ({ setCompleteInviteLink }: Props) => { const router = useRouter(); + const { createNotification } = useNotificationContext(); + const { currentOrg } = useOrganization(); + const { data: ssoConfig, isLoading: isLoadingSSOConfig } = useGetSSOConfig(currentOrg?._id ?? ""); const [searchMemberFilter, setSearchMemberFilter] = useState(""); const {data: serverDetails } = useFetchServerStatus() const { workspaces } = useWorkspace(); @@ -79,7 +85,7 @@ export const OrgMembersTable = ({ "upgradePlan", "setUpEmail" ] as const); - + useEffect(() => { if (router.query.action === "invite") { handlePopUpOpen("addMember"); @@ -152,6 +158,15 @@ export const OrgMembersTable = ({ + )} + ( + + + + )} + /> +
+ + +
+ + + + ); +} \ No newline at end of file diff --git a/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistSection.tsx b/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistSection.tsx new file mode 100644 index 0000000000..729ab549e5 --- /dev/null +++ b/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistSection.tsx @@ -0,0 +1,105 @@ +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import { + Button, + DeleteActionModal, + UpgradePlanModal +} from "@app/components/v2"; +import { useSubscription,useWorkspace } from "@app/context"; +import { + useDeleteTrustedIp +} from "@app/hooks/api"; +import { usePopUp } from "@app/hooks/usePopUp"; + +import { IPAllowlistModal } from "./IPAllowlistModal"; +import { IPAllowlistTable } from "./IPAllowlistTable"; + +export const IPAllowlistSection = () => { + const { createNotification } = useNotificationContext(); + const { mutateAsync } = useDeleteTrustedIp(); + const { subscription } = useSubscription(); + const { currentWorkspace } = useWorkspace(); + + const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ + "trustedIp", + "deleteTrustedIp", + "upgradePlan" + ] as const); + + const onDeleteTrustedIpSubmit = async (trustedIpId: string) => { + try { + + if (!currentWorkspace?._id) return; + + await mutateAsync({ + workspaceId: currentWorkspace._id, + trustedIpId + }); + + createNotification({ + text: "Successfully deleted IP access range", + type: "success" + }); + + handlePopUpClose("deleteTrustedIp"); + } catch (err) { + console.log(err); + createNotification({ + text: "Failed to delete IP access range", + type: "error" + }); + } + } + + return ( +
+
+

+ IP Allowlist +

+ +
+ + + handlePopUpToggle("deleteTrustedIp", isOpen)} + deleteKey="confirm" + onDeleteApproved={() => + onDeleteTrustedIpSubmit((popUp?.deleteTrustedIp?.data as { trustedIpId: string })?.trustedIpId) + } + /> + handlePopUpToggle("upgradePlan", isOpen)} + text="You can use IP allowlisting if you switch to Infisical's Pro plan." + /> +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistTable.tsx b/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistTable.tsx new file mode 100644 index 0000000000..d160f15dbd --- /dev/null +++ b/frontend/src/views/Project/IPAllowListPage/components/IPAllowlistTable.tsx @@ -0,0 +1,162 @@ +import { faGlobe, faPencil, faXmark } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { + EmptyState, + IconButton, + Table, + TableContainer, + TableSkeleton, + TBody, + Td, + Th, + THead, + Tr, + UpgradePlanModal +} from "@app/components/v2"; +import { useSubscription, useWorkspace } from "@app/context"; +import { + useGetTrustedIps +} from "@app/hooks/api"; +import { UsePopUpState } from "@app/hooks/usePopUp"; + +type Props = { + popUp: UsePopUpState<["upgradePlan"]>; + handlePopUpOpen: ( + popUpName: keyof UsePopUpState<["trustedIp", "deleteTrustedIp", "upgradePlan"]>, + data?: { + trustedIpId: string; + ipAddress?: string; + comment?: string; + isActive?: boolean; + prefix?: number; + }, + ) => void; + handlePopUpToggle: (popUpName: keyof UsePopUpState<["upgradePlan"]>, state?: boolean) => void; +}; + +export const IPAllowlistTable = ({ + popUp, + handlePopUpOpen, + handlePopUpToggle +}: Props) => { + const { subscription } = useSubscription(); + const { currentWorkspace } = useWorkspace(); + const { data, isLoading } = useGetTrustedIps(currentWorkspace?._id ?? ""); + + const formatType = (type: string, prefix?: number) => { + return `${type.slice(0, 2).toUpperCase() + type.slice(2)} ${(prefix !== undefined) ? "CIDR" : ""}`; + } + + return ( +
+ + + + + + + + {/* */} + + + + {!isLoading && data && data?.length > 0 && data + .sort((a, b) => a.ipAddress.localeCompare(b.ipAddress)) + .map(({ + _id, + ipAddress, + comment, + type, + prefix, + isActive + }) => { + return ( + + + + + {/* */} + + + ); + })} + {isLoading && } + {!isLoading && data && data?.length === 0 && ( + + + + )} + +
IP Address / RangeFormatCommentStatus +
+ {`${ipAddress}${(prefix !== undefined) ? `/${prefix}` : ""}`} + + {formatType(type, prefix)} + + {comment} + +
+ +

Active

+
+
+ { + if (subscription?.ipAllowlisting) { + handlePopUpOpen("trustedIp", { + trustedIpId: _id, + ipAddress, + comment, + prefix, + isActive + }); + } else { + handlePopUpOpen("upgradePlan"); + } + }} + colorSchema="primary" + variant="plain" + ariaLabel="update" + > + + + { + if (subscription?.ipAllowlisting) { + handlePopUpOpen("deleteTrustedIp", { + trustedIpId: _id + }); + } else { + handlePopUpOpen("upgradePlan"); + } + }} + size="lg" + colorSchema="danger" + variant="plain" + ariaLabel="update" + > + + +
+ +
+
+ handlePopUpToggle("upgradePlan", isOpen)} + text="You can use IP allowlisting if you switch to Infisical's Pro plan." + /> +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Project/IPAllowListPage/components/index.tsx b/frontend/src/views/Project/IPAllowListPage/components/index.tsx new file mode 100644 index 0000000000..d4146cb4d1 --- /dev/null +++ b/frontend/src/views/Project/IPAllowListPage/components/index.tsx @@ -0,0 +1 @@ +export { IPAllowlistSection } from "./IPAllowlistSection"; \ No newline at end of file diff --git a/frontend/src/views/Project/IPAllowListPage/index.tsx b/frontend/src/views/Project/IPAllowListPage/index.tsx new file mode 100644 index 0000000000..e7a4071840 --- /dev/null +++ b/frontend/src/views/Project/IPAllowListPage/index.tsx @@ -0,0 +1 @@ +export { IPAllowlistPage } from "./IPAllowlistPage"; \ No newline at end of file diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx index e763691d55..0f27757fae 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/CompanyNameSection.tsx @@ -7,7 +7,8 @@ import { useNotificationContext } from "@app/components/context/Notifications/No import { Button, FormControl, - Input} from "@app/components/v2"; + Input +} from "@app/components/v2"; import { useOrganization } from "@app/context"; import { useGetOrgBillingDetails, diff --git a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx index 7f566c5f3a..a124813ed4 100644 --- a/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx +++ b/frontend/src/views/Settings/BillingSettingsPage/components/BillingDetailsTab/PmtMethodsSection.tsx @@ -29,7 +29,7 @@ export const PmtMethodsSection = () => {

- Payment Methods + Payment methods

); diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx new file mode 100644 index 0000000000..9a36722371 --- /dev/null +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgAuthTab.tsx @@ -0,0 +1,9 @@ +import { OrgSSOSection } from "./OrgSSOSection"; + +export const OrgAuthTab = () => { + return ( +
+ +
+ ); +} \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx new file mode 100644 index 0000000000..73213db31f --- /dev/null +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/OrgSSOSection.tsx @@ -0,0 +1,119 @@ +import { faPlus } from "@fortawesome/free-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import { Button, Switch, UpgradePlanModal } from "@app/components/v2"; +import { useOrganization, useSubscription } from "@app/context"; +import { + useGetSSOConfig, + useUpdateSSOConfig +} from "@app/hooks/api"; +import { usePopUp } from "@app/hooks/usePopUp"; + +import { SSOModal } from "./SSOModal"; + +const ssoAuthProviderMap: { [key: string]: string } = { + "okta-saml": "Okta SAML 2.0" +} + +export const OrgSSOSection = (): JSX.Element => { + const { currentOrg } = useOrganization(); + const { subscription } = useSubscription(); + const { createNotification } = useNotificationContext(); + const { data, isLoading } = useGetSSOConfig(currentOrg?._id ?? ""); + const { mutateAsync } = useUpdateSSOConfig(); + const { popUp, handlePopUpOpen, handlePopUpClose, handlePopUpToggle } = usePopUp([ + "upgradePlan", + "addSSO" + ] as const); + + const handleSamlSSOToggle = async (value: boolean) => { + try { + if (!currentOrg?._id) return; + + await mutateAsync({ + organizationId: currentOrg?._id, + isActive: value + }); + + createNotification({ + text: `Successfully ${value ? "enabled" : "disabled"} SAML SSO`, + type: "success" + }); + } catch (err) { + console.error(err); + createNotification({ + text: `Failed to ${value ? "enable" : "disable"} SAML SSO`, + type: "error" + }); + } + } + + return ( +
+
+

+ SAML SSO Configuration +

+ {!isLoading && ( + + )} +
+ {!isLoading && data && ( + <> +
+ handleSamlSSOToggle(value)} + isChecked={data.isActive} + > + Enable SAML SSO + +
+
+

SSO identifier

+

{data._id}

+
+
+

Type

+

{ssoAuthProviderMap[data.authProvider]}

+
+
+

Audience

+

{data.audience}

+
+
+

Entrypoint

+

{data.entryPoint}

+
+
+

Issuer

+

{data.issuer}

+
+ + )} + + handlePopUpToggle("upgradePlan", isOpen)} + text="You can use SAML SSO if you switch to Infisical's Pro plan." + /> +
+ ); +}; \ No newline at end of file diff --git a/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/SSOModal.tsx b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/SSOModal.tsx new file mode 100644 index 0000000000..15cffa761d --- /dev/null +++ b/frontend/src/views/Settings/OrgSettingsPage/components/OrgAuthTab/SSOModal.tsx @@ -0,0 +1,253 @@ +import { useEffect } from "react"; +import { Controller, useForm } from "react-hook-form"; +import { yupResolver } from "@hookform/resolvers/yup"; +import * as yup from "yup"; + +import { useNotificationContext } from "@app/components/context/Notifications/NotificationProvider"; +import { + Button, + FormControl, + Input, + Modal, + ModalContent, + Select, + SelectItem, + TextArea} from "@app/components/v2"; +import { useOrganization } from "@app/context"; +import { + useCreateSSOConfig, + useGetSSOConfig, + useUpdateSSOConfig +} from "@app/hooks/api"; +import { UsePopUpState } from "@app/hooks/usePopUp"; + +const ssoAuthProviders = [ + { label: "Okta SAML 2.0", value: "okta-saml" } +]; + +const schema = yup.object({ + authProvider: yup.string().required("SSO Type is required"), + entryPoint: yup.string().required("IDP entrypoint is required"), + issuer: yup.string().required("Issuer string is required"), + cert: yup.string().required("IDP's public signing certificate is required"), + audience: yup.string().required("Expected SAML response audience is required"), +}).required(); + +export type AddSSOFormData = yup.InferType; + +type Props = { + popUp: UsePopUpState<["addSSO"]>; + handlePopUpClose: (popUpName: keyof UsePopUpState<["addSSO"]>) => void; + handlePopUpToggle: (popUpName: keyof UsePopUpState<["addSSO"]>, state?: boolean) => void; +}; + +export const SSOModal = ({ + popUp, + handlePopUpClose, + handlePopUpToggle +}: Props) => { + const { currentOrg } = useOrganization(); + const { createNotification } = useNotificationContext(); + const { mutateAsync: createMutateAsync, isLoading: createIsLoading } = useCreateSSOConfig(); + const { mutateAsync: updateMutateAsync, isLoading: updateIsLoading } = useUpdateSSOConfig(); + const { data } = useGetSSOConfig(currentOrg?._id ?? ""); + + const { + control, + handleSubmit, + reset, + watch, + } = useForm({ + defaultValues: { + authProvider: "okta-saml" + }, + resolver: yupResolver(schema) + }); + + useEffect(() => { + if (data) { + reset({ + authProvider: data?.authProvider ?? "", + entryPoint: data?.entryPoint ?? "", + issuer: data?.issuer ?? "", + cert: data?.cert ?? "", + audience: data?.audience ?? "" + }); + } + }, [data]); + + const onSSOModalSubmit = async ({ + authProvider, + entryPoint, + issuer, + cert, + audience + }: AddSSOFormData) => { + try { + if (!currentOrg) return; + + if (!data) { + await createMutateAsync({ + organizationId: currentOrg._id, + authProvider, + isActive: false, + entryPoint, + issuer, + cert, + audience + }); + } else { + await updateMutateAsync({ + organizationId: currentOrg._id, + authProvider, + isActive: false, + entryPoint, + issuer, + cert, + audience + }); + } + + handlePopUpClose("addSSO"); + + createNotification({ + text: `Successfully ${!data ? "added" : "updated"} SAML SSO configuration`, + type: "success" + }); + } catch (err) { + console.error(err); + createNotification({ + text: `Failed to ${!data ? "add" : "update"} SAML SSO configuration`, + type: "error" + }); + } + } + + const authProvider = watch("authProvider"); + + return ( + { + handlePopUpToggle("addSSO", isOpen); + reset(); + }} + > + +
+ ( + + + + )} + /> + {authProvider && authProvider === "okta-saml" && ( + <> + ( + + + + )} + /> + ( + + + + )} + /> + ( + + + + )} + /> + ( + +