diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 000000000..6a47c2536 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,2 @@ +backend/node_modules +frontend/node_modules \ No newline at end of file diff --git a/.env.example b/.env.example index 79fca5686..59c9c5930 100644 --- a/.env.example +++ b/.env.example @@ -1,5 +1,6 @@ # Keys # Required key for platform encryption/decryption ops +# THIS IS A SAMPLE ENCRYPTION KEY AND SHOULD NOT BE USED FOR PRODUCTION ENCRYPTION_KEY=6c1fe4e407b8911c104518103505b218 # JWT @@ -8,6 +9,7 @@ JWT_SIGNUP_SECRET=3679e04ca949f914c03332aaaeba805a JWT_REFRESH_SECRET=5f2f3c8f0159068dc2bbb3a652a716ff JWT_AUTH_SECRET=4be6ba5602e0fa0ac6ac05c3cd4d247f JWT_SERVICE_SECRET=f32f716d70a42c5703f4656015e76200 +JWT_PROVIDER_AUTH_SECRET=f32f716d70a42c5703f4656015e76201 # JWT lifetime # Optional lifetimes for JWT tokens expressed in seconds or a string @@ -15,6 +17,7 @@ JWT_SERVICE_SECRET=f32f716d70a42c5703f4656015e76200 JWT_AUTH_LIFETIME= JWT_REFRESH_LIFETIME= JWT_SIGNUP_LIFETIME= +JWT_PROVIDER_AUTH_LIFETIME= # MongoDB # Backend will connect to the MongoDB instance at connection string MONGO_URL which can either be a ref @@ -30,14 +33,12 @@ MONGO_PASSWORD=example # Required SITE_URL=http://localhost:8080 -# Mail/SMTP -SMTP_HOST= # required -SMTP_USERNAME= # required -SMTP_PASSWORD= # required -SMTP_PORT=587 -SMTP_SECURE=false -SMTP_FROM_ADDRESS= # required -SMTP_FROM_NAME=Infisical +# Mail/SMTP +SMTP_HOST= +SMTP_PORT= +SMTP_NAME= +SMTP_USERNAME= +SMTP_PASSWORD= # Integration # Optional only if integration is used @@ -66,4 +67,7 @@ STRIPE_WEBHOOK_SECRET= STRIPE_PRODUCT_STARTER= STRIPE_PRODUCT_TEAM= STRIPE_PRODUCT_PRO= -NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= \ No newline at end of file +NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY= + +CLIENT_ID_GOOGLE= +CLIENT_SECRET_GOOGLE= diff --git a/.github/images/deploy-aws-button.png b/.github/images/deploy-aws-button.png new file mode 100644 index 000000000..2a44a926a Binary files /dev/null and b/.github/images/deploy-aws-button.png differ diff --git a/.github/images/do-k8-install-btn.png b/.github/images/do-k8-install-btn.png new file mode 100644 index 000000000..79b286a48 Binary files /dev/null and b/.github/images/do-k8-install-btn.png differ diff --git a/.github/resources/docker-compose.be-test.yml b/.github/resources/docker-compose.be-test.yml index 6efdd87f6..c256649c1 100644 --- a/.github/resources/docker-compose.be-test.yml +++ b/.github/resources/docker-compose.be-test.yml @@ -13,6 +13,7 @@ services: - MONGO_URL=mongodb://test:example@mongo:27017/?authSource=admin - MONGO_USERNAME=test - MONGO_PASSWORD=example + - ENCRYPTION_KEY=a984ecdf82ec779e55dbcc21303a900f networks: - infisical-test diff --git a/.github/values.yaml b/.github/values.yaml index 819df5066..bab85c47e 100644 --- a/.github/values.yaml +++ b/.github/values.yaml @@ -6,7 +6,7 @@ frontend: secrets.infisical.com/auto-reload: "true" replicaCount: 2 image: - repository: infisical/frontend + repository: infisical/staging_deployment_frontend tag: "latest" pullPolicy: Always kubeSecretRef: managed-secret-frontend @@ -25,7 +25,7 @@ backend: secrets.infisical.com/auto-reload: "true" replicaCount: 2 image: - repository: infisical/backend + repository: infisical/staging_deployment_backend tag: "latest" pullPolicy: Always kubeSecretRef: managed-backend-secret diff --git a/.github/workflows/build-docker-image-to-prod.yml b/.github/workflows/build-docker-image-to-prod.yml new file mode 100644 index 000000000..322a553c4 --- /dev/null +++ b/.github/workflows/build-docker-image-to-prod.yml @@ -0,0 +1,118 @@ +name: Release production images (frontend, backend) +on: + push: + tags: + - "infisical/v*.*.*" + +jobs: + backend-image: + name: Build backend image + runs-on: ubuntu-latest + steps: + - name: Extract version from tag + id: extract_version + run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}" + - name: ☁️ Checkout source + uses: actions/checkout@v3 + - name: 📦 Install dependencies to test all dependencies + run: npm ci --only-production + working-directory: backend + - name: 🧪 Run tests + run: npm run test:ci + working-directory: backend + - name: Save commit hashes for tag + id: commit + uses: pr-mpt/actions-commit-hash@v2 + - name: 🔧 Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: 🐋 Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Depot CLI + uses: depot/setup-action@v1 + - name: 📦 Build backend and export to Docker + uses: depot/build-push-action@v1 + with: + project: 64mmf0n610 + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + load: true + context: backend + tags: infisical/backend:test + - name: ⏻ Spawn backend container and dependencies + run: | + docker compose -f .github/resources/docker-compose.be-test.yml up --wait --quiet-pull + - name: 🧪 Test backend image + run: | + ./.github/resources/healthcheck.sh infisical-backend-test + - name: ⏻ Shut down backend container and dependencies + run: | + docker compose -f .github/resources/docker-compose.be-test.yml down + - name: 🏗️ Build backend and push + uses: depot/build-push-action@v1 + with: + project: 64mmf0n610 + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + push: true + context: backend + tags: | + infisical/backend:${{ steps.commit.outputs.short }} + infisical/backend:latest + infisical/backend:${{ steps.extract_version.outputs.version }} + platforms: linux/amd64,linux/arm64 + + frontend-image: + name: Build frontend image + runs-on: ubuntu-latest + steps: + - name: Extract version from tag + id: extract_version + run: echo "::set-output name=version::${GITHUB_REF_NAME#infisical/}" + - name: ☁️ Checkout source + uses: actions/checkout@v3 + - name: Save commit hashes for tag + id: commit + uses: pr-mpt/actions-commit-hash@v2 + - name: 🔧 Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: 🐋 Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Depot CLI + uses: depot/setup-action@v1 + - name: 📦 Build frontend and export to Docker + uses: depot/build-push-action@v1 + with: + load: true + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + project: 64mmf0n610 + context: frontend + tags: infisical/frontend:test + build-args: | + POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }} + - name: ⏻ Spawn frontend container + run: | + docker run -d --rm --name infisical-frontend-test infisical/frontend:test + - name: 🧪 Test frontend image + run: | + ./.github/resources/healthcheck.sh infisical-frontend-test + - name: ⏻ Shut down frontend container + run: | + docker stop infisical-frontend-test + - name: 🏗️ Build frontend and push + uses: depot/build-push-action@v1 + with: + project: 64mmf0n610 + push: true + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + context: frontend + tags: | + infisical/frontend:${{ steps.commit.outputs.short }} + infisical/frontend:latest + infisical/frontend:${{ steps.extract_version.outputs.version }} + platforms: linux/amd64,linux/arm64 + build-args: | + POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }} diff --git a/.github/workflows/docker-image.yml b/.github/workflows/build-staging-img.yml similarity index 86% rename from .github/workflows/docker-image.yml rename to .github/workflows/build-staging-img.yml index b4f9546ae..0e50d0906 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/build-staging-img.yml @@ -5,10 +5,15 @@ jobs: backend-image: name: Build backend image runs-on: ubuntu-latest - steps: - name: ☁️ Checkout source uses: actions/checkout@v3 + - name: 📦 Install dependencies to test all dependencies + run: npm ci --only-production + working-directory: backend + - name: 🧪 Run tests + run: npm run test:ci + working-directory: backend - name: Save commit hashes for tag id: commit uses: pr-mpt/actions-commit-hash@v2 @@ -45,14 +50,14 @@ jobs: token: ${{ secrets.DEPOT_PROJECT_TOKEN }} push: true context: backend - tags: infisical/backend:${{ steps.commit.outputs.short }}, - infisical/backend:latest + tags: | + infisical/staging_deployment_backend:${{ steps.commit.outputs.short }} + infisical/staging_deployment_backend:latest platforms: linux/amd64,linux/arm64 frontend-image: name: Build frontend image runs-on: ubuntu-latest - steps: - name: ☁️ Checkout source uses: actions/checkout@v3 @@ -75,12 +80,12 @@ jobs: token: ${{ secrets.DEPOT_PROJECT_TOKEN }} project: 64mmf0n610 context: frontend - tags: infisical/frontend:test + tags: infisical/staging_deployment_frontend:test build-args: | POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }} - name: ⏻ Spawn frontend container run: | - docker run -d --rm --name infisical-frontend-test infisical/frontend:test + docker run -d --rm --name infisical-frontend-test infisical/staging_deployment_frontend:test - name: 🧪 Test frontend image run: | ./.github/resources/healthcheck.sh infisical-frontend-test @@ -94,8 +99,9 @@ jobs: push: true token: ${{ secrets.DEPOT_PROJECT_TOKEN }} context: frontend - tags: infisical/frontend:${{ steps.commit.outputs.short }}, - infisical/frontend:latest + tags: | + infisical/staging_deployment_frontend:${{ steps.commit.outputs.short }} + infisical/staging_deployment_frontend:latest platforms: linux/amd64,linux/arm64 build-args: | POSTHOG_API_KEY=${{ secrets.PUBLIC_POSTHOG_API_KEY }} @@ -122,17 +128,17 @@ jobs: token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} - name: Save DigitalOcean kubeconfig with short-lived credentials run: doctl kubernetes cluster kubeconfig save --expiry-seconds 600 k8s-1-25-4-do-0-nyc1-1670645170179 - - name: switch to gamma namespace + - name: switch to gamma namespace run: kubectl config set-context --current --namespace=gamma - name: test kubectl run: kubectl get ingress - name: Download helm values to file and upgrade gamma deploy run: | wget https://raw.githubusercontent.com/Infisical/infisical/main/.github/values.yaml - helm upgrade infisical infisical-helm-charts/infisical --values values.yaml --recreate-pods + helm upgrade infisical infisical-helm-charts/infisical --values values.yaml --wait if [[ $(helm status infisical) == *"FAILED"* ]]; then echo "Helm upgrade failed" exit 1 else echo "Helm upgrade was successful" - fi \ No newline at end of file + fi diff --git a/.github/workflows/check-be-pull-request.yml b/.github/workflows/check-be-pull-request.yml index 3cb010e8c..2eb040084 100644 --- a/.github/workflows/check-be-pull-request.yml +++ b/.github/workflows/check-be-pull-request.yml @@ -13,6 +13,7 @@ jobs: check-be-pr: name: Check runs-on: ubuntu-latest + timeout-minutes: 15 steps: - name: ☁️ Checkout source @@ -26,17 +27,17 @@ jobs: - name: 📦 Install dependencies run: npm ci --only-production working-directory: backend - - name: 🧪 Run tests - run: npm run test:ci - working-directory: backend - - name: 📁 Upload test results - uses: actions/upload-artifact@v3 - if: always() - with: - name: be-test-results - path: | - ./backend/reports - ./backend/coverage + # - name: 🧪 Run tests + # run: npm run test:ci + # working-directory: backend + # - name: 📁 Upload test results + # uses: actions/upload-artifact@v3 + # if: always() + # with: + # name: be-test-results + # path: | + # ./backend/reports + # ./backend/coverage - name: 🏗️ Run build run: npm run build working-directory: backend diff --git a/.github/workflows/check-fe-pull-request.yml b/.github/workflows/check-fe-pull-request.yml index b91e6f060..75465a014 100644 --- a/.github/workflows/check-fe-pull-request.yml +++ b/.github/workflows/check-fe-pull-request.yml @@ -2,40 +2,35 @@ name: Check Frontend Pull Request on: pull_request: - types: [ opened, synchronize ] + types: [opened, synchronize] paths: - - 'frontend/**' - - '!frontend/README.md' - - '!frontend/.*' - - 'frontend/.eslintrc.js' - + - "frontend/**" + - "!frontend/README.md" + - "!frontend/.*" + - "frontend/.eslintrc.js" jobs: - check-fe-pr: name: Check runs-on: ubuntu-latest + timeout-minutes: 15 steps: - - - name: ☁️ Checkout source + - name: ☁️ Checkout source uses: actions/checkout@v3 - - - name: 🔧 Setup Node 16 + - name: 🔧 Setup Node 16 uses: actions/setup-node@v3 with: - node-version: '16' - cache: 'npm' + node-version: "16" + cache: "npm" cache-dependency-path: frontend/package-lock.json - - - name: 📦 Install dependencies + - name: 📦 Install dependencies run: npm ci --only-production --ignore-scripts working-directory: frontend # - # name: 🧪 Run tests # run: npm run test:ci # working-directory: frontend - - - name: 🏗️ Run build + - name: 🏗️ Run build run: npm run build working-directory: frontend diff --git a/.github/workflows/release-standalone-docker-img.yml b/.github/workflows/release-standalone-docker-img.yml new file mode 100644 index 000000000..84a0aa72e --- /dev/null +++ b/.github/workflows/release-standalone-docker-img.yml @@ -0,0 +1,68 @@ +name: Release standalone docker image +on: [workflow_dispatch] + +jobs: + infisical-standalone: + name: Build infisical standalone image + runs-on: ubuntu-latest + steps: + - name: ☁️ Checkout source + uses: actions/checkout@v3 + with: + fetch-depth: 0 + - name: 📦 Install dependencies to test all dependencies + run: npm ci --only-production + working-directory: backend + - uses: paulhatch/semantic-version@v5.0.2 + id: version + with: + # The prefix to use to identify tags + tag_prefix: "infisical-standalone/v" + # A string which, if present in a git commit, indicates that a change represents a + # major (breaking) change, supports regular expressions wrapped with '/' + major_pattern: "(MAJOR)" + # Same as above except indicating a minor change, supports regular expressions wrapped with '/' + minor_pattern: "(MINOR)" + # A string to determine the format of the version output + version_format: "${major}.${minor}.${patch}-prerelease${increment}" + # Optional path to check for changes. If any changes are detected in the path the + # 'changed' output will true. Enter multiple paths separated by spaces. + change_path: "backend,frontend" + # Prevents pre-v1.0.0 version from automatically incrementing the major version. + # If enabled, when the major version is 0, major releases will be treated as minor and minor as patch. Note that the version_type output is unchanged. + enable_prerelease_mode: true + # - name: 🧪 Run tests + # run: npm run test:ci + # working-directory: backend + - name: version output + run: | + echo "Output Value: ${{ steps.version.outputs.major }}" + echo "Output Value: ${{ steps.version.outputs.minor }}" + echo "Output Value: ${{ steps.version.outputs.patch }}" + echo "Output Value: ${{ steps.version.outputs.version }}" + echo "Output Value: ${{ steps.version.outputs.version_type }}" + echo "Output Value: ${{ steps.version.outputs.increment }}" + - name: Save commit hashes for tag + id: commit + uses: pr-mpt/actions-commit-hash@v2 + - name: 🔧 Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: 🐋 Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Depot CLI + uses: depot/setup-action@v1 + - name: 📦 Build backend and export to Docker + uses: depot/build-push-action@v1 + with: + project: 64mmf0n610 + token: ${{ secrets.DEPOT_PROJECT_TOKEN }} + push: true + context: . + tags: | + infisical/infisical:latest + infisical/infisical:${{ steps.commit.outputs.short }} + platforms: linux/amd64,linux/arm64 + file: Dockerfile.standalone-infisical diff --git a/.github/workflows/release_build.yml b/.github/workflows/release_build.yml index af395ce6c..9840e2d3e 100644 --- a/.github/workflows/release_build.yml +++ b/.github/workflows/release_build.yml @@ -4,7 +4,7 @@ on: push: # run only against tags tags: - - "v*" + - "infisical-cli/v*.*.*" permissions: contents: write @@ -41,13 +41,15 @@ jobs: git clone https://github.com/plentico/osxcross-target.git ../../osxcross/target - uses: goreleaser/goreleaser-action@v4 with: - distribution: goreleaser + distribution: goreleaser-pro version: latest args: release --clean env: GITHUB_TOKEN: ${{ secrets.GO_RELEASER_GITHUB_TOKEN }} + POSTHOG_API_KEY_FOR_CLI: ${{ secrets.POSTHOG_API_KEY_FOR_CLI }} FURY_TOKEN: ${{ secrets.FURYPUSHTOKEN }} AUR_KEY: ${{ secrets.AUR_KEY }} + GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }} - uses: actions/setup-python@v4 - run: pip install --upgrade cloudsmith-cli - name: Publish to CloudSmith diff --git a/.goreleaser.yaml b/.goreleaser.yaml index dfcacf59d..e30c6b763 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -11,10 +11,16 @@ before: - ./cli/scripts/completions.sh - ./cli/scripts/manpages.sh +monorepo: + tag_prefix: infisical-cli/ + dir: cli + builds: - id: darwin-build binary: infisical - ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }} + ldflags: + - -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }} + - -X github.com/Infisical/infisical-merge/packages/telemetry.POSTHOG_API_KEY_FOR_CLI={{ .Env.POSTHOG_API_KEY_FOR_CLI }} flags: - -trimpath env: @@ -32,7 +38,9 @@ builds: env: - CGO_ENABLED=0 binary: infisical - ldflags: -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }} + ldflags: + - -X github.com/Infisical/infisical-merge/packages/util.CLI_VERSION={{ .Version }} + - -X github.com/Infisical/infisical-merge/packages/telemetry.POSTHOG_API_KEY_FOR_CLI={{ .Env.POSTHOG_API_KEY_FOR_CLI }} flags: - -trimpath goos: @@ -61,10 +69,10 @@ archives: - goos: windows format: zip files: - - README* - - LICENSE* - - manpages/* - - completions/* + - ../README* + - ../LICENSE* + - ../manpages/* + - ../completions/* release: replace_existing_draft: true @@ -74,14 +82,7 @@ checksum: name_template: "checksums.txt" snapshot: - name_template: "{{ incpatch .Version }}-devel" - -changelog: - sort: asc - filters: - exclude: - - "^docs:" - - "^test:" + name_template: "{{ .Version }}-devel" # publishers: # - name: fury.io @@ -164,7 +165,7 @@ aurs: mkdir -p "${pkgdir}/usr/share/zsh/site-functions/" mkdir -p "${pkgdir}/usr/share/fish/vendor_completions.d/" install -Dm644 "./completions/infisical.bash" "${pkgdir}/usr/share/bash-completion/completions/infisical" - install -Dm644 "./completions/infisical.zsh" "${pkgdir}/usr/share/zsh/site-functions/infisical" + install -Dm644 "./completions/infisical.zsh" "${pkgdir}/usr/share/zsh/site-functions/_infisical" install -Dm644 "./completions/infisical.fish" "${pkgdir}/usr/share/fish/vendor_completions.d/infisical.fish" # man pages install -Dm644 "./manpages/infisical.1.gz" "${pkgdir}/usr/share/man/man1/infisical.1.gz" diff --git a/.husky/pre-commit b/.husky/pre-commit index 0b3d59a18..e235e5d79 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -3,3 +3,5 @@ . "$(dirname -- "$0")/_/husky.sh" npx lint-staged + +infisical scan git-changes --staged -v diff --git a/.infisicalignore b/.infisicalignore new file mode 100644 index 000000000..fa3815a6e --- /dev/null +++ b/.infisicalignore @@ -0,0 +1 @@ +.github/resources/docker-compose.be-test.yml:generic-api-key:16 \ No newline at end of file diff --git a/Dockerfile.standalone-infisical b/Dockerfile.standalone-infisical new file mode 100644 index 000000000..8770bb234 --- /dev/null +++ b/Dockerfile.standalone-infisical @@ -0,0 +1,107 @@ +ARG POSTHOG_HOST=https://app.posthog.com +ARG POSTHOG_API_KEY=posthog-api-key + +FROM node:16-alpine AS frontend-dependencies + +WORKDIR /app + +COPY frontend/package.json frontend/package-lock.json frontend/next.config.js ./ + +# Install dependencies +RUN npm ci --only-production --ignore-scripts + +# Rebuild the source code only when needed +FROM node:16-alpine AS frontend-builder +WORKDIR /app + +# Copy dependencies +COPY --from=frontend-dependencies /app/node_modules ./node_modules +# Copy all files +COPY /frontend . + +ENV NODE_ENV production +ENV NEXT_PUBLIC_ENV production +ARG POSTHOG_HOST +ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST +ARG POSTHOG_API_KEY +ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY +ARG INTERCOM_ID +ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID + +# Build +RUN npm run build + +# Production image +FROM node:16-alpine AS frontend-runner +WORKDIR /app + +RUN addgroup --system --gid 1001 nodejs +RUN adduser --system --uid 1001 nextjs + +RUN mkdir -p /app/.next/cache/images && chown nextjs:nodejs /app/.next/cache/images +VOLUME /app/.next/cache/images + +ARG POSTHOG_API_KEY +ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \ + BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY +ARG INTERCOM_ID +ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \ + BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID + +COPY --chown=nextjs:nodejs --chmod=555 frontend/scripts ./scripts +COPY --from=frontend-builder /app/public ./public +RUN chown nextjs:nodejs ./public/data +COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/standalone ./ +COPY --from=frontend-builder --chown=nextjs:nodejs /app/.next/static ./.next/static + +USER nextjs + +ENV NEXT_TELEMETRY_DISABLED 1 + +## +## BACKEND +## +FROM node:16-alpine AS backend-build + +WORKDIR /app + +COPY backend/package*.json ./ +RUN npm ci --only-production + +COPY /backend . +RUN npm run build + +# Production stage +FROM node:16-alpine AS backend-runner + +WORKDIR /app + +COPY backend/package*.json ./ +RUN npm ci --only-production + +COPY --from=backend-build /app . + +# Production stage +FROM node:16-alpine AS production + +WORKDIR / + +# Install PM2 +RUN npm install -g pm2 +# Copy ecosystem.config.js +COPY ecosystem.config.js . + +RUN apk add --no-cache nginx + +COPY nginx/default-stand-alone-docker.conf /etc/nginx/nginx.conf + +COPY --from=backend-runner /app /backend + +COPY --from=frontend-runner /app/ /app/ + +EXPOSE 80 +ENV HTTPS_ENABLED false + +CMD ["pm2-runtime", "start", "ecosystem.config.js"] + + diff --git a/README.md b/README.md index 449b8cce6..c8e67d219 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ infisical

-

Open-source, end-to-end encrypted tool to manage secrets and configs across your team, devices, and infrastructure.

+

Open-source, end-to-end encrypted platform to manage secrets and configs across your team and infrastructure.

- Slack | + Slack | Infisical Cloud | Self-Hosting | - Docs | + Docs | Website

@@ -25,9 +25,9 @@ git commit activity - Cloudsmith downloads + Cloudsmith downloads - + Slack community channel @@ -37,328 +37,110 @@ Dashboard -**Read this in other languages**: [English language](i18n/README.en.md) -[Spanish language](i18n/README.es.md) -[German language](i18n/README.de.md) -[Korean language](i18n/README.ko.md) -[Turkish language](i18n/README.tr.md) -[Bahasa Indonesia language](i18n/README.id.md) -[Portuguese - Brazil](i18n/README.pt-br.md) -[Japanese language](i18n/README.ja.md) -[Italian language](i18n/README.it.md) +## Introduction -**[Infisical](https://infisical.com)** is an open source, end-to-end encrypted secret manager which you can use to centralize your API keys and configs. From Infisical, you can then distribute these secrets across your whole development lifecycle - from development to production . It's designed to be simple and take minutes to get going. +**[Infisical](https://infisical.com)** is an open source, end-to-end encrypted secret management platform that teams use to centralize their secrets like API keys, database credentials, and configurations. -- **[User-Friendly Dashboard](https://infisical.com/docs/getting-started/dashboard/project)** to manage your team's secrets and configs within projects -- **[Language-Agnostic CLI](https://infisical.com/docs/cli/overview)** that pulls and injects esecrets and configs into your local workflow +We're on a mission to make secret management more accessible to everyone, not just security teams, and that means redesigning the entire developer experience from ground up. + +## Features + +- **[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 +- [**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 -- **Navigate Multiple Environments** per project (e.g. development, staging, production, etc.) -- **Personal overrides** for secrets and configs -- **[Integrations](https://infisical.com/docs/integrations/overview)** with CI/CD and production infrastructure -- **[Infisical API](https://infisical.com/docs/api-reference/overview/introduction)** - manage secrets via HTTPS requests to the platform -- **[Secret Versioning](https://infisical.com/docs/getting-started/dashboard/versioning)** to view the change history for any secret -- **[Audit Logs](https://infisical.com/docs/getting-started/dashboard/audit-logs)** to record every action taken in a project -- **[Point-in-time Secrets Recovery](https://infisical.com/docs/getting-started/dashboard/pit-recovery)** for rolling back to any snapshot of your secrets +- **[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 -- **2FA** (more options coming soon) -- **Smart Security Alerts** -- 🔜 **1-Click Deploy** to AWS -- 🔜 **Automatic Secret Rotation** -- 🔜 **Slack & MS Teams** integrations +- [**Simple on-premise deployments** to AWS and Digital Ocean](https://infisical.com/docs/self-hosting/overview) +- [**Secret Scanning**](https://infisical.com/docs/cli/scanning-overview) -And more. +And much more. -## 🚀 Get started +## Getting started -To quickly get started, visit our [get started guide](https://infisical.com/docs/getting-started/introduction). +Check out the [Quickstart](https://infisical.com/docs/getting-started/introduction) Guides -

- - -

+### Use Infisical Cloud -## 🔥 What's cool about this? +The fastest and most reliable way to get started with Infisical is signing up for free to [Infisical Cloud](https://app.infisical.com/login). -Infisical makes secret management simple and end-to-end encrypted by default. We're on a mission to make it more accessible to all developers, not just security teams. +### Deploy Infisical on premise -According to a [report](https://www.ekransystem.com/en/blog/secrets-management), only 10% of organizations use secret management solutions despite all using digital secrets to some extent. + -If you care about efficiency and security, then Infisical is right for you. +View all [deployment options](https://infisical.com/docs/self-hosting/overview) -We are currently working hard to make Infisical more extensive. Need any integrations or want a new feature? Feel free to [create an issue](https://github.com/Infisical/infisical/issues) or [contribute](https://infisical.com/docs/contributing/overview) directly to the repository. +### Run Infisical locally -## 🔌 Integrations +To set up and run Infisical locally, make sure you have Git and Docker installed on your system. Then run the command for your system: -We're currently setting the foundation and building [integrations](https://infisical.com/docs/integrations/overview) so secrets can be synced everywhere. Any help is welcome! :) +Linux/macOS: - - - - - - - - - -
Platforms Frameworks
+```console +git clone https://github.com/Infisical/infisical && cd "$(basename $_ .git)" && cp .env.example .env && docker-compose -f docker-compose.yml up +``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - ✔️ Docker - - - - ✔️ Docker Compose - - - - ✔️ Heroku - -
- - ✔️ Vercel - - - - ✔️ Kubernetes - - - - ✔️ Fly.io - -
- 🔜 Supabase - - - ✔️ GitHub Actions - - - 🔜 Railway (https://github.com/Infisical/infisical/issues/271) -
- 🔜 GCP SM (https://github.com/Infisical/infisical/issues/285) - - - ✔️ GitLab CI/CD - - - - ✔️ CircleCI - -
- 🔜 Jenkins - - 🔜 Digital Ocean - - - ✔️ Azure Key Vault - -
- - ✔️ Travis CI - - - - ✔️ AWS Secrets Manager - - - 🔜 Forge -
- 🔜 Bitbucket - - - ✔️ AWS Parameter Store - - - - ✔️ Render - -
- 🔜 BuddyCI - - 🔜 Serverless - - - ✔️ Netlify - -
+Windows Command Prompt: -
+```console +git clone https://github.com/Infisical/infisical && cd infisical && copy .env.example .env && docker-compose -f docker-compose.yml up +``` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - ✔️ React - - - - ✔️ Express - -
- - ✔️ Gatsby - - - - ✔️ Flask - -
- - ✔️ Django - - - - ✔️ Laravel - -
- - ✔️ NestJS - - - - ✔️ Remix - -
- - ✔️ Next.js - - - - ✔️ Vite - -
- - ✔️ Vue - - - - ✔️ Ruby on Rails - -
- - ✔️ Fiber - - - - ✔️ Nuxt - -
- - ✔️ .NET - - - And more... -
+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. -## 💚 Community & Support +To scan your full git history, run: -- [Slack](https://join.slack.com/t/infisical-users/shared_invite/zt-1kdbk07ro-RtoyEt_9E~fyzGo_xQYP6g) (For live discussion with the community and the Infisical team) -- [GitHub Discussions](https://github.com/Infisical/infisical/discussions) (For help with building and deeper conversations about features) -- [GitHub Issues](https://github.com/Infisical/infisical-cli/issues) (For any bugs and errors you encounter using Infisical) -- [Twitter](https://twitter.com/infisical) (Get news fast) +``` +infisical scan --verbose +``` -## 🏘 Open-source vs. paid +Install pre commit hook to scan each commit before you push to your repository -This repo is entirely MIT licensed, with the exception of the `ee` directory which will contain premium enterprise features requiring a Infisical license in the future. We're currently focused on developing non-enterprise offerings first that should suit most use cases. +``` +infisical scan install --pre-commit-hook +``` -## 🛡 Security +Lean about Infisical's code scanning feature [here](https://infisical.com/docs/cli/scanning-overview) -Looking to report a security vulnerability? Please don't post about it in GitHub issue. Instead, refer to our [SECURITY.md](./SECURITY.md) file. -## 🚨 Stay Up-to-Date +## Open-source vs. paid -Infisical officially launched as v.1.0 on November 21st, 2022. There are a lot of new features coming very frequently. Watch **releases** of this repository to be notified about future updates: +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 in the future. -![infisical-star-github](https://github.com/Infisical/infisical/blob/main/.github/images/star-infisical.gif?raw=true) +## Security -## 🌱 Contributing +Please do not file GitHub issues or post on our public forum for security vulnerabilities, as they are public! -Whether it's big or small, we love contributions ❤️ Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview). +Infisical takes security issues very seriously. If you have any concerns about Infisical or believe you have uncovered a vulnerability, please get in touch via the e-mail address security@infisical.com. In the message, try to provide a description of the issue and ideally a way of reproducing it. The security team will get back to you as soon as possible. + +Note that this security address should be used only for undisclosed vulnerabilities. Please report any security problems to us before disclosing it publicly. + +## Contributing + +Whether it's big or small, we love contributions. Check out our guide to see how to [get started](https://infisical.com/docs/contributing/overview). Not sure where to get started? You can: - [Book a free, non-pressure pairing sessions with one of our teammates](mailto:tony@infisical.com?subject=Pairing%20session&body=I'd%20like%20to%20do%20a%20pairing%20session!)! -- Join our Slack, and ask us any questions there. +- Join our Slack, and ask us any questions there. -## 🦸 Contributors +## Resources + +- [Docs](https://infisical.com/docs/documentation/getting-started/introduction) for comprehensive documentation and guides +- [Slack](https://join.slack.com/t/infisical-users/shared_invite/zt-1wehzfnzn-1aMo5JcGENJiNAC2SD8Jlg) for discussion with the community and Infisical team. +- [GitHub](https://github.com/Infisical/infisical) for code, issues, and pull requests +- [Twitter](https://twitter.com/infisical) for fast news +- [YouTube](https://www.youtube.com/@infisical5306) for videos on secret management +- [Blog](https://infisical.com/blog) for secret management insights, articles, tutorials, and updates +- [Roadmap](https://www.notion.so/infisical/be2d2585a6694e40889b03aef96ea36b?v=5b19a8127d1a4060b54769567a8785fa) for planned features + +## Acknowledgements [//]: contributor-faces @@ -366,10 +148,5 @@ Not sure where to get started? You can: - + -## 🌎 Translations - -Infisical is currently available in English, Korean, French, and Portuguese (Brazil). Help us translate Infisical to your language! - -You can find all the info in [this issue](https://github.com/Infisical/infisical/issues/181). diff --git a/SECURITY.md b/SECURITY.md index bc383f109..debde5ba8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,9 +1,13 @@ # Security Policy -## Supported Versions +## Supported versions We always recommend using the latest version of Infisical to ensure you get all security updates. -## Reporting a Vulnerability +## Reporting vulnerabilities -Please report security vulnerabilities or concerns to team@infisical.com. +Please do not file GitHub issues or post on our public forum for security vulnerabilities, as they are public! + +Infisical takes security issues very seriously. If you have any concerns about Infisical or believe you have uncovered a vulnerability, please get in touch via the e-mail address security@infisical.com. In the message, try to provide a description of the issue and ideally a way of reproducing it. The security team will get back to you as soon as possible. + +Note that this security address should be used only for undisclosed vulnerabilities. Please report any security problems to us before disclosing it publicly. \ No newline at end of file diff --git a/backend/package-lock.json b/backend/package-lock.json index 80ab4e03b..302ade10b 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -9,40 +9,46 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.281.0", - "@godaddy/terminus": "^4.11.2", + "@aws-sdk/client-secrets-manager": "^3.319.0", + "@godaddy/terminus": "^4.12.0", "@octokit/rest": "^19.0.5", - "@sentry/node": "^7.40.0", - "@sentry/tracing": "^7.39.0", + "@sentry/node": "^7.49.0", + "@sentry/tracing": "^7.48.0", "@types/crypto-js": "^4.1.1", "@types/libsodium-wrappers": "^0.7.10", + "argon2": "^0.30.3", "await-to-js": "^3.0.0", - "aws-sdk": "^2.1324.0", - "axios": "^1.1.3", + "aws-sdk": "^2.1364.0", + "axios": "^1.3.5", "axios-retry": "^3.4.0", "bcrypt": "^5.1.0", - "bigint-conversion": "^2.2.2", + "bigint-conversion": "^2.4.0", "builder-pattern": "^2.2.0", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "crypto-js": "^4.1.1", "dotenv": "^16.0.1", "express": "^4.18.1", + "express-async-errors": "^3.1.1", "express-rate-limit": "^6.7.0", "express-validator": "^6.14.2", "handlebars": "^4.7.7", "helmet": "^5.1.1", - "infisical-node": "^1.0.37", + "infisical-node": "^1.2.1", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", "jsrp": "^0.2.4", "libsodium-wrappers": "^0.7.10", "lodash": "^4.17.21", - "mongoose": "^6.10.2", + "mongoose": "^6.10.5", + "nanoid": "^3.3.6", + "node-cache": "^5.1.2", "nodemailer": "^6.8.0", - "posthog-node": "^2.5.4", + "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", + "posthog-node": "^2.6.0", "query-string": "^7.1.3", - "request-ip": "^3.3.0", + "rate-limit-mongo": "^2.3.2", "rimraf": "^3.0.2", "stripe": "^10.7.0", "swagger-autogen": "^2.22.0", @@ -62,11 +68,12 @@ "@types/cookie-parser": "^1.4.3", "@types/cors": "^2.8.12", "@types/express": "^4.17.14", - "@types/jest": "^29.2.4", + "@types/jest": "^29.5.0", "@types/jsonwebtoken": "^8.5.9", "@types/lodash": "^4.14.191", "@types/node": "^18.11.3", "@types/nodemailer": "^6.4.6", + "@types/passport": "^1.0.12", "@types/supertest": "^2.0.12", "@types/swagger-jsdoc": "^6.0.1", "@types/swagger-ui-express": "^4.1.3", @@ -85,18 +92,33 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/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/@aws-crypto/ie11-detection": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", @@ -174,737 +196,542 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" }, "node_modules/@aws-sdk/abort-controller": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.272.0.tgz", - "integrity": "sha512-s2TV3phapcTwZNr4qLxbfuQuE9ZMP4RoJdkvRRCkKdm6jslsWLJf2Zlcxti/23hOlINUMYv2iXE2pftIgWGdpg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.347.0.tgz", + "integrity": "sha512-P/2qE6ntYEmYG4Ez535nJWZbXqgbkJx8CMz7ChEuEg3Gp3dvVYEKg+iEUEvlqQ2U5dWP5J3ehw5po9t86IsVPQ==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.279.0.tgz", - "integrity": "sha512-MQQdgc3CGDumKutKWlNcDFgNXe2/Tr9TqDGh1EbtXODdxrsT/xQPMghlGCsrTxnPk16zj6OIlS/4h9bTbk6CVg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.347.0.tgz", + "integrity": "sha512-Z92GT2SC1y1r0bl3XI6ZH6QMsL2AaG3IR6ORXeiA94OY9/eF/tQT0zDbwn/MZUwJuBnR0CfO8bq7IQgCAguQ4A==", "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.279.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-secrets-manager": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.281.0.tgz", - "integrity": "sha512-vL+LygNDoCja/47pFwSnI3tCWfy5SGHlz6C1whcszmfl81gXyuHNlAK8RXVRiKhnD11zmCsHJhZyYSfTz5RErQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.347.0.tgz", + "integrity": "sha512-lqBBJobdpVGx5OJpI3P52SaOilPkVW9zKVwPndoou8hpPYMMUVbVZ/Q0rSmjXC7wi9VzMB4SlENDM519Hu/tdQ==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.281.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.281.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1", + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0", "uuid": "^8.3.2" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/client-sso": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.281.0.tgz", - "integrity": "sha512-3RvO5zClQhu37w9VMLoHPGk58S3y8Spb7XX8rW51bm5TUglYQskQ0X2VLEUW/7ZGx/peokHws9Z9+w5yGq5sdA==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.281.0.tgz", - "integrity": "sha512-P6zf9pDuxApVoCYStAg7L8BU9AcWI8PxfLSX4r2WnmcQropxzPJ3op1j9nvbwwBDMFWephijVY4AVp8MqPcPyg==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/client-sts": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.281.0.tgz", - "integrity": "sha512-w8QomyhCVEArRcXgOkjbofiS/PLEKWRAyYBovjMS1cGhns2ZYJXFgHNgr3VGE54TghUc5dR1CqKuBKKM4ThrgA==", - "dependencies": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.281.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-sdk-sts": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "fast-xml-parser": "4.1.2", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.281.0.tgz", - "integrity": "sha512-H99nhMhHImQKgNhHKYc6usTS6UK8KzCcVGpILLVTuP97YlrYAMFAVstA3Xk6mZ28JAbHVXvI6vJjkMNOzCSKCA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.281.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-node": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.281.0.tgz", - "integrity": "sha512-jhddd+lJp8G8hBJ+6glmXjfWJT3nxiE1aliH3fBC4RR3D+1kRXc99Xg6mbUb8bm+GrVZ4gzfiqSgg+ByKjd7xA==", - "dependencies": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.281.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.281.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.281.0.tgz", - "integrity": "sha512-IqJnpXuLpJYoSCf/Rt66/CPVTjfkam3z9+ZvlQJV+VbK+vGj276qEtTmSN3XPZZgF1XbWptvkzIWDszLhHiZmg==", - "dependencies": { - "@aws-sdk/client-sso": "3.281.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/token-providers": "3.281.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@aws-sdk/client-secrets-manager/node_modules/@aws-sdk/token-providers": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.281.0.tgz", - "integrity": "sha512-36Vg/F6Edm7qdjcTeNVON+sK2edgHhmhTtAEjWcuUk5AX/Et+Ate/A2N8HD3nxwlAcgidfnBC9SHYJatbhcEnQ==", - "dependencies": { - "@aws-sdk/client-sso-oidc": "3.281.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - }, - "engines": { - "node": ">=14.0.0" - } - }, "node_modules/@aws-sdk/client-sso": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.279.0.tgz", - "integrity": "sha512-599Y5wOrkpjD6p0BTs0X4+Ge9O7jlAPJ2ttI9lfhT2/UEZyqoJHajJs1pMJV75oeZklPOBi8G9jnZcMVJgRpvQ==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.347.0.tgz", + "integrity": "sha512-AZehWCNLUXTrDavsZYRi7d84Uef20ppYJ2FY0KxqrKB3lx89mO29SfSJSC4woeW5+6ooBokq8HtKxw5ImPfRhA==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.279.0.tgz", - "integrity": "sha512-tC9xKGo3z/HQbJDMvaUrnBSSRX7sOX2YUA2OpJ3T1TTfylLTO70OKjg1G4OMFNiPpJsHonwD7Iud+rnMnUKI0g==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.347.0.tgz", + "integrity": "sha512-IBxRfPqb8f9FqpmDbzcRDfoiasj/Y47C4Gj+j3kA5T1XWyGwbDI9QnPW/rnkZTWxLUUG1LSbBNwbPD6TLoff8A==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.279.0.tgz", - "integrity": "sha512-y/cI5Gg5WWqmSSDQftCT26wOLu0HSuPY1u6Q4Q97FBIfRC3hYztjYdUDHuTu6qPPT+tdsnWOUy2tr3qamVSQ4g==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.347.0.tgz", + "integrity": "sha512-QcJCUlzJZLAFTFSuELKd4BF5I5W38TR/m7NX2y1tn2la9JIrWSrz+tj598zfp2V4pJPzRJ1i8RglTZxSRIvsxQ==", "dependencies": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-sdk-sts": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-sdk-sts": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", "fast-xml-parser": "4.1.2", - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/config-resolver": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.272.0.tgz", - "integrity": "sha512-Dr4CffRVNsOp3LRNdpvcH6XuSgXOSLblWliCy/5I86cNl567KVMxujVx6uPrdTXYs2h1rt3MNl6jQGnAiJeTbw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.347.0.tgz", + "integrity": "sha512-2ja+Sf/VnUO7IQ3nKbDQ5aumYKKJUaTm/BuVJ29wNho8wYHfuf7wHZV0pDTkB8RF5SH7IpHap7zpZAj39Iq+EA==", "dependencies": { - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-config-provider": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.279.0.tgz", - "integrity": "sha512-RhpKmIM1RfrmbtTXiDK3qyx9aJcZlvHpP18Axbjokld7R6YEdMpv8piB8v19kd6zl0e9xPNrX9At6UOFsXpeJw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.347.0.tgz", + "integrity": "sha512-7NiVVQC51HvomI44OyD+UekZ7qxauJeFGwQILbQ0beAxNuPZL7Ect/jB6A5MeleyqP+sVn8cB7qBMZjFJRhoJA==", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.272.0.tgz", - "integrity": "sha512-QI65NbLnKLYHyTYhXaaUrq6eVsCCrMUb05WDA7+TJkWkjXesovpjc8vUKgFiLSxmgKmb2uOhHNcDyObKMrYQFw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.347.0.tgz", + "integrity": "sha512-UnEM+LKGpXKzw/1WvYEQsC6Wj9PupYZdQOE+e2Dgy2dqk/pVFy4WueRtFXYDT2B41ppv3drdXUuKZRIDVqIgNQ==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-imds": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.272.0.tgz", - "integrity": "sha512-wwAfVY1jTFQEfxVfdYD5r5ieYGl+0g4nhekVxNMqE8E1JeRDd18OqiwAflzpgBIqxfqvCUkf+vl5JYyacMkNAQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.347.0.tgz", + "integrity": "sha512-7scCy/DCDRLIhlqTxff97LQWDnRwRXji3bxxMg+xWOTTaJe7PWx+etGSbBWaL42vsBHFShQjSLvJryEgoBktpw==", "dependencies": { - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.279.0.tgz", - "integrity": "sha512-FCpr3/khMTb2pWLMC138wU7HzcpkrjejrBNfCJSUu7Emxm039UMLjT2JObnRKxidKlz58oYBRayVIbBYRWREcg==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.347.0.tgz", + "integrity": "sha512-84TNF34ryabmVbILOq7f+/Jy8tJaskvHdax3X90qxFtXRU11kX0bf5NYL616KT0epR0VGpy50ThfIqvBwxeJfQ==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.279.0.tgz", - "integrity": "sha512-7D8ETopCt3H+x2BEPMEhzc4dcNtSK7umnRdgfiTGRjcQSVPh5Whq/tDIAtNj2D+PmLgu3e+Hk7jrXkaMCDlxMw==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.347.0.tgz", + "integrity": "sha512-ds2uxE0krl94RdQ7bstwafUXdlMeEOPgedhaheVVlj8kH+XqlZdwUUaUv1uoEI9iBzuSjKftUkIHo0xsTiwtaw==", "dependencies": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.279.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.272.0.tgz", - "integrity": "sha512-hiCAjWWm2PeBFp5cjkxqyam/XADjiS+e7GzwC34TbZn3LisS0uoweLojj9tD11NnnUhyhbLteUvu5+rotOLwrg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.347.0.tgz", + "integrity": "sha512-yl1z4MsaBdXd4GQ2halIvYds23S67kElyOwz7g8kaQ4kHj+UoYWxz3JVW/DGusM6XmQ9/F67utBrUVA0uhQYyw==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.279.0.tgz", - "integrity": "sha512-u8ZHz9Sv7sAv2vllyzcdgcO1pC5pa2UuoYKfz9J8hqLHc8VJYtYQ6WJvi4GoA55VDPk87pyVYz9t6ATntsukaw==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.347.0.tgz", + "integrity": "sha512-M1d7EnUaJbSNCmNalEbINmtFkc9wJufx7UhKtEeFwSq9KEzOMroH1MEOeiqIw9f/zE8NI/iPkVeEhw123vmBrQ==", "dependencies": { - "@aws-sdk/client-sso": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/token-providers": "3.279.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/token-providers": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.272.0.tgz", - "integrity": "sha512-ImrHMkcgneGa/HadHAQXPwOrX26sAKuB8qlMxZF/ZCM2B55u8deY+ZVkVuraeKb7YsahMGehPFOfRAF6mvFI5Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.347.0.tgz", + "integrity": "sha512-DxoTlVK8lXjS1zVphtz/Ab+jkN/IZor9d6pP2GjJHNoAIIzXfRwwj5C8vr4eTayx/5VJ7GRP91J8GJ2cKly8Qw==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.279.0.tgz", - "integrity": "sha512-iZI7hrP7oEP2zzStuiEWklVQY3HqIX02PxQiGMgW9/6Bb+2xBpZykIkBBmqaOKlNF/us1TJS6WDOylL1Z1EcIw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.347.0.tgz", + "integrity": "sha512-ny8tnuLToQIYbS+ztRh4/fViDDV1xk+WuapSK2T1MAIuPvhyD1IDulTyqv6P9ROoNIqt1NAoLctkWxdkLvqyQA==", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.279.0", - "@aws-sdk/client-sso": "3.279.0", - "@aws-sdk/client-sts": "3.279.0", - "@aws-sdk/credential-provider-cognito-identity": "3.279.0", - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.279.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.347.0", + "@aws-sdk/client-sso": "3.347.0", + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/credential-provider-cognito-identity": "3.347.0", + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/@aws-sdk/fetch-http-handler": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.272.0.tgz", - "integrity": "sha512-1Qhm9e0RbS1Xf4CZqUbQyUMkDLd7GrsRXWIvm9b86/vgeV8/WnjO3CMue9D51nYgcyQORhYXv6uVjAYCWbUExA==", + "node_modules/@aws-sdk/eventstream-codec": { + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.347.0.tgz", + "integrity": "sha512-61q+SyspjsaQ4sdgjizMyRgVph2CiW4aAtfpoH69EJFJfTxTR/OqnZ9Jx/3YiYi0ksrvDenJddYodfWWJqD8/w==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/querystring-builder": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "tslib": "^2.3.1" + "@aws-crypto/crc32": "3.0.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/fetch-http-handler": { + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.347.0.tgz", + "integrity": "sha512-sQ5P7ivY8//7wdxfA76LT1sF6V2Tyyz1qF6xXf9sihPN5Q1Y65c+SKpMzXyFSPqWZ82+SQQuDliYZouVyS6kQQ==", + "dependencies": { + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/hash-node": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.272.0.tgz", - "integrity": "sha512-40dwND+iAm3VtPHPZu7/+CIdVJFk2s0cWZt1lOiMPMSXycSYJ45wMk7Lly3uoqRx0uWfFK5iT2OCv+fJi5jTng==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.347.0.tgz", + "integrity": "sha512-96+ml/4EaUaVpzBdOLGOxdoXOjkPgkoJp/0i1fxOJEvl8wdAQSwc3IugVK9wZkCxy2DlENtgOe6DfIOhfffm/g==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-buffer-from": "3.208.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-buffer-from": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/invalid-dependency": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.272.0.tgz", - "integrity": "sha512-ysW6wbjl1Y78txHUQ/Tldj2Rg1BI7rpMO9B9xAF6yAX3mQ7t6SUPQG/ewOGvH2208NBIl3qP5e/hDf0Q6r/1iw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.347.0.tgz", + "integrity": "sha512-8imQcwLwqZ/wTJXZqzXT9pGLIksTRckhGLZaXT60tiBOPKuerTsus2L59UstLs5LP8TKaVZKFFSsjRIn9dQdmQ==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/is-array-buffer": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", - "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz", + "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-content-length": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.272.0.tgz", - "integrity": "sha512-sAbDZSTNmLX+UTGwlUHJBWy0QGQkiClpHwVFXACon+aG0ySLNeRKEVYs6NCPYldw4cj6hveLUn50cX44ukHErw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.347.0.tgz", + "integrity": "sha512-i4qtWTDImMaDUtwKQPbaZpXsReiwiBomM1cWymCU4bhz81HL01oIxOxOBuiM+3NlDoCSPr3KI6txZSz/8cqXCQ==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-endpoint": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.272.0.tgz", - "integrity": "sha512-Dk3JVjj7SxxoUKv3xGiOeBksvPtFhTDrVW75XJ98Ymv8gJH5L1sq4hIeJAHRKogGiRFq2J73mnZSlM9FVXEylg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.347.0.tgz", + "integrity": "sha512-unF0c6dMaUL1ffU+37Ugty43DgMnzPWXr/Jup/8GbK5fzzWT5NQq6dj9KHPubMbWeEjQbmczvhv25JuJdK8gNQ==", "dependencies": { - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.278.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.278.0.tgz", - "integrity": "sha512-oTkF3exy89KE8NgSeXFwD+0H0GRKL2qUw92t3caEj7+4KzU/0m3t7NtKlq2NLRtTJhZ/izYRpV536oogLzGm3g==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.347.0.tgz", + "integrity": "sha512-kpKmR9OvMlnReqp5sKcJkozbj1wmlblbVSbnQAIkzeQj2xD5dnVR3Nn2ogQKxSmU1Fv7dEroBtrruJ1o3fY38A==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.272.0.tgz", - "integrity": "sha512-u2SQ0hWrFwxbxxYMG5uMEgf01pQY5jauK/LYWgGIvuCmFgiyRQQP3oN7kkmsxnS9MWmNmhbyQguX2NY02s5e9w==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.347.0.tgz", + "integrity": "sha512-NYC+Id5UCkVn+3P1t/YtmHt75uED06vwaKyxDy0UmB2K66PZLVtwWbLpVWrhbroaw1bvUHYcRyQ9NIfnVcXQjA==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.272.0.tgz", - "integrity": "sha512-Gp/eKWeUWVNiiBdmUM2qLkBv+VLSJKoWAO+aKmyxxwjjmWhE0FrfA1NQ1a3g+NGMhRbAfQdaYswRAKsul70ISg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.347.0.tgz", + "integrity": "sha512-qfnSvkFKCAMjMHR31NdsT0gv5Sq/ZHTUD4yQsSLpbVQ6iYAS834lrzXt41iyEHt57Y514uG7F/Xfvude3u4icQ==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-retry": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.272.0.tgz", - "integrity": "sha512-pCGvHM7C76VbO/dFerH+Vwf7tGv7j+e+eGrvhQ35mRghCtfIou/WMfTZlD1TNee93crrAQQVZKjtW3dMB3WCzg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.347.0.tgz", + "integrity": "sha512-CpdM+8dCSbX96agy4FCzOfzDmhNnGBM/pxrgIVLm5nkYTLuXp/d7ubpFEUHULr+4hCd5wakHotMt7yO29NFaVw==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/service-error-classification": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-middleware": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "tslib": "^2.3.1", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/service-error-classification": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "tslib": "^2.5.0", "uuid": "^8.3.2" }, "engines": { @@ -912,408 +739,406 @@ } }, "node_modules/@aws-sdk/middleware-sdk-sts": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.272.0.tgz", - "integrity": "sha512-VvYPg7LrDIjUOWueSzo2wBzcNG7dw+cmzV6zAKaLxf0RC5jeAP4hE0OzDiiZfDrjNghEzgq/V+0NO+LewqYL9Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.347.0.tgz", + "integrity": "sha512-38LJ0bkIoVF3W97x6Jyyou72YV9Cfbml4OaDEdnrCOo0EssNZM5d7RhjMvQDwww7/3OBY/BzeOcZKfJlkYUXGw==", "dependencies": { - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-serde": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.272.0.tgz", - "integrity": "sha512-kW1uOxgPSwtXPB5rm3QLdWomu42lkYpQL94tM1BjyFOWmBLO2lQhk5a7Dw6HkTozT9a+vxtscLChRa6KZe61Hw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.347.0.tgz", + "integrity": "sha512-x5Foi7jRbVJXDu9bHfyCbhYDH5pKK+31MmsSJ3k8rY8keXLBxm2XEEg/AIoV9/TUF9EeVvZ7F1/RmMpJnWQsEg==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-signing": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.272.0.tgz", - "integrity": "sha512-4LChFK4VAR91X+dupqM8fQqYhFGE0G4Bf9rQlVTgGSbi2KUOmpqXzH0/WKE228nKuEhmH8+Qd2VPSAE2JcyAUA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.347.0.tgz", + "integrity": "sha512-zVBF/4MGKnvhAE/J+oAL/VAehiyv+trs2dqSQXwHou9j8eA8Vm8HS2NdOwpkZQchIxTuwFlqSusDuPEdYFbvGw==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/signature-v4": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-stack": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.272.0.tgz", - "integrity": "sha512-jhwhknnPBGhfXAGV5GXUWfEhDFoP/DN8MPCO2yC5OAxyp6oVJ8lTPLkZYMTW5VL0c0eG44dXpF4Ib01V+PlDrQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.347.0.tgz", + "integrity": "sha512-Izidg4rqtYMcKuvn2UzgEpPLSmyd8ub9+LQ2oIzG3mpIzCBITq7wp40jN1iNkMg+X6KEnX9vdMJIYZsPYMCYuQ==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.272.0.tgz", - "integrity": "sha512-Qy7/0fsDJxY5l0bEk7WKDfqb4Os/sCAgFR2zEvrhDtbkhYPf72ysvg/nRUTncmCbo8tOok4SJii2myk8KMfjjw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.347.0.tgz", + "integrity": "sha512-wJbGN3OE1/daVCrwk49whhIr9E0j1N4gWwN/wi4WuyYIA+5lMUfVp0aGIOvZR+878DxuFz2hQ4XcZVT4K2WvQw==", "dependencies": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/node-config-provider": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.272.0.tgz", - "integrity": "sha512-YYCIBh9g1EQo7hm2l22HX5Yr9RoPQ2RCvhzKvF1n1e8t1QH4iObQrYUtqHG4khcm64Cft8C5MwZmgzHbya5Z6Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.347.0.tgz", + "integrity": "sha512-faU93d3+5uTTUcotGgMXF+sJVFjrKh+ufW+CzYKT4yUHammyaIab/IbTPWy2hIolcEGtuPeVoxXw8TXbkh/tuw==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/node-http-handler": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.272.0.tgz", - "integrity": "sha512-VrW9PjhhngeyYp4yGYPe5S0vgZH6NwU3Po9xAgayUeE37Inr7LS1YteFMHdpgsUUeNXnh7d06CXqHo1XjtqOKA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.347.0.tgz", + "integrity": "sha512-eluPf3CeeEaPbETsPw7ee0Rb0FP79amu8vdLMrQmkrD+KP4owupUXOEI4drxWJgBSd+3PRowPWCDA8wUtraHKg==", "dependencies": { - "@aws-sdk/abort-controller": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/querystring-builder": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/abort-controller": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/property-provider": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.272.0.tgz", - "integrity": "sha512-V1pZTaH5eqpAt8O8CzbItHhOtzIfFuWymvwZFkAtwKuaHpnl7jjrTouV482zoq8AD/fF+VVSshwBKYA7bhidIw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.347.0.tgz", + "integrity": "sha512-t3nJ8CYPLKAF2v9nIHOHOlF0CviQbTvbFc2L4a+A+EVd/rM4PzL3+3n8ZJsr0h7f6uD04+b5YRFgKgnaqLXlEg==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/protocol-http": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.272.0.tgz", - "integrity": "sha512-4JQ54v5Yn08jspNDeHo45CaSn1CvTJqS1Ywgr79eU6jBExtguOWv6LNtwVSBD9X37v88iqaxt8iu1Z3pZZAJeg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.347.0.tgz", + "integrity": "sha512-2YdBhc02Wvy03YjhGwUxF0UQgrPWEy8Iq75pfS42N+/0B/+eWX1aQgfjFxIpLg7YSjT5eKtYOQGlYd4MFTgj9g==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/querystring-builder": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.272.0.tgz", - "integrity": "sha512-ndo++7GkdCj5tBXE6rGcITpSpZS4PfyV38wntGYAlj9liL1omk3bLZRY6uzqqkJpVHqbg2fD7O2qHNItzZgqhw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.347.0.tgz", + "integrity": "sha512-phtKTe6FXoV02MoPkIVV6owXI8Mwr5IBN3bPoxhcPvJG2AjEmnetSIrhb8kwc4oNhlwfZwH6Jo5ARW/VEWbZtg==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/querystring-parser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.272.0.tgz", - "integrity": "sha512-5oS4/9n6N1LZW9tI3qq/0GnCuWoOXRgcHVB+AJLRBvDbEe+GI+C/xK1tKLsfpDNgsQJHc4IPQoIt4megyZ/1+A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.347.0.tgz", + "integrity": "sha512-5VXOhfZz78T2W7SuXf2avfjKglx1VZgZgp9Zfhrt/Rq+MTu2D+PZc5zmJHhYigD7x83jLSLogpuInQpFMA9LgA==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/service-error-classification": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.272.0.tgz", - "integrity": "sha512-REoltM1LK9byyIufLqx9znhSolPcHQgVHIA2S0zu5sdt5qER4OubkLAXuo4MBbisUTmh8VOOvIyUb5ijZCXq1w==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.347.0.tgz", + "integrity": "sha512-xZ3MqSY81Oy2gh5g0fCtooAbahqh9VhsF8vcKjVX8+XPbGC8y+kej82+MsMg4gYL8gRFB9u4hgYbNgIS6JTAvg==", "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/shared-ini-file-loader": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.272.0.tgz", - "integrity": "sha512-lzFPohp5sy2XvwFjZIzLVCRpC0i5cwBiaXmFzXYQZJm6FSCszHO4ax+m9yrtlyVFF/2YPWl+/bzNthy4aJtseA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.347.0.tgz", + "integrity": "sha512-Xw+zAZQVLb+xMNHChXQ29tzzLqm3AEHsD8JJnlkeFjeMnWQtXdUfOARl5s8NzAppcKQNlVe2gPzjaKjoy2jz1Q==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/signature-v4": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.272.0.tgz", - "integrity": "sha512-pWxnHG1NqJWMwlhJ6NHNiUikOL00DHROmxah6krJPMPq4I3am2KY2Rs/8ouWhnEXKaHAv4EQhSALJ+7Mq5S4/A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.347.0.tgz", + "integrity": "sha512-58Uq1do+VsTHYkP11dTK+DF53fguoNNJL9rHRWhzP+OcYv3/mBMLoS2WPz/x9FO5mBg4ESFsug0I6mXbd36tjw==", "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-hex-encoding": "3.201.0", - "@aws-sdk/util-middleware": "3.272.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/eventstream-codec": "3.347.0", + "@aws-sdk/is-array-buffer": "3.310.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/smithy-client": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.279.0.tgz", - "integrity": "sha512-ZcYWUQDGAYN6NXRpJuSn46PetrpPCA6TrDVwP9+3pERzTXZ66npXoG2XhHjNrOXy/Ted5A3OxKrM4/zLu9tK3A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.347.0.tgz", + "integrity": "sha512-PaGTDsJLGK0sTjA6YdYQzILRlPRN3uVFyqeBUkfltXssvUzkm8z2t1lz2H4VyJLAhwnG5ZuZTNEV/2mcWrU7JQ==", "dependencies": { - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.279.0.tgz", - "integrity": "sha512-bsUlZSizTXZ8Pehdatcioi8VphxYn7fRjo5L083peOvBjoL+9WSGyP74PLrFLNwA35QxddwOqgnpQZoE1heuPQ==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.347.0.tgz", + "integrity": "sha512-DZS9UWEy105zsaBJTgcvv1U+0jl7j1OzfMpnLf/lEYjEvx/4FqY2Ue/OZUACJorZgm/dWNqrhY17tZXtS/S3ew==", "dependencies": { - "@aws-sdk/client-sso-oidc": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso-oidc": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.272.0.tgz", - "integrity": "sha512-MmmL6vxMGP5Bsi+4wRx4mxYlU/LX6M0noOXrDh/x5FfG7/4ZOar/nDxqDadhJtNM88cuWVHZWY59P54JzkGWmA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.347.0.tgz", + "integrity": "sha512-GkCMy79mdjU9OTIe5KT58fI/6uqdf8UmMdWqVHmFJ+UpEzOci7L/uw4sOXWo7xpPzLs6cJ7s5ouGZW4GRPmHFA==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/url-parser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.272.0.tgz", - "integrity": "sha512-vX/Tx02PlnQ/Kgtf5TnrNDHPNbY+amLZjW0Z1d9vzAvSZhQ4i9Y18yxoRDIaDTCNVRDjdhV8iuctW+05PB5JtQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.347.0.tgz", + "integrity": "sha512-lhrnVjxdV7hl+yCnJfDZOaVLSqKjxN20MIOiijRiqaWGLGEAiSqBreMhL89X1WKCifxAs4zZf9YB9SbdziRpAA==", "dependencies": { - "@aws-sdk/querystring-parser": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/querystring-parser": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-base64": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", - "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz", + "integrity": "sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg==", "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-body-length-browser": { - "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", - "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz", + "integrity": "sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-body-length-node": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", - "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz", + "integrity": "sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-buffer-from": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", - "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz", + "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==", "dependencies": { - "@aws-sdk/is-array-buffer": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/is-array-buffer": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-config-provider": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", - "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz", + "integrity": "sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-defaults-mode-browser": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.279.0.tgz", - "integrity": "sha512-RnchYRrpapTT5Hu23LOfk6e8RMVq0kUzho6xA6TJj1a4uGxkcRMvgzPipCq1P5uHu0mrkQBg9pGPEVNOUs38/Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.347.0.tgz", + "integrity": "sha512-+JHFA4reWnW/nMWwrLKqL2Lm/biw/Dzi/Ix54DAkRZ08C462jMKVnUlzAI+TfxQE3YLm99EIa0G7jiEA+p81Qw==", "dependencies": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@aws-sdk/util-defaults-mode-node": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.279.0.tgz", - "integrity": "sha512-A2NB10xReWC+GSnOivKGZ9rnljIZdEP8WMCQQEnA6DJNI19AUFF/O9QJ9y+cHGLKEms7jH86Y99wShdpzAK+Jw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.347.0.tgz", + "integrity": "sha512-A8BzIVhAAZE5WEukoAN2kYebzTc99ZgncbwOmgCCbvdaYlk5tzguR/s+uoT4G0JgQGol/4hAMuJEl7elNgU6RQ==", "dependencies": { - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">= 10.0.0" } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.272.0.tgz", - "integrity": "sha512-c4MPUaJt2G6gGpoiwIOqDfUa98c1J63RpYvf/spQEKOtC/tF5Gfqlxuq8FnAl5lHnrqj1B9ZXLLxFhHtDR0IiQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.347.0.tgz", + "integrity": "sha512-/WUkirizeNAqwVj0zkcrqdQ9pUm1HY5kU+qy7xTR0OebkuJauglkmSTMD+56L1JPunWqHhlwCMVRaz5eaJdSEQ==", "dependencies": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-hex-encoding": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", - "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz", + "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", - "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-middleware": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.272.0.tgz", - "integrity": "sha512-Abw8m30arbwxqmeMMha5J11ESpHUNmCeSqSzE8/C4B8jZQtHY4kq7f+upzcNIQ11lsd+uzBEzNG3+dDRi0XOJQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.347.0.tgz", + "integrity": "sha512-8owqUA3ePufeYTUvlzdJ7Z0miLorTwx+rNol5lourGQZ9JXsVMo23+yGA7nOlFuXSGkoKpMOtn6S0BT2bcfeiw==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-retry": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.272.0.tgz", - "integrity": "sha512-Ngha5414LR4gRHURVKC9ZYXsEJhMkm+SJ+44wlzOhavglfdcKKPUsibz5cKY1jpUV7oKECwaxHWpBB8r6h+hOg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.347.0.tgz", + "integrity": "sha512-NxnQA0/FHFxriQAeEgBonA43Q9/VPFQa8cfJDuT2A1YZruMasgjcltoZszi1dvoIRWSZsFTW42eY2gdOd0nffQ==", "dependencies": { - "@aws-sdk/service-error-classification": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/service-error-classification": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">= 14.0.0" } }, "node_modules/@aws-sdk/util-uri-escape": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", - "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz", + "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==", "dependencies": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.272.0.tgz", - "integrity": "sha512-Lp5QX5bH6uuwBlIdr7w7OAcAI50ttyskb++yUr9i+SPvj6RI2dsfIBaK4mDg1qUdM5LeUdvIyqwj3XHjFKAAvA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.347.0.tgz", + "integrity": "sha512-ydxtsKVtQefgbk1Dku1q7pMkjDYThauG9/8mQkZUAVik55OUZw71Zzr3XO8J8RKvQG8lmhPXuAQ0FKAyycc0RA==", "dependencies": { - "@aws-sdk/types": "3.272.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.272.0.tgz", - "integrity": "sha512-ljK+R3l+Q1LIHrcR+Knhk0rmcSkfFadZ8V+crEGpABf/QUQRg7NkZMsoe814tfBO5F7tMxo8wwwSdaVNNHtoRA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.347.0.tgz", + "integrity": "sha512-6X0b9qGsbD1s80PmbaB6v1/ZtLfSx6fjRX8caM7NN0y/ObuLoX8LhYnW6WlB2f1+xb4EjaCNgpP/zCf98MXosw==", "dependencies": { - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" @@ -1328,12 +1153,12 @@ } }, "node_modules/@aws-sdk/util-utf8": { - "version": "3.254.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.254.0.tgz", - "integrity": "sha512-14Kso/eIt5/qfIBmhEL9L1IfyUqswjSTqO2mY7KOzUZ9SZbwn3rpxmtkhmATkRjD7XIlLKaxBkI7tU9Zjzj8Kw==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz", + "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==", "dependencies": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" }, "engines": { "node": ">=14.0.0" @@ -1348,9 +1173,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "dependencies": { "@babel/highlight": "^7.18.6" @@ -1360,30 +1185,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", + "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", + "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.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", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -1414,12 +1239,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", + "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", "dev": true, "dependencies": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" @@ -1428,28 +1253,14 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "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==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.22.0", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -1471,9 +1282,9 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "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==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1505,52 +1316,52 @@ } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "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==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "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==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-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.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "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==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "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==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1569,9 +1380,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "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==", "dev": true, "engines": { "node": ">=6.9.0" @@ -1596,14 +1407,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", + "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", "dev": true, "dependencies": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.3" }, "engines": { "node": ">=6.9.0" @@ -1695,9 +1506,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.3.tgz", + "integrity": "sha512-vrukxyW/ep8UD1UDzOYpTKQ6abgjFoeG6L+4ar9+c5TN9QnlqiOi6QK7LSR5ewm/ERyGkT/Ai6VboNrxhbr9Uw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -1767,12 +1578,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", + "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1869,12 +1680,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "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==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1884,9 +1695,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", + "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -1895,33 +1706,33 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", + "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.1.tgz", + "integrity": "sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", - "@babel/helper-environment-visitor": "^7.18.9", + "@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.21.2", - "@babel/types": "^7.21.2", + "@babel/parser": "^7.22.0", + "@babel/types": "^7.22.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -1939,12 +1750,12 @@ } }, "node_modules/@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.3.tgz", + "integrity": "sha512-P3na3xIQHTKY4L0YOG7pM8M8uoUIB910WQaSiiMCZUC2Cy8XFEQONGABFnHWBa2gpGKODTAJcNhi5Zk0sLRrzg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, @@ -1998,15 +1809,39 @@ "kuler": "^2.0.0" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -2022,18 +1857,18 @@ } }, "node_modules/@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/@godaddy/terminus": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.11.2.tgz", - "integrity": "sha512-e/kbOWpGKME42eltM/wXM3RxSUOrfureZxEd6Dt6NXyFoJ7E8lnmm7znXydJsL3B7ky4HRFZI+eHrep54NZbeQ==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.0.tgz", + "integrity": "sha512-zbl6gKxPAnAoAAGCyRN1kOMHTXgiW3C09w8McLKZWSSHQlsiRZlMZzBwSv1aK9PaRU25w80cnOlt3ow+uQwR1Q==", "dependencies": { "stoppable": "^1.1.0" } @@ -2189,16 +2024,16 @@ } }, "node_modules/@jest/console": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", - "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" }, "engines": { @@ -2206,37 +2041,37 @@ } }, "node_modules/@jest/core": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", - "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/reporters": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@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", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.3", - "jest-config": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-resolve-dependencies": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", - "jest-watcher": "^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", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" }, @@ -2253,37 +2088,37 @@ } }, "node_modules/@jest/environment": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", - "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "dependencies": { - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3" + "jest-mock": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", "dev": true, "dependencies": { - "expect": "^29.4.3", - "jest-snapshot": "^29.4.3" + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/expect-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", - "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3" @@ -2293,48 +2128,48 @@ } }, "node_modules/@jest/fake-timers": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", - "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/globals": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", - "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/types": "^29.4.3", - "jest-mock": "^29.4.3" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/reporters": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", - "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.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", "@types/node": "*", "chalk": "^4.0.0", @@ -2347,9 +2182,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -2394,13 +2229,13 @@ } }, "node_modules/@jest/test-result": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", - "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" }, @@ -2409,14 +2244,14 @@ } }, "node_modules/@jest/test-sequencer": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", - "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.3", + "@jest/test-result": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "slash": "^3.0.0" }, "engines": { @@ -2424,22 +2259,22 @@ } }, "node_modules/@jest/transform": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", - "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "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.4.3", + "jest-haste-map": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -2450,9 +2285,9 @@ } }, "node_modules/@jest/types": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", - "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", @@ -2467,13 +2302,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -2498,25 +2334,31 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + }, "node_modules/@juanelas/base64": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.0.5.tgz", - "integrity": "sha512-gTIElNo4ohMcYUZzol/Hb6DYJzphxl0b1B4egJJ+JiqxqcOcWx4XLMAB+lhWuMsMX3uR1oc5hwPusU3lgc1FkQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" }, "node_modules/@mapbox/node-pre-gyp": { "version": "1.0.10", @@ -2790,9 +2632,9 @@ } }, "node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -2820,9 +2662,9 @@ } }, "node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dependencies": { "@octokit/request": "^6.0.0", "@octokit/types": "^9.0.0", @@ -2833,16 +2675,17 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dependencies": { - "@octokit/types": "^9.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" }, "engines": { "node": ">= 14" @@ -2860,11 +2703,11 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "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==", "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" }, "engines": { @@ -2875,9 +2718,9 @@ } }, "node_modules/@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -2904,25 +2747,38 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" }, "engines": { "node": ">= 14" } }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" + }, "node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^17.2.0" + } + }, + "node_modules/@phc/format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", + "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==", + "engines": { + "node": ">=10" } }, "node_modules/@posthog/plugin-scaffold": { @@ -2988,14 +2844,52 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "node_modules/@sentry/node": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.40.0.tgz", - "integrity": "sha512-S2pcLBUsCg3+WYlyQbXKPey3H1yaZPt9fpJTPAoabbidYXweBAbtFjSCRwPFwCQMzWusWxlYEwWRT77C07pHVg==", + "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==", "dependencies": { - "@sentry/core": "7.40.0", - "@sentry/types": "7.40.0", - "@sentry/utils": "7.40.0", + "@sentry/core": "7.53.1", + "@sentry/types": "7.53.1", + "@sentry/utils": "7.53.1", + "tslib": "^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==", + "dependencies": { + "@sentry/types": "7.53.1", + "@sentry/utils": "7.53.1", + "tslib": "^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/node": { + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.53.1.tgz", + "integrity": "sha512-B4ax8sRd54xj4ad+4eY2EOKNt0Mh1NjuLW1zUKS8HW3h0bmuaDFzGuhEVvEY5H4SaV6tZKj1c0dvnMnyUbYkhA==", + "dependencies": { + "@sentry-internal/tracing": "7.53.1", + "@sentry/core": "7.53.1", + "@sentry/types": "7.53.1", + "@sentry/utils": "7.53.1", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", @@ -3005,92 +2899,43 @@ "node": ">=8" } }, - "node_modules/@sentry/node/node_modules/@sentry/core": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.40.0.tgz", - "integrity": "sha512-OPAobQG0GTY++r5LWUcOA1lS+2TY2Lmw/i5s4kL9WbY+f08dbLNEGNBObY7/V98OL4f7OG+nWaPFybgM7kqUTQ==", - "dependencies": { - "@sentry/types": "7.40.0", - "@sentry/utils": "7.40.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/types": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.40.0.tgz", - "integrity": "sha512-dIbqBenbmDx1F8pvfC11C88J83ecwumUhV+YOIxcmVd1fmlPF2hXWZ01+NTkTDkCu341sJx4wPQogByFy8FwGA==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/node/node_modules/@sentry/utils": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.40.0.tgz", - "integrity": "sha512-ZdCbTpAXPiVVfvNJVftnDhsctOui71MDUhVIdLkgg4Cuic+WHGPRmmZ+H6uZdp7vRaeB+Uvnn5+t2iSAVo/mAA==", - "dependencies": { - "@sentry/types": "7.40.0", - "tslib": "^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.39.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.39.0.tgz", - "integrity": "sha512-bSRdUMzp/n54J+Qf4hHC4WVvdv4vZEv3NEbNNsnIZNAhnVAq6QB9VzsGRJZ12PqxJU3StDuqLiZFVOmGxETCkQ==", + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.53.1.tgz", + "integrity": "sha512-1lpys/e19ee2gDTkcgIXyFNJySEqxdIxlu3Q1Oj+V0ORXVBfA9kFap2fHPWASaDJvmy1zpgGKlbzCpr+IEyfYQ==", "dependencies": { - "@sentry/core": "7.39.0", - "@sentry/types": "7.39.0", - "@sentry/utils": "7.39.0", + "@sentry-internal/tracing": "7.53.1" + }, + "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==", + "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==", + "dependencies": { + "@sentry/types": "7.53.1", "tslib": "^1.9.3" }, "engines": { "node": ">=8" } }, - "node_modules/@sentry/tracing/node_modules/@sentry/core": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.39.0.tgz", - "integrity": "sha512-45WJIcWWCQnZ8zhHtcrkJjQ4YydmzMWY4pmRuBG7Qp+zrCT6ISoyODcjY+SCHFdvXkiYFi8+bFZa1qG3YQnnYw==", - "dependencies": { - "@sentry/types": "7.39.0", - "@sentry/utils": "7.39.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/tracing/node_modules/@sentry/types": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.39.0.tgz", - "integrity": "sha512-5Y83Y8O3dT5zT2jTKEIPMcpn5lUm05KRMaCXuw0sRsv4r9TbBUKeqiSU1LjowT8rB/XNy8m7DHav8+NmogPaJw==", - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/tracing/node_modules/@sentry/utils": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.39.0.tgz", - "integrity": "sha512-/ZxlPgm1mGgmuMckCTc9iyqDuFTEYNEoMB53IjVFz8ann+37OiWB7Py/QV1rEEsv3xKrGbA8thhRhV9E1sjTlQ==", - "dependencies": { - "@sentry/types": "7.39.0", - "tslib": "^1.9.3" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@sentry/tracing/node_modules/tslib": { + "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==" @@ -3102,21 +2947,44 @@ "dev": true }, "node_modules/@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "dependencies": { "type-detect": "4.0.8" } }, "node_modules/@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", + "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, "dependencies": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.0.1.tgz", + "integrity": "sha512-9OrEn0WfOVtBNYJUjUAn9AOiJ4lzERCJJ/JeZs8E6yajTGxBaFRxUnNBHiNqoDJVg076hY36UmEnPx7xXrvUSg==", + "dependencies": { + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.0.0.tgz", + "integrity": "sha512-kc1m5wPBHQCTixwuaOh9vnak/iJm21DrSf9UK6yDE5S3mQQ4u11pqAUiKWnlrZnYkeLfAI9UEHj9OaMT1v5Umg==", + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, "node_modules/@tsconfig/node10": { @@ -3138,15 +3006,15 @@ "dev": true }, "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "node_modules/@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "dependencies": { "@babel/parser": "^7.20.7", @@ -3176,12 +3044,12 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.0.tgz", + "integrity": "sha512-TBOjqAGf0hmaqRwpii5LLkJLg7c6OMm4nHLmpsUxwk9bBHtoTC6dAHdVWdGv4TBxj2CZOZY8Xfq8WmfoVi7n4Q==", "dev": true, "dependencies": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "node_modules/@types/bcrypt": { @@ -3260,14 +3128,15 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.33", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", - "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "node_modules/@types/graceful-fs": { @@ -3304,9 +3173,9 @@ } }, "node_modules/@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", "dev": true, "dependencies": { "expect": "^29.0.0", @@ -3314,9 +3183,9 @@ } }, "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "node_modules/@types/jsonwebtoken": { @@ -3334,9 +3203,9 @@ "integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA==" }, "node_modules/@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", + "version": "4.14.195", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", "dev": true }, "node_modules/@types/long": { @@ -3345,25 +3214,34 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "node_modules/@types/node": { - "version": "18.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz", - "integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==" + "version": "18.16.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", + "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==" }, "node_modules/@types/nodemailer": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", - "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", + "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", "dev": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/passport": { + "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/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", @@ -3383,11 +3261,21 @@ "dev": true }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -3405,9 +3293,9 @@ "dev": true }, "node_modules/@types/superagent": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", - "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", "dev": true, "dependencies": { "@types/cookiejar": "*", @@ -3459,9 +3347,9 @@ } }, "node_modules/@types/yargs": { - "version": "17.0.22", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", - "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -3474,19 +3362,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@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", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -3507,62 +3395,15 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/parser": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", - "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" }, "engines": { @@ -3582,13 +3423,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", - "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3599,13 +3440,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "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==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -3625,67 +3466,10 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/types": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", - "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3696,13 +3480,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", - "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3723,18 +3507,18 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "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.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -3748,87 +3532,13 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", - "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", + "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==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -3999,6 +3709,20 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "node_modules/argon2": { + "version": "0.30.3", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", + "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "@phc/format": "^1.0.0", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -4071,9 +3795,9 @@ } }, "node_modules/aws-sdk": { - "version": "2.1324.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1324.0.tgz", - "integrity": "sha512-7T9Jn6qtzCANdqRcdhxZ9Fx31/U+h/VPFxEU3+sFEnC7WtGtRlgmsJOY2lIdFKRXkHYT3Jw5MqDyjnb/i1QqbA==", + "version": "2.1386.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1386.0.tgz", + "integrity": "sha512-bmUvpNRR4x1YvTaAm7WK/2lSNVPrNuiYlleU47GA5Xskh8PKaWedGHvGinH2YwhC720hM0Qc4f4/snUPGJ0eYg==", "dependencies": { "buffer": "4.9.2", "events": "1.1.1", @@ -4084,7 +3808,7 @@ "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" }, "engines": { "node": ">= 10.0.0" @@ -4099,9 +3823,9 @@ } }, "node_modules/axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -4109,24 +3833,24 @@ } }, "node_modules/axios-retry": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.4.0.tgz", - "integrity": "sha512-VdgaP+gHH4iQYCCNUWF2pcqeciVOdGrBBAYUfTY+wPcO5Ltvp/37MLFNCmJKo7Gj3SHvCSdL8ouI1qLYJN3liA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.0.tgz", + "integrity": "sha512-g48qNrLX30VU6ECWltpFCPegKK6dWzMDYv2o83W2zUL/Zh/SLXbT6ksGoKqYZHtghzqeeXhZBcSXJkO1fPbCcw==", "dependencies": { "@babel/runtime": "^7.15.4", "is-retry-allowed": "^2.2.0" } }, "node_modules/babel-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", - "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "dependencies": { - "@jest/transform": "^29.4.3", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.3", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -4155,9 +3879,9 @@ } }, "node_modules/babel-plugin-jest-hoist": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", - "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "dependencies": { "@babel/template": "^7.3.3", @@ -4193,12 +3917,12 @@ } }, "node_modules/babel-preset-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", - "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "dependencies": { - "babel-plugin-jest-hoist": "^29.4.3", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" }, "engines": { @@ -4232,6 +3956,14 @@ } ] }, + "node_modules/base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/bcrypt": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", @@ -4251,11 +3983,11 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, "node_modules/bigint-conversion": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.3.0.tgz", - "integrity": "sha512-U4Yzg8ygZ3m78n9weKP/6NMxN/98Pdsw6YdnDYgQO8fffL7ila31fCZIy5lCMswr4kEcyl8bGHltcHT0QdG/MQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.4.1.tgz", + "integrity": "sha512-/DTRevseMZoqN4KLkN5BryOiom0KbwYajiXG5Vo+ZcEPAO0WBZyZoYyDZSgfeq/v/oegLo9bjdndDBlExvAhBQ==", "dependencies": { - "@juanelas/base64": "^1.0.1" + "@juanelas/base64": "^1.1.2" } }, "node_modules/binary-extensions": { @@ -4267,6 +3999,42 @@ "node": ">=8" } }, + "node_modules/bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/bl/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -4330,9 +4098,9 @@ } }, "node_modules/browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.6.tgz", + "integrity": "sha512-PF07dKGXKR+/bljJzCB6rAYtHEu21TthLxmJagtQizx+rwiqdRDBO5971Xu1N7MgcMLi4+mr4Cnl76x7O3DHtA==", "dev": true, "funding": [ { @@ -4342,13 +4110,17 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001489", + "electron-to-chromium": "^1.4.411", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" }, "bin": { "browserslist": "cli.js" @@ -4509,9 +4281,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001458", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz", - "integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==", + "version": "1.0.30001489", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", + "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", "dev": true, "funding": [ { @@ -4521,6 +4293,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -4640,6 +4416,14 @@ "node": ">=12" } }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "engines": { + "node": ">=0.8" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -4815,8 +4599,7 @@ "node_modules/core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "node_modules/cors": { "version": "2.8.5", @@ -4922,9 +4705,9 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "engines": { "node": ">=0.10.0" } @@ -4942,6 +4725,14 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, + "node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -5055,9 +4846,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz", - "integrity": "sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==", + "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==", "dev": true }, "node_modules/emittery": { @@ -5126,13 +4917,15 @@ } }, "node_modules/eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@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", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -5142,10 +4935,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -5153,13 +4945,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "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", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -5167,7 +4958,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -5195,46 +4985,22 @@ "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -5242,6 +5008,9 @@ }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/estraverse": { @@ -5254,14 +5023,14 @@ } }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -5284,9 +5053,9 @@ } }, "node_modules/esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -5392,16 +5161,16 @@ } }, "node_modules/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "dependencies": { - "@jest/expect-utils": "^29.4.3", + "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3" + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -5448,6 +5217,14 @@ "node": ">= 0.10.0" } }, + "node_modules/express-async-errors": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", + "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", + "peerDependencies": { + "express": "^4.16.2" + } + }, "node_modules/express-rate-limit": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz", @@ -5853,12 +5630,13 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -5976,9 +5754,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/grapheme-splitter": { @@ -5987,6 +5765,12 @@ "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", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -6027,6 +5811,17 @@ "node": ">=8" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -6205,11 +6000,12 @@ } }, "node_modules/infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", + "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", "dependencies": { "axios": "^1.3.3", + "dotenv": "^16.0.3", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" } @@ -6305,9 +6101,9 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dev": true, "dependencies": { "has": "^1.0.3" @@ -6521,15 +6317,15 @@ } }, "node_modules/jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", - "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "dependencies": { - "@jest/core": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^29.4.3" + "jest-cli": "^29.5.0" }, "bin": { "jest": "bin/jest.js" @@ -6547,9 +6343,9 @@ } }, "node_modules/jest-changed-files": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", - "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "dependencies": { "execa": "^5.0.0", @@ -6560,28 +6356,29 @@ } }, "node_modules/jest-circus": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", - "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "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", "p-limit": "^3.1.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -6590,21 +6387,21 @@ } }, "node_modules/jest-cli": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", - "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "dependencies": { - "@jest/core": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", "yargs": "^17.3.1" }, @@ -6624,31 +6421,31 @@ } }, "node_modules/jest-config": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", - "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.3", - "@jest/types": "^29.4.3", - "babel-jest": "^29.4.3", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "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.4.3", - "jest-environment-node": "^29.4.3", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" }, @@ -6669,15 +6466,15 @@ } }, "node_modules/jest-diff": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", - "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, "dependencies": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -6696,33 +6493,33 @@ } }, "node_modules/jest-each": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", - "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.4.3", - "pretty-format": "^29.4.3" + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-environment-node": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", - "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", + "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==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -6738,20 +6535,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", - "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@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.4.3", - "jest-worker": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -6778,46 +6575,46 @@ } }, "node_modules/jest-leak-detector": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", - "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "dependencies": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-matcher-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", - "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", + "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==", "dev": true, "dependencies": { "chalk": "^4.0.0", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-message-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", - "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "dependencies": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" }, @@ -6826,14 +6623,14 @@ } }, "node_modules/jest-mock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", - "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-util": "^29.4.3" + "jest-util": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -6866,17 +6663,17 @@ } }, "node_modules/jest-resolve": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", - "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", + "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==", "dev": true, "dependencies": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" @@ -6886,43 +6683,43 @@ } }, "node_modules/jest-resolve-dependencies": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", - "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "dependencies": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.4.3" + "jest-snapshot": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-runner": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", - "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "dependencies": { - "@jest/console": "^29.4.3", - "@jest/environment": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@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", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-leak-detector": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-util": "^29.4.3", - "jest-watcher": "^29.4.3", - "jest-worker": "^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", "p-limit": "^3.1.0", "source-map-support": "0.5.13" }, @@ -6931,31 +6728,31 @@ } }, "node_modules/jest-runtime": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", - "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", "dev": true, "dependencies": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/globals": "^29.4.3", + "@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.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@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.4.3", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" }, @@ -6964,9 +6761,9 @@ } }, "node_modules/jest-snapshot": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", - "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", @@ -6975,23 +6772,22 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.3", + "expect": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "semver": "^7.3.5" }, "engines": { @@ -6999,12 +6795,12 @@ } }, "node_modules/jest-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", - "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -7016,35 +6812,35 @@ } }, "node_modules/jest-validate": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", - "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-watcher": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", - "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "dependencies": { - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "string-length": "^4.0.1" }, "engines": { @@ -7052,13 +6848,13 @@ } }, "node_modules/jest-worker": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", - "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -7089,16 +6885,6 @@ "node": ">= 0.6.0" } }, - "node_modules/js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" - } - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -7404,13 +7190,13 @@ } }, "node_modules/maxmind": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.8.tgz", - "integrity": "sha512-HrfxEu5yPBPtTy/OT+W5bPQwEfLUX0EHqe2EbJiB47xQMumHqXvSP7PAwzV8Z++NRCmQwy4moQrTSt0+dH+Jmg==", + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.11.tgz", + "integrity": "sha512-tJDrKbUzN6PSA88tWgg0L2R4Ln00XwecYQJPFI+RvlF2k1sx6VQYtuQ1SVxm8+bw5tF7GWV4xyb+3/KyzEpPUw==", "dev": true, "dependencies": { "mmdb-lib": "2.0.2", - "tiny-lru": "9.0.3" + "tiny-lru": "11.0.1" }, "engines": { "node": ">=12", @@ -7541,9 +7327,9 @@ } }, "node_modules/minipass": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.4.tgz", - "integrity": "sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "engines": { "node": ">=8" } @@ -7598,11 +7384,11 @@ } }, "node_modules/mongodb": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.14.0.tgz", - "integrity": "sha512-coGKkWXIBczZPr284tYKFLg+KbGPPLlSbdgfKAb6QqCFt5bo5VFZ50O3FFzsw4rnkqjwT6D8Qcoo9nshYKM7Mg==", + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.16.0.tgz", + "integrity": "sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g==", "dependencies": { - "bson": "^4.7.0", + "bson": "^4.7.2", "mongodb-connection-string-url": "^2.5.4", "socks": "^2.7.1" }, @@ -7624,13 +7410,13 @@ } }, "node_modules/mongoose": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.10.2.tgz", - "integrity": "sha512-9/AbheG2PiVVBWLx3S6LgCIEQNdMppjdnp/WH9nLGjFzjJeb9LiHNPEtsOGOm8qXmuICHMdbn5iUFAsLWWvpEw==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.1.tgz", + "integrity": "sha512-AvQ8C5ZGF6GcsQhoRg/i7pbNZpb96qLGU5ICBllckp7qMOxcfUF1nA6JstZw841BqRcE6myZ/mx9CluEESaw5Q==", "dependencies": { - "bson": "^4.7.0", + "bson": "^4.7.2", "kareem": "2.5.1", - "mongodb": "4.14.0", + "mongodb": "4.16.0", "mpath": "0.9.0", "mquery": "4.0.3", "ms": "2.1.3", @@ -7673,6 +7459,23 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -7703,10 +7506,21 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -7748,23 +7562,23 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", "dev": true }, "node_modules/nodemailer": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", - "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==", + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz", + "integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg==", "engines": { "node": ">=6.0.0" } }, "node_modules/nodemon": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", - "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, "dependencies": { "chokidar": "^3.5.2", @@ -10440,6 +10254,11 @@ "set-blocking": "^2.0.0" } }, + "node_modules/oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10498,6 +10317,17 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/optional-require": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "dependencies": { + "require-at": "^1.0.6" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -10592,6 +10422,61 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "dependencies": { + "passport-oauth2": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "dependencies": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -10638,6 +10523,11 @@ "node": ">=8" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -10730,9 +10620,9 @@ } }, "node_modules/posthog-node": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.5.4.tgz", - "integrity": "sha512-CdywlVh0CZU05/3MrBc0qY/zsLdU2X9XSz/yL1qMRhbyZhD8lrnuGlI69G2cpzZtli6S/nu64wcmULz/mFFA5w==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.6.0.tgz", + "integrity": "sha512-/BiFw/jwdP0uJSRAIoYqLoBTjZ612xv74b1L/a3T/p1nJVL8e0OrHuxbJW56c6WVW/IKm9gBF/zhbqfaz0XgJQ==", "dependencies": { "axios": "^0.27.0" }, @@ -10759,9 +10649,9 @@ } }, "node_modules/pretty-format": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", - "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "dependencies": { "@jest/schemas": "^29.4.3", @@ -10784,6 +10674,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -10853,6 +10748,22 @@ "node": ">=6" } }, + "node_modules/pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ] + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -10941,6 +10852,62 @@ "node": ">= 0.6" } }, + "node_modules/rate-limit-mongo": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rate-limit-mongo/-/rate-limit-mongo-2.3.2.tgz", + "integrity": "sha512-dLck0j5N/AX9ycVHn5lX9Ti2Wrrwi1LfbXitu/mMBZOo2nC26RgYKJVbcb2mYgb9VMaPI2IwJVzIa2hAQrMaDA==", + "dependencies": { + "mongodb": "^3.6.7", + "twostep": "0.4.2", + "underscore": "1.12.1" + } + }, + "node_modules/rate-limit-mongo/node_modules/bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "integrity": "sha512-EvVNVeGo4tHxwi8L6bPj3y3itEvStdwvvlojVxxbyYfoaxJ6keLgrTuKdyfEAszFK+H3olzBuafE0yoh0D1gdg==", + "engines": { + "node": ">=0.6.19" + } + }, + "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==", + "dependencies": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.1.8", + "safe-buffer": "^5.1.2" + }, + "engines": { + "node": ">=4" + }, + "optionalDependencies": { + "saslprep": "^1.0.0" + }, + "peerDependenciesMeta": { + "aws4": { + "optional": true + }, + "bson-ext": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "mongodb-extjson": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, "node_modules/raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -10962,9 +10929,9 @@ "dev": true }, "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -10991,23 +10958,14 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, + "node_modules/require-at": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=4" } }, - "node_modules/request-ip": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/request-ip/-/request-ip-3.3.0.tgz", - "integrity": "sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==" - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -11018,12 +10976,12 @@ } }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -11065,9 +11023,9 @@ } }, "node_modules/resolve.exports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz", - "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true, "engines": { "node": ">=10" @@ -11149,9 +11107,9 @@ ] }, "node_modules/safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==", + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", "engines": { "node": ">=10" } @@ -11179,9 +11137,9 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dependencies": { "lru-cache": "^6.0.0" }, @@ -11708,14 +11666,14 @@ } }, "node_modules/swagger-ui-dist": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.16.1.tgz", - "integrity": "sha512-4J4XekQG0ol4/TyUzMfksrWsMTbw/7JYlT+SFaX7H0xamd1OeuVlUSb/Cbq4qdDx1lc+uLZQW7u2mlImcE8c+w==" + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.19.0.tgz", + "integrity": "sha512-9C9fJGI18gK5AhaU5YRyPY1lXJH4lmWh8h9zFMrJBkYzdRjCbAzYl1ayWPYgwFvag/Luqi3Co599OK/39IS2QQ==" }, "node_modules/swagger-ui-express": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.2.tgz", - "integrity": "sha512-MHIOaq9JrTTB3ygUJD+08PbjM5Tt/q7x80yz9VTFIatw8j5uIWKcr90S0h5NLMzFEDC6+eVprtoeA5MDZXCUKQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", + "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", "dependencies": { "swagger-ui-dist": ">=4.11.0" }, @@ -11723,17 +11681,17 @@ "node": ">= v0.10.32" }, "peerDependencies": { - "express": ">=4.0.0" + "express": ">=4.0.0 || >=5.0.0-beta" } }, "node_modules/tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -11773,12 +11731,12 @@ "dev": true }, "node_modules/tiny-lru": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-9.0.3.tgz", - "integrity": "sha512-/i9GruRjXsnDgehxvy6iZ4AFNVxngEFbwzirhdulomMNPGPVV3ECMZOWSw0w4sRMZ9Al9m4jy08GPvRxRUGYlw==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz", + "integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==", "dev": true, "engines": { - "node": ">=6" + "node": ">=12" } }, "node_modules/tmpl": { @@ -11860,9 +11818,9 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "node_modules/ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "dependencies": { "bs-logger": "0.x", @@ -11885,7 +11843,7 @@ "@jest/types": "^29.0.0", "babel-jest": "^29.0.0", "jest": "^29.0.0", - "typescript": ">=4.3" + "typescript": ">=4.3 <6" }, "peerDependenciesMeta": { "@babel/core": { @@ -11946,9 +11904,9 @@ } }, "node_modules/tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "node_modules/tsutils": { "version": "3.21.0", @@ -11981,6 +11939,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" }, + "node_modules/twostep": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/twostep/-/twostep-0.4.2.tgz", + "integrity": "sha512-O/wdPYk9ey04qcCiw8AQN74DbvLFZLAgnryrNTpV7T/sxB4lcGkCMHynx5xCcA6fCh739ZAqp3HcGhy770X1qA==" + }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -12050,12 +12013,22 @@ "node": ">=0.8.0" } }, + "node_modules/uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "node_modules/underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, "node_modules/universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -12070,9 +12043,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "funding": [ { @@ -12082,6 +12055,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -12089,7 +12066,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -12287,9 +12264,9 @@ } }, "node_modules/winston": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", - "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", + "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", "dependencies": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -12390,18 +12367,21 @@ "dev": true }, "node_modules/xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "dependencies": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" } }, "node_modules/xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", "engines": { "node": ">=4.0" } @@ -12422,9 +12402,9 @@ "dev": true }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -12472,15 +12452,32 @@ }, "dependencies": { "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, + "@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "requires": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + } + } + }, "@aws-crypto/ie11-detection": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", @@ -12568,977 +12565,799 @@ } }, "@aws-sdk/abort-controller": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.272.0.tgz", - "integrity": "sha512-s2TV3phapcTwZNr4qLxbfuQuE9ZMP4RoJdkvRRCkKdm6jslsWLJf2Zlcxti/23hOlINUMYv2iXE2pftIgWGdpg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/abort-controller/-/abort-controller-3.347.0.tgz", + "integrity": "sha512-P/2qE6ntYEmYG4Ez535nJWZbXqgbkJx8CMz7ChEuEg3Gp3dvVYEKg+iEUEvlqQ2U5dWP5J3ehw5po9t86IsVPQ==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/client-cognito-identity": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.279.0.tgz", - "integrity": "sha512-MQQdgc3CGDumKutKWlNcDFgNXe2/Tr9TqDGh1EbtXODdxrsT/xQPMghlGCsrTxnPk16zj6OIlS/4h9bTbk6CVg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.347.0.tgz", + "integrity": "sha512-Z92GT2SC1y1r0bl3XI6ZH6QMsL2AaG3IR6ORXeiA94OY9/eF/tQT0zDbwn/MZUwJuBnR0CfO8bq7IQgCAguQ4A==", "optional": true, "requires": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.279.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" } }, "@aws-sdk/client-secrets-manager": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.281.0.tgz", - "integrity": "sha512-vL+LygNDoCja/47pFwSnI3tCWfy5SGHlz6C1whcszmfl81gXyuHNlAK8RXVRiKhnD11zmCsHJhZyYSfTz5RErQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.347.0.tgz", + "integrity": "sha512-lqBBJobdpVGx5OJpI3P52SaOilPkVW9zKVwPndoou8hpPYMMUVbVZ/Q0rSmjXC7wi9VzMB4SlENDM519Hu/tdQ==", "requires": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/client-sts": "3.281.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.281.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1", + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0", "uuid": "^8.3.2" - }, - "dependencies": { - "@aws-sdk/client-sso": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.281.0.tgz", - "integrity": "sha512-3RvO5zClQhu37w9VMLoHPGk58S3y8Spb7XX8rW51bm5TUglYQskQ0X2VLEUW/7ZGx/peokHws9Z9+w5yGq5sdA==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-sso-oidc": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.281.0.tgz", - "integrity": "sha512-P6zf9pDuxApVoCYStAg7L8BU9AcWI8PxfLSX4r2WnmcQropxzPJ3op1j9nvbwwBDMFWephijVY4AVp8MqPcPyg==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/client-sts": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.281.0.tgz", - "integrity": "sha512-w8QomyhCVEArRcXgOkjbofiS/PLEKWRAyYBovjMS1cGhns2ZYJXFgHNgr3VGE54TghUc5dR1CqKuBKKM4ThrgA==", - "requires": { - "@aws-crypto/sha256-browser": "3.0.0", - "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.281.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-sdk-sts": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "fast-xml-parser": "4.1.2", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-ini": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.281.0.tgz", - "integrity": "sha512-H99nhMhHImQKgNhHKYc6usTS6UK8KzCcVGpILLVTuP97YlrYAMFAVstA3Xk6mZ28JAbHVXvI6vJjkMNOzCSKCA==", - "requires": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.281.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-node": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.281.0.tgz", - "integrity": "sha512-jhddd+lJp8G8hBJ+6glmXjfWJT3nxiE1aliH3fBC4RR3D+1kRXc99Xg6mbUb8bm+GrVZ4gzfiqSgg+ByKjd7xA==", - "requires": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.281.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.281.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/credential-provider-sso": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.281.0.tgz", - "integrity": "sha512-IqJnpXuLpJYoSCf/Rt66/CPVTjfkam3z9+ZvlQJV+VbK+vGj276qEtTmSN3XPZZgF1XbWptvkzIWDszLhHiZmg==", - "requires": { - "@aws-sdk/client-sso": "3.281.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/token-providers": "3.281.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - } - }, - "@aws-sdk/token-providers": { - "version": "3.281.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.281.0.tgz", - "integrity": "sha512-36Vg/F6Edm7qdjcTeNVON+sK2edgHhmhTtAEjWcuUk5AX/Et+Ate/A2N8HD3nxwlAcgidfnBC9SHYJatbhcEnQ==", - "requires": { - "@aws-sdk/client-sso-oidc": "3.281.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" - } - } } }, "@aws-sdk/client-sso": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.279.0.tgz", - "integrity": "sha512-599Y5wOrkpjD6p0BTs0X4+Ge9O7jlAPJ2ttI9lfhT2/UEZyqoJHajJs1pMJV75oeZklPOBi8G9jnZcMVJgRpvQ==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.347.0.tgz", + "integrity": "sha512-AZehWCNLUXTrDavsZYRi7d84Uef20ppYJ2FY0KxqrKB3lx89mO29SfSJSC4woeW5+6ooBokq8HtKxw5ImPfRhA==", "requires": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" } }, "@aws-sdk/client-sso-oidc": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.279.0.tgz", - "integrity": "sha512-tC9xKGo3z/HQbJDMvaUrnBSSRX7sOX2YUA2OpJ3T1TTfylLTO70OKjg1G4OMFNiPpJsHonwD7Iud+rnMnUKI0g==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.347.0.tgz", + "integrity": "sha512-IBxRfPqb8f9FqpmDbzcRDfoiasj/Y47C4Gj+j3kA5T1XWyGwbDI9QnPW/rnkZTWxLUUG1LSbBNwbPD6TLoff8A==", "requires": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" } }, "@aws-sdk/client-sts": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.279.0.tgz", - "integrity": "sha512-y/cI5Gg5WWqmSSDQftCT26wOLu0HSuPY1u6Q4Q97FBIfRC3hYztjYdUDHuTu6qPPT+tdsnWOUy2tr3qamVSQ4g==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.347.0.tgz", + "integrity": "sha512-QcJCUlzJZLAFTFSuELKd4BF5I5W38TR/m7NX2y1tn2la9JIrWSrz+tj598zfp2V4pJPzRJ1i8RglTZxSRIvsxQ==", "requires": { "@aws-crypto/sha256-browser": "3.0.0", "@aws-crypto/sha256-js": "3.0.0", - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/fetch-http-handler": "3.272.0", - "@aws-sdk/hash-node": "3.272.0", - "@aws-sdk/invalid-dependency": "3.272.0", - "@aws-sdk/middleware-content-length": "3.272.0", - "@aws-sdk/middleware-endpoint": "3.272.0", - "@aws-sdk/middleware-host-header": "3.278.0", - "@aws-sdk/middleware-logger": "3.272.0", - "@aws-sdk/middleware-recursion-detection": "3.272.0", - "@aws-sdk/middleware-retry": "3.272.0", - "@aws-sdk/middleware-sdk-sts": "3.272.0", - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/middleware-user-agent": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/node-http-handler": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/smithy-client": "3.279.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "@aws-sdk/util-body-length-browser": "3.188.0", - "@aws-sdk/util-body-length-node": "3.208.0", - "@aws-sdk/util-defaults-mode-browser": "3.279.0", - "@aws-sdk/util-defaults-mode-node": "3.279.0", - "@aws-sdk/util-endpoints": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "@aws-sdk/util-user-agent-browser": "3.272.0", - "@aws-sdk/util-user-agent-node": "3.272.0", - "@aws-sdk/util-utf8": "3.254.0", + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/fetch-http-handler": "3.347.0", + "@aws-sdk/hash-node": "3.347.0", + "@aws-sdk/invalid-dependency": "3.347.0", + "@aws-sdk/middleware-content-length": "3.347.0", + "@aws-sdk/middleware-endpoint": "3.347.0", + "@aws-sdk/middleware-host-header": "3.347.0", + "@aws-sdk/middleware-logger": "3.347.0", + "@aws-sdk/middleware-recursion-detection": "3.347.0", + "@aws-sdk/middleware-retry": "3.347.0", + "@aws-sdk/middleware-sdk-sts": "3.347.0", + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/middleware-user-agent": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/node-http-handler": "3.347.0", + "@aws-sdk/smithy-client": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "@aws-sdk/util-body-length-browser": "3.310.0", + "@aws-sdk/util-body-length-node": "3.310.0", + "@aws-sdk/util-defaults-mode-browser": "3.347.0", + "@aws-sdk/util-defaults-mode-node": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "@aws-sdk/util-user-agent-browser": "3.347.0", + "@aws-sdk/util-user-agent-node": "3.347.0", + "@aws-sdk/util-utf8": "3.310.0", + "@smithy/protocol-http": "^1.0.1", + "@smithy/types": "^1.0.0", "fast-xml-parser": "4.1.2", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/config-resolver": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.272.0.tgz", - "integrity": "sha512-Dr4CffRVNsOp3LRNdpvcH6XuSgXOSLblWliCy/5I86cNl567KVMxujVx6uPrdTXYs2h1rt3MNl6jQGnAiJeTbw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/config-resolver/-/config-resolver-3.347.0.tgz", + "integrity": "sha512-2ja+Sf/VnUO7IQ3nKbDQ5aumYKKJUaTm/BuVJ29wNho8wYHfuf7wHZV0pDTkB8RF5SH7IpHap7zpZAj39Iq+EA==", "requires": { - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-config-provider": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-cognito-identity": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.279.0.tgz", - "integrity": "sha512-RhpKmIM1RfrmbtTXiDK3qyx9aJcZlvHpP18Axbjokld7R6YEdMpv8piB8v19kd6zl0e9xPNrX9At6UOFsXpeJw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.347.0.tgz", + "integrity": "sha512-7NiVVQC51HvomI44OyD+UekZ7qxauJeFGwQILbQ0beAxNuPZL7Ect/jB6A5MeleyqP+sVn8cB7qBMZjFJRhoJA==", "optional": true, "requires": { - "@aws-sdk/client-cognito-identity": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-env": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.272.0.tgz", - "integrity": "sha512-QI65NbLnKLYHyTYhXaaUrq6eVsCCrMUb05WDA7+TJkWkjXesovpjc8vUKgFiLSxmgKmb2uOhHNcDyObKMrYQFw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.347.0.tgz", + "integrity": "sha512-UnEM+LKGpXKzw/1WvYEQsC6Wj9PupYZdQOE+e2Dgy2dqk/pVFy4WueRtFXYDT2B41ppv3drdXUuKZRIDVqIgNQ==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-imds": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.272.0.tgz", - "integrity": "sha512-wwAfVY1jTFQEfxVfdYD5r5ieYGl+0g4nhekVxNMqE8E1JeRDd18OqiwAflzpgBIqxfqvCUkf+vl5JYyacMkNAQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-imds/-/credential-provider-imds-3.347.0.tgz", + "integrity": "sha512-7scCy/DCDRLIhlqTxff97LQWDnRwRXji3bxxMg+xWOTTaJe7PWx+etGSbBWaL42vsBHFShQjSLvJryEgoBktpw==", "requires": { - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-ini": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.279.0.tgz", - "integrity": "sha512-FCpr3/khMTb2pWLMC138wU7HzcpkrjejrBNfCJSUu7Emxm039UMLjT2JObnRKxidKlz58oYBRayVIbBYRWREcg==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.347.0.tgz", + "integrity": "sha512-84TNF34ryabmVbILOq7f+/Jy8tJaskvHdax3X90qxFtXRU11kX0bf5NYL616KT0epR0VGpy50ThfIqvBwxeJfQ==", "requires": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-node": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.279.0.tgz", - "integrity": "sha512-7D8ETopCt3H+x2BEPMEhzc4dcNtSK7umnRdgfiTGRjcQSVPh5Whq/tDIAtNj2D+PmLgu3e+Hk7jrXkaMCDlxMw==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.347.0.tgz", + "integrity": "sha512-ds2uxE0krl94RdQ7bstwafUXdlMeEOPgedhaheVVlj8kH+XqlZdwUUaUv1uoEI9iBzuSjKftUkIHo0xsTiwtaw==", "requires": { - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.279.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-process": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.272.0.tgz", - "integrity": "sha512-hiCAjWWm2PeBFp5cjkxqyam/XADjiS+e7GzwC34TbZn3LisS0uoweLojj9tD11NnnUhyhbLteUvu5+rotOLwrg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.347.0.tgz", + "integrity": "sha512-yl1z4MsaBdXd4GQ2halIvYds23S67kElyOwz7g8kaQ4kHj+UoYWxz3JVW/DGusM6XmQ9/F67utBrUVA0uhQYyw==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-sso": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.279.0.tgz", - "integrity": "sha512-u8ZHz9Sv7sAv2vllyzcdgcO1pC5pa2UuoYKfz9J8hqLHc8VJYtYQ6WJvi4GoA55VDPk87pyVYz9t6ATntsukaw==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.347.0.tgz", + "integrity": "sha512-M1d7EnUaJbSNCmNalEbINmtFkc9wJufx7UhKtEeFwSq9KEzOMroH1MEOeiqIw9f/zE8NI/iPkVeEhw123vmBrQ==", "requires": { - "@aws-sdk/client-sso": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/token-providers": "3.279.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/token-providers": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-provider-web-identity": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.272.0.tgz", - "integrity": "sha512-ImrHMkcgneGa/HadHAQXPwOrX26sAKuB8qlMxZF/ZCM2B55u8deY+ZVkVuraeKb7YsahMGehPFOfRAF6mvFI5Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.347.0.tgz", + "integrity": "sha512-DxoTlVK8lXjS1zVphtz/Ab+jkN/IZor9d6pP2GjJHNoAIIzXfRwwj5C8vr4eTayx/5VJ7GRP91J8GJ2cKly8Qw==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/credential-providers": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.279.0.tgz", - "integrity": "sha512-iZI7hrP7oEP2zzStuiEWklVQY3HqIX02PxQiGMgW9/6Bb+2xBpZykIkBBmqaOKlNF/us1TJS6WDOylL1Z1EcIw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.347.0.tgz", + "integrity": "sha512-ny8tnuLToQIYbS+ztRh4/fViDDV1xk+WuapSK2T1MAIuPvhyD1IDulTyqv6P9ROoNIqt1NAoLctkWxdkLvqyQA==", "optional": true, "requires": { - "@aws-sdk/client-cognito-identity": "3.279.0", - "@aws-sdk/client-sso": "3.279.0", - "@aws-sdk/client-sts": "3.279.0", - "@aws-sdk/credential-provider-cognito-identity": "3.279.0", - "@aws-sdk/credential-provider-env": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/credential-provider-ini": "3.279.0", - "@aws-sdk/credential-provider-node": "3.279.0", - "@aws-sdk/credential-provider-process": "3.272.0", - "@aws-sdk/credential-provider-sso": "3.279.0", - "@aws-sdk/credential-provider-web-identity": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-cognito-identity": "3.347.0", + "@aws-sdk/client-sso": "3.347.0", + "@aws-sdk/client-sts": "3.347.0", + "@aws-sdk/credential-provider-cognito-identity": "3.347.0", + "@aws-sdk/credential-provider-env": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/credential-provider-ini": "3.347.0", + "@aws-sdk/credential-provider-node": "3.347.0", + "@aws-sdk/credential-provider-process": "3.347.0", + "@aws-sdk/credential-provider-sso": "3.347.0", + "@aws-sdk/credential-provider-web-identity": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" + } + }, + "@aws-sdk/eventstream-codec": { + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/eventstream-codec/-/eventstream-codec-3.347.0.tgz", + "integrity": "sha512-61q+SyspjsaQ4sdgjizMyRgVph2CiW4aAtfpoH69EJFJfTxTR/OqnZ9Jx/3YiYi0ksrvDenJddYodfWWJqD8/w==", + "requires": { + "@aws-crypto/crc32": "3.0.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/fetch-http-handler": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.272.0.tgz", - "integrity": "sha512-1Qhm9e0RbS1Xf4CZqUbQyUMkDLd7GrsRXWIvm9b86/vgeV8/WnjO3CMue9D51nYgcyQORhYXv6uVjAYCWbUExA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/fetch-http-handler/-/fetch-http-handler-3.347.0.tgz", + "integrity": "sha512-sQ5P7ivY8//7wdxfA76LT1sF6V2Tyyz1qF6xXf9sihPN5Q1Y65c+SKpMzXyFSPqWZ82+SQQuDliYZouVyS6kQQ==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/querystring-builder": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-base64": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-base64": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/hash-node": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.272.0.tgz", - "integrity": "sha512-40dwND+iAm3VtPHPZu7/+CIdVJFk2s0cWZt1lOiMPMSXycSYJ45wMk7Lly3uoqRx0uWfFK5iT2OCv+fJi5jTng==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/hash-node/-/hash-node-3.347.0.tgz", + "integrity": "sha512-96+ml/4EaUaVpzBdOLGOxdoXOjkPgkoJp/0i1fxOJEvl8wdAQSwc3IugVK9wZkCxy2DlENtgOe6DfIOhfffm/g==", "requires": { - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-buffer-from": "3.208.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-buffer-from": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/invalid-dependency": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.272.0.tgz", - "integrity": "sha512-ysW6wbjl1Y78txHUQ/Tldj2Rg1BI7rpMO9B9xAF6yAX3mQ7t6SUPQG/ewOGvH2208NBIl3qP5e/hDf0Q6r/1iw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/invalid-dependency/-/invalid-dependency-3.347.0.tgz", + "integrity": "sha512-8imQcwLwqZ/wTJXZqzXT9pGLIksTRckhGLZaXT60tiBOPKuerTsus2L59UstLs5LP8TKaVZKFFSsjRIn9dQdmQ==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/is-array-buffer": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.201.0.tgz", - "integrity": "sha512-UPez5qLh3dNgt0DYnPD/q0mVJY84rA17QE26hVNOW3fAji8W2wrwrxdacWOxyXvlxWsVRcKmr+lay1MDqpAMfg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/is-array-buffer/-/is-array-buffer-3.310.0.tgz", + "integrity": "sha512-urnbcCR+h9NWUnmOtet/s4ghvzsidFmspfhYaHAmSRdy9yDjdjBJMFjjsn85A1ODUktztm+cVncXjQ38WCMjMQ==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-content-length": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.272.0.tgz", - "integrity": "sha512-sAbDZSTNmLX+UTGwlUHJBWy0QGQkiClpHwVFXACon+aG0ySLNeRKEVYs6NCPYldw4cj6hveLUn50cX44ukHErw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-content-length/-/middleware-content-length-3.347.0.tgz", + "integrity": "sha512-i4qtWTDImMaDUtwKQPbaZpXsReiwiBomM1cWymCU4bhz81HL01oIxOxOBuiM+3NlDoCSPr3KI6txZSz/8cqXCQ==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-endpoint": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.272.0.tgz", - "integrity": "sha512-Dk3JVjj7SxxoUKv3xGiOeBksvPtFhTDrVW75XJ98Ymv8gJH5L1sq4hIeJAHRKogGiRFq2J73mnZSlM9FVXEylg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-endpoint/-/middleware-endpoint-3.347.0.tgz", + "integrity": "sha512-unF0c6dMaUL1ffU+37Ugty43DgMnzPWXr/Jup/8GbK5fzzWT5NQq6dj9KHPubMbWeEjQbmczvhv25JuJdK8gNQ==", "requires": { - "@aws-sdk/middleware-serde": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/url-parser": "3.272.0", - "@aws-sdk/util-config-provider": "3.208.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-serde": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/url-parser": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-host-header": { - "version": "3.278.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.278.0.tgz", - "integrity": "sha512-oTkF3exy89KE8NgSeXFwD+0H0GRKL2qUw92t3caEj7+4KzU/0m3t7NtKlq2NLRtTJhZ/izYRpV536oogLzGm3g==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.347.0.tgz", + "integrity": "sha512-kpKmR9OvMlnReqp5sKcJkozbj1wmlblbVSbnQAIkzeQj2xD5dnVR3Nn2ogQKxSmU1Fv7dEroBtrruJ1o3fY38A==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-logger": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.272.0.tgz", - "integrity": "sha512-u2SQ0hWrFwxbxxYMG5uMEgf01pQY5jauK/LYWgGIvuCmFgiyRQQP3oN7kkmsxnS9MWmNmhbyQguX2NY02s5e9w==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.347.0.tgz", + "integrity": "sha512-NYC+Id5UCkVn+3P1t/YtmHt75uED06vwaKyxDy0UmB2K66PZLVtwWbLpVWrhbroaw1bvUHYcRyQ9NIfnVcXQjA==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-recursion-detection": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.272.0.tgz", - "integrity": "sha512-Gp/eKWeUWVNiiBdmUM2qLkBv+VLSJKoWAO+aKmyxxwjjmWhE0FrfA1NQ1a3g+NGMhRbAfQdaYswRAKsul70ISg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.347.0.tgz", + "integrity": "sha512-qfnSvkFKCAMjMHR31NdsT0gv5Sq/ZHTUD4yQsSLpbVQ6iYAS834lrzXt41iyEHt57Y514uG7F/Xfvude3u4icQ==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-retry": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.272.0.tgz", - "integrity": "sha512-pCGvHM7C76VbO/dFerH+Vwf7tGv7j+e+eGrvhQ35mRghCtfIou/WMfTZlD1TNee93crrAQQVZKjtW3dMB3WCzg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-retry/-/middleware-retry-3.347.0.tgz", + "integrity": "sha512-CpdM+8dCSbX96agy4FCzOfzDmhNnGBM/pxrgIVLm5nkYTLuXp/d7ubpFEUHULr+4hCd5wakHotMt7yO29NFaVw==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/service-error-classification": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-middleware": "3.272.0", - "@aws-sdk/util-retry": "3.272.0", - "tslib": "^2.3.1", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/service-error-classification": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-retry": "3.347.0", + "tslib": "^2.5.0", "uuid": "^8.3.2" } }, "@aws-sdk/middleware-sdk-sts": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.272.0.tgz", - "integrity": "sha512-VvYPg7LrDIjUOWueSzo2wBzcNG7dw+cmzV6zAKaLxf0RC5jeAP4hE0OzDiiZfDrjNghEzgq/V+0NO+LewqYL9Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.347.0.tgz", + "integrity": "sha512-38LJ0bkIoVF3W97x6Jyyou72YV9Cfbml4OaDEdnrCOo0EssNZM5d7RhjMvQDwww7/3OBY/BzeOcZKfJlkYUXGw==", "requires": { - "@aws-sdk/middleware-signing": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-signing": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-serde": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.272.0.tgz", - "integrity": "sha512-kW1uOxgPSwtXPB5rm3QLdWomu42lkYpQL94tM1BjyFOWmBLO2lQhk5a7Dw6HkTozT9a+vxtscLChRa6KZe61Hw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-serde/-/middleware-serde-3.347.0.tgz", + "integrity": "sha512-x5Foi7jRbVJXDu9bHfyCbhYDH5pKK+31MmsSJ3k8rY8keXLBxm2XEEg/AIoV9/TUF9EeVvZ7F1/RmMpJnWQsEg==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-signing": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.272.0.tgz", - "integrity": "sha512-4LChFK4VAR91X+dupqM8fQqYhFGE0G4Bf9rQlVTgGSbi2KUOmpqXzH0/WKE228nKuEhmH8+Qd2VPSAE2JcyAUA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.347.0.tgz", + "integrity": "sha512-zVBF/4MGKnvhAE/J+oAL/VAehiyv+trs2dqSQXwHou9j8eA8Vm8HS2NdOwpkZQchIxTuwFlqSusDuPEdYFbvGw==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/signature-v4": "3.272.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-middleware": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/signature-v4": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-middleware": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-stack": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.272.0.tgz", - "integrity": "sha512-jhwhknnPBGhfXAGV5GXUWfEhDFoP/DN8MPCO2yC5OAxyp6oVJ8lTPLkZYMTW5VL0c0eG44dXpF4Ib01V+PlDrQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-stack/-/middleware-stack-3.347.0.tgz", + "integrity": "sha512-Izidg4rqtYMcKuvn2UzgEpPLSmyd8ub9+LQ2oIzG3mpIzCBITq7wp40jN1iNkMg+X6KEnX9vdMJIYZsPYMCYuQ==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/middleware-user-agent": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.272.0.tgz", - "integrity": "sha512-Qy7/0fsDJxY5l0bEk7WKDfqb4Os/sCAgFR2zEvrhDtbkhYPf72ysvg/nRUTncmCbo8tOok4SJii2myk8KMfjjw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.347.0.tgz", + "integrity": "sha512-wJbGN3OE1/daVCrwk49whhIr9E0j1N4gWwN/wi4WuyYIA+5lMUfVp0aGIOvZR+878DxuFz2hQ4XcZVT4K2WvQw==", "requires": { - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-endpoints": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/node-config-provider": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.272.0.tgz", - "integrity": "sha512-YYCIBh9g1EQo7hm2l22HX5Yr9RoPQ2RCvhzKvF1n1e8t1QH4iObQrYUtqHG4khcm64Cft8C5MwZmgzHbya5Z6Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-config-provider/-/node-config-provider-3.347.0.tgz", + "integrity": "sha512-faU93d3+5uTTUcotGgMXF+sJVFjrKh+ufW+CzYKT4yUHammyaIab/IbTPWy2hIolcEGtuPeVoxXw8TXbkh/tuw==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/node-http-handler": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.272.0.tgz", - "integrity": "sha512-VrW9PjhhngeyYp4yGYPe5S0vgZH6NwU3Po9xAgayUeE37Inr7LS1YteFMHdpgsUUeNXnh7d06CXqHo1XjtqOKA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/node-http-handler/-/node-http-handler-3.347.0.tgz", + "integrity": "sha512-eluPf3CeeEaPbETsPw7ee0Rb0FP79amu8vdLMrQmkrD+KP4owupUXOEI4drxWJgBSd+3PRowPWCDA8wUtraHKg==", "requires": { - "@aws-sdk/abort-controller": "3.272.0", - "@aws-sdk/protocol-http": "3.272.0", - "@aws-sdk/querystring-builder": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/abort-controller": "3.347.0", + "@aws-sdk/protocol-http": "3.347.0", + "@aws-sdk/querystring-builder": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/property-provider": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.272.0.tgz", - "integrity": "sha512-V1pZTaH5eqpAt8O8CzbItHhOtzIfFuWymvwZFkAtwKuaHpnl7jjrTouV482zoq8AD/fF+VVSshwBKYA7bhidIw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/property-provider/-/property-provider-3.347.0.tgz", + "integrity": "sha512-t3nJ8CYPLKAF2v9nIHOHOlF0CviQbTvbFc2L4a+A+EVd/rM4PzL3+3n8ZJsr0h7f6uD04+b5YRFgKgnaqLXlEg==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/protocol-http": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.272.0.tgz", - "integrity": "sha512-4JQ54v5Yn08jspNDeHo45CaSn1CvTJqS1Ywgr79eU6jBExtguOWv6LNtwVSBD9X37v88iqaxt8iu1Z3pZZAJeg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/protocol-http/-/protocol-http-3.347.0.tgz", + "integrity": "sha512-2YdBhc02Wvy03YjhGwUxF0UQgrPWEy8Iq75pfS42N+/0B/+eWX1aQgfjFxIpLg7YSjT5eKtYOQGlYd4MFTgj9g==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/querystring-builder": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.272.0.tgz", - "integrity": "sha512-ndo++7GkdCj5tBXE6rGcITpSpZS4PfyV38wntGYAlj9liL1omk3bLZRY6uzqqkJpVHqbg2fD7O2qHNItzZgqhw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-builder/-/querystring-builder-3.347.0.tgz", + "integrity": "sha512-phtKTe6FXoV02MoPkIVV6owXI8Mwr5IBN3bPoxhcPvJG2AjEmnetSIrhb8kwc4oNhlwfZwH6Jo5ARW/VEWbZtg==", "requires": { - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/querystring-parser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.272.0.tgz", - "integrity": "sha512-5oS4/9n6N1LZW9tI3qq/0GnCuWoOXRgcHVB+AJLRBvDbEe+GI+C/xK1tKLsfpDNgsQJHc4IPQoIt4megyZ/1+A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/querystring-parser/-/querystring-parser-3.347.0.tgz", + "integrity": "sha512-5VXOhfZz78T2W7SuXf2avfjKglx1VZgZgp9Zfhrt/Rq+MTu2D+PZc5zmJHhYigD7x83jLSLogpuInQpFMA9LgA==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/service-error-classification": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.272.0.tgz", - "integrity": "sha512-REoltM1LK9byyIufLqx9znhSolPcHQgVHIA2S0zu5sdt5qER4OubkLAXuo4MBbisUTmh8VOOvIyUb5ijZCXq1w==" + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/service-error-classification/-/service-error-classification-3.347.0.tgz", + "integrity": "sha512-xZ3MqSY81Oy2gh5g0fCtooAbahqh9VhsF8vcKjVX8+XPbGC8y+kej82+MsMg4gYL8gRFB9u4hgYbNgIS6JTAvg==" }, "@aws-sdk/shared-ini-file-loader": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.272.0.tgz", - "integrity": "sha512-lzFPohp5sy2XvwFjZIzLVCRpC0i5cwBiaXmFzXYQZJm6FSCszHO4ax+m9yrtlyVFF/2YPWl+/bzNthy4aJtseA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/shared-ini-file-loader/-/shared-ini-file-loader-3.347.0.tgz", + "integrity": "sha512-Xw+zAZQVLb+xMNHChXQ29tzzLqm3AEHsD8JJnlkeFjeMnWQtXdUfOARl5s8NzAppcKQNlVe2gPzjaKjoy2jz1Q==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/signature-v4": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.272.0.tgz", - "integrity": "sha512-pWxnHG1NqJWMwlhJ6NHNiUikOL00DHROmxah6krJPMPq4I3am2KY2Rs/8ouWhnEXKaHAv4EQhSALJ+7Mq5S4/A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4/-/signature-v4-3.347.0.tgz", + "integrity": "sha512-58Uq1do+VsTHYkP11dTK+DF53fguoNNJL9rHRWhzP+OcYv3/mBMLoS2WPz/x9FO5mBg4ESFsug0I6mXbd36tjw==", "requires": { - "@aws-sdk/is-array-buffer": "3.201.0", - "@aws-sdk/types": "3.272.0", - "@aws-sdk/util-hex-encoding": "3.201.0", - "@aws-sdk/util-middleware": "3.272.0", - "@aws-sdk/util-uri-escape": "3.201.0", - "@aws-sdk/util-utf8": "3.254.0", - "tslib": "^2.3.1" + "@aws-sdk/eventstream-codec": "3.347.0", + "@aws-sdk/is-array-buffer": "3.310.0", + "@aws-sdk/types": "3.347.0", + "@aws-sdk/util-hex-encoding": "3.310.0", + "@aws-sdk/util-middleware": "3.347.0", + "@aws-sdk/util-uri-escape": "3.310.0", + "@aws-sdk/util-utf8": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/smithy-client": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.279.0.tgz", - "integrity": "sha512-ZcYWUQDGAYN6NXRpJuSn46PetrpPCA6TrDVwP9+3pERzTXZ66npXoG2XhHjNrOXy/Ted5A3OxKrM4/zLu9tK3A==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/smithy-client/-/smithy-client-3.347.0.tgz", + "integrity": "sha512-PaGTDsJLGK0sTjA6YdYQzILRlPRN3uVFyqeBUkfltXssvUzkm8z2t1lz2H4VyJLAhwnG5ZuZTNEV/2mcWrU7JQ==", "requires": { - "@aws-sdk/middleware-stack": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/middleware-stack": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/token-providers": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.279.0.tgz", - "integrity": "sha512-bsUlZSizTXZ8Pehdatcioi8VphxYn7fRjo5L083peOvBjoL+9WSGyP74PLrFLNwA35QxddwOqgnpQZoE1heuPQ==", - "optional": true, + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.347.0.tgz", + "integrity": "sha512-DZS9UWEy105zsaBJTgcvv1U+0jl7j1OzfMpnLf/lEYjEvx/4FqY2Ue/OZUACJorZgm/dWNqrhY17tZXtS/S3ew==", "requires": { - "@aws-sdk/client-sso-oidc": "3.279.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/shared-ini-file-loader": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/client-sso-oidc": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/shared-ini-file-loader": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/types": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.272.0.tgz", - "integrity": "sha512-MmmL6vxMGP5Bsi+4wRx4mxYlU/LX6M0noOXrDh/x5FfG7/4ZOar/nDxqDadhJtNM88cuWVHZWY59P54JzkGWmA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.347.0.tgz", + "integrity": "sha512-GkCMy79mdjU9OTIe5KT58fI/6uqdf8UmMdWqVHmFJ+UpEzOci7L/uw4sOXWo7xpPzLs6cJ7s5ouGZW4GRPmHFA==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/url-parser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.272.0.tgz", - "integrity": "sha512-vX/Tx02PlnQ/Kgtf5TnrNDHPNbY+amLZjW0Z1d9vzAvSZhQ4i9Y18yxoRDIaDTCNVRDjdhV8iuctW+05PB5JtQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/url-parser/-/url-parser-3.347.0.tgz", + "integrity": "sha512-lhrnVjxdV7hl+yCnJfDZOaVLSqKjxN20MIOiijRiqaWGLGEAiSqBreMhL89X1WKCifxAs4zZf9YB9SbdziRpAA==", "requires": { - "@aws-sdk/querystring-parser": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/querystring-parser": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-base64": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.208.0.tgz", - "integrity": "sha512-PQniZph5A6N7uuEOQi+1hnMz/FSOK/8kMFyFO+4DgA1dZ5pcKcn5wiFwHkcTb/BsgVqQa3Jx0VHNnvhlS8JyTg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-base64/-/util-base64-3.310.0.tgz", + "integrity": "sha512-v3+HBKQvqgdzcbL+pFswlx5HQsd9L6ZTlyPVL2LS9nNXnCcR3XgGz9jRskikRUuUvUXtkSG1J88GAOnJ/apTPg==", "requires": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-body-length-browser": { - "version": "3.188.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.188.0.tgz", - "integrity": "sha512-8VpnwFWXhnZ/iRSl9mTf+VKOX9wDE8QtN4bj9pBfxwf90H1X7E8T6NkiZD3k+HubYf2J94e7DbeHs7fuCPW5Qg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-browser/-/util-body-length-browser-3.310.0.tgz", + "integrity": "sha512-sxsC3lPBGfpHtNTUoGXMQXLwjmR0zVpx0rSvzTPAuoVILVsp5AU/w5FphNPxD5OVIjNbZv9KsKTuvNTiZjDp9g==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-body-length-node": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.208.0.tgz", - "integrity": "sha512-3zj50e5g7t/MQf53SsuuSf0hEELzMtD8RX8C76f12OSRo2Bca4FLLYHe0TZbxcfQHom8/hOaeZEyTyMogMglqg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-body-length-node/-/util-body-length-node-3.310.0.tgz", + "integrity": "sha512-2tqGXdyKhyA6w4zz7UPoS8Ip+7sayOg9BwHNidiGm2ikbDxm1YrCfYXvCBdwaJxa4hJfRVz+aL9e+d3GqPI9pQ==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-buffer-from": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.208.0.tgz", - "integrity": "sha512-7L0XUixNEFcLUGPeBF35enCvB9Xl+K6SQsmbrPk1P3mlV9mguWSDQqbOBwY1Ir0OVbD6H/ZOQU7hI/9RtRI0Zw==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-buffer-from/-/util-buffer-from-3.310.0.tgz", + "integrity": "sha512-i6LVeXFtGih5Zs8enLrt+ExXY92QV25jtEnTKHsmlFqFAuL3VBeod6boeMXkN2p9lbSVVQ1sAOOYZOHYbYkntw==", "requires": { - "@aws-sdk/is-array-buffer": "3.201.0", - "tslib": "^2.3.1" + "@aws-sdk/is-array-buffer": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-config-provider": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.208.0.tgz", - "integrity": "sha512-DSRqwrERUsT34ug+anlMBIFooBEGwM8GejC7q00Y/9IPrQy50KnG5PW2NiTjuLKNi7pdEOlwTSEocJE15eDZIg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-config-provider/-/util-config-provider-3.310.0.tgz", + "integrity": "sha512-xIBaYo8dwiojCw8vnUcIL4Z5tyfb1v3yjqyJKJWV/dqKUFOOS0U591plmXbM+M/QkXyML3ypon1f8+BoaDExrg==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-defaults-mode-browser": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.279.0.tgz", - "integrity": "sha512-RnchYRrpapTT5Hu23LOfk6e8RMVq0kUzho6xA6TJj1a4uGxkcRMvgzPipCq1P5uHu0mrkQBg9pGPEVNOUs38/Q==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-browser/-/util-defaults-mode-browser-3.347.0.tgz", + "integrity": "sha512-+JHFA4reWnW/nMWwrLKqL2Lm/biw/Dzi/Ix54DAkRZ08C462jMKVnUlzAI+TfxQE3YLm99EIa0G7jiEA+p81Qw==", "requires": { - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-defaults-mode-node": { - "version": "3.279.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.279.0.tgz", - "integrity": "sha512-A2NB10xReWC+GSnOivKGZ9rnljIZdEP8WMCQQEnA6DJNI19AUFF/O9QJ9y+cHGLKEms7jH86Y99wShdpzAK+Jw==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-defaults-mode-node/-/util-defaults-mode-node-3.347.0.tgz", + "integrity": "sha512-A8BzIVhAAZE5WEukoAN2kYebzTc99ZgncbwOmgCCbvdaYlk5tzguR/s+uoT4G0JgQGol/4hAMuJEl7elNgU6RQ==", "requires": { - "@aws-sdk/config-resolver": "3.272.0", - "@aws-sdk/credential-provider-imds": "3.272.0", - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/property-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/config-resolver": "3.347.0", + "@aws-sdk/credential-provider-imds": "3.347.0", + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/property-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-endpoints": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.272.0.tgz", - "integrity": "sha512-c4MPUaJt2G6gGpoiwIOqDfUa98c1J63RpYvf/spQEKOtC/tF5Gfqlxuq8FnAl5lHnrqj1B9ZXLLxFhHtDR0IiQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.347.0.tgz", + "integrity": "sha512-/WUkirizeNAqwVj0zkcrqdQ9pUm1HY5kU+qy7xTR0OebkuJauglkmSTMD+56L1JPunWqHhlwCMVRaz5eaJdSEQ==", "requires": { - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-hex-encoding": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.201.0.tgz", - "integrity": "sha512-7t1vR1pVxKx0motd3X9rI3m/xNp78p3sHtP5yo4NP4ARpxyJ0fokBomY8ScaH2D/B+U5o9ARxldJUdMqyBlJcA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-hex-encoding/-/util-hex-encoding-3.310.0.tgz", + "integrity": "sha512-sVN7mcCCDSJ67pI1ZMtk84SKGqyix6/0A1Ab163YKn+lFBQRMKexleZzpYzNGxYzmQS6VanP/cfU7NiLQOaSfA==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-locate-window": { - "version": "3.208.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.208.0.tgz", - "integrity": "sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-middleware": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.272.0.tgz", - "integrity": "sha512-Abw8m30arbwxqmeMMha5J11ESpHUNmCeSqSzE8/C4B8jZQtHY4kq7f+upzcNIQ11lsd+uzBEzNG3+dDRi0XOJQ==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-middleware/-/util-middleware-3.347.0.tgz", + "integrity": "sha512-8owqUA3ePufeYTUvlzdJ7Z0miLorTwx+rNol5lourGQZ9JXsVMo23+yGA7nOlFuXSGkoKpMOtn6S0BT2bcfeiw==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-retry": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.272.0.tgz", - "integrity": "sha512-Ngha5414LR4gRHURVKC9ZYXsEJhMkm+SJ+44wlzOhavglfdcKKPUsibz5cKY1jpUV7oKECwaxHWpBB8r6h+hOg==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-retry/-/util-retry-3.347.0.tgz", + "integrity": "sha512-NxnQA0/FHFxriQAeEgBonA43Q9/VPFQa8cfJDuT2A1YZruMasgjcltoZszi1dvoIRWSZsFTW42eY2gdOd0nffQ==", "requires": { - "@aws-sdk/service-error-classification": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/service-error-classification": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-uri-escape": { - "version": "3.201.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.201.0.tgz", - "integrity": "sha512-TeTWbGx4LU2c5rx0obHeDFeO9HvwYwQtMh1yniBz00pQb6Qt6YVOETVQikRZ+XRQwEyCg/dA375UplIpiy54mA==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-uri-escape/-/util-uri-escape-3.310.0.tgz", + "integrity": "sha512-drzt+aB2qo2LgtDoiy/3sVG8w63cgLkqFIa2NFlGpUgHFWTXkqtbgf4L5QdjRGKWhmZsnqkbtL7vkSWEcYDJ4Q==", "requires": { - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-user-agent-browser": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.272.0.tgz", - "integrity": "sha512-Lp5QX5bH6uuwBlIdr7w7OAcAI50ttyskb++yUr9i+SPvj6RI2dsfIBaK4mDg1qUdM5LeUdvIyqwj3XHjFKAAvA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.347.0.tgz", + "integrity": "sha512-ydxtsKVtQefgbk1Dku1q7pMkjDYThauG9/8mQkZUAVik55OUZw71Zzr3XO8J8RKvQG8lmhPXuAQ0FKAyycc0RA==", "requires": { - "@aws-sdk/types": "3.272.0", + "@aws-sdk/types": "3.347.0", "bowser": "^2.11.0", - "tslib": "^2.3.1" + "tslib": "^2.5.0" } }, "@aws-sdk/util-user-agent-node": { - "version": "3.272.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.272.0.tgz", - "integrity": "sha512-ljK+R3l+Q1LIHrcR+Knhk0rmcSkfFadZ8V+crEGpABf/QUQRg7NkZMsoe814tfBO5F7tMxo8wwwSdaVNNHtoRA==", + "version": "3.347.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.347.0.tgz", + "integrity": "sha512-6X0b9qGsbD1s80PmbaB6v1/ZtLfSx6fjRX8caM7NN0y/ObuLoX8LhYnW6WlB2f1+xb4EjaCNgpP/zCf98MXosw==", "requires": { - "@aws-sdk/node-config-provider": "3.272.0", - "@aws-sdk/types": "3.272.0", - "tslib": "^2.3.1" + "@aws-sdk/node-config-provider": "3.347.0", + "@aws-sdk/types": "3.347.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-utf8": { - "version": "3.254.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.254.0.tgz", - "integrity": "sha512-14Kso/eIt5/qfIBmhEL9L1IfyUqswjSTqO2mY7KOzUZ9SZbwn3rpxmtkhmATkRjD7XIlLKaxBkI7tU9Zjzj8Kw==", + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8/-/util-utf8-3.310.0.tgz", + "integrity": "sha512-DnLfFT8uCO22uOJc0pt0DsSNau1GTisngBCDw8jQuWT5CqogMJu4b/uXmwEqfj8B3GX6Xsz8zOd6JpRlPftQoA==", "requires": { - "@aws-sdk/util-buffer-from": "3.208.0", - "tslib": "^2.3.1" + "@aws-sdk/util-buffer-from": "3.310.0", + "tslib": "^2.5.0" } }, "@aws-sdk/util-utf8-browser": { @@ -13550,36 +13369,36 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dev": true, "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.0.tgz", - "integrity": "sha512-gMuZsmsgxk/ENC3O/fRw5QY8A9/uxQbbCEypnLIiYYc/qVJtEV7ouxC3EllIIwNzMqAQee5tanFabWsUOutS7g==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.22.3.tgz", + "integrity": "sha512-aNtko9OPOwVESUFp3MZfD8Uzxl7JzSeJpd7npIoxCasU37PFbAQRpKglkaKwlHOyeJdrREpo8TW8ldrkYWwvIQ==", "dev": true }, "@babel/core": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.0.tgz", - "integrity": "sha512-PuxUbxcW6ZYe656yL3EAhpy7qXKq0DmYsrJLpbB8XrsCP9Nm+XCg9XFMb5vIDliPD7+U/+M+QJlH17XOcB7eXA==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.1.tgz", + "integrity": "sha512-Hkqu7J4ynysSXxmAahpN1jjRwVJ+NdpraFLIWflgjpVob3KNyK3/tIUc7Q7szed8WMp0JNa7Qtd1E9Oo22F9gA==", "dev": true, "requires": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.0", - "@babel/helper-compilation-targets": "^7.20.7", - "@babel/helper-module-transforms": "^7.21.0", - "@babel/helpers": "^7.21.0", - "@babel/parser": "^7.21.0", - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.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", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -13602,38 +13421,25 @@ } }, "@babel/generator": { - "version": "7.21.1", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.1.tgz", - "integrity": "sha512-1lT45bAYlQhFn/BHivJs43AiW2rg3/UbLyShGfF3C0KmHvO5fSghWd5kBJy30kpRRucGzXStvnnCFniCR2kXAA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.22.3.tgz", + "integrity": "sha512-C17MW4wlk//ES/CJDL51kPNwl+qiBQyN7b9SKyVp11BLGFeSPoVaHrv+MNt8jwQFhQWowW88z1eeBx3pFz9v8A==", "dev": true, "requires": { - "@babel/types": "^7.21.0", + "@babel/types": "^7.22.3", "@jridgewell/gen-mapping": "^0.3.2", "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "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==", "dev": true, "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.22.0", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -13648,9 +13454,9 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "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==", "dev": true }, "@babel/helper-function-name": { @@ -13673,43 +13479,43 @@ } }, "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "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==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" } }, "@babel/helper-module-transforms": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.2.tgz", - "integrity": "sha512-79yj2AR4U/Oqq/WOV7Lx6hUjau1Zfo4cI+JLAVYeMV5XIlbOhmjEk5ulbTc9fMpmlojzZHkUUxAiK+UKn+hNQQ==", + "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==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-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.20.7", - "@babel/traverse": "^7.21.2", - "@babel/types": "^7.21.2" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.0" } }, "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "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==", "dev": true }, "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "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==", "dev": true, "requires": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" } }, "@babel/helper-split-export-declaration": { @@ -13722,9 +13528,9 @@ } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "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==", "dev": true }, "@babel/helper-validator-identifier": { @@ -13740,14 +13546,14 @@ "dev": true }, "@babel/helpers": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.0.tgz", - "integrity": "sha512-XXve0CBtOW0pd7MRzzmoyuSj0e3SEzj8pgyFxnTT1NJZL38BD1MK7yYrm8yefRPIDvNNe14xR4FdbHwpInD4rA==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.3.tgz", + "integrity": "sha512-jBJ7jWblbgr7r6wYZHMdIqKc73ycaTcCaWRq4/2LpuPHcx7xMlZvpGQkOYc9HeSjn6rcx15CPlgVcBtZ4WZJ2w==", "dev": true, "requires": { - "@babel/template": "^7.20.7", - "@babel/traverse": "^7.21.0", - "@babel/types": "^7.21.0" + "@babel/template": "^7.21.9", + "@babel/traverse": "^7.22.1", + "@babel/types": "^7.22.3" } }, "@babel/highlight": { @@ -13820,9 +13626,9 @@ } }, "@babel/parser": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.2.tgz", - "integrity": "sha512-URpaIJQwEkEC2T9Kn+Ai6Xe/02iNaVCuT/PtoRz3GPVJVDpPd7mLo+VddTbhCRU9TXqW5mSrQfXZyi8kDKOVpQ==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.3.tgz", + "integrity": "sha512-vrukxyW/ep8UD1UDzOYpTKQ6abgjFoeG6L+4ar9+c5TN9QnlqiOi6QK7LSR5ewm/ERyGkT/Ai6VboNrxhbr9Uw==", "dev": true }, "@babel/plugin-syntax-async-generators": { @@ -13871,12 +13677,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", + "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -13943,47 +13749,47 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "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==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/runtime": { - "version": "7.21.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", - "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.3.tgz", + "integrity": "sha512-XsDuspWKLUsxwCp6r7EhsExHtYfbe5oAGQ19kqngTdCPUoPQzOPdUbD/pB9PJiwb2ptYKQDjSJT3R6dC+EPqfQ==", "requires": { "regenerator-runtime": "^0.13.11" } }, "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", + "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" } }, "@babel/traverse": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.2.tgz", - "integrity": "sha512-ts5FFU/dSUPS13tv8XiEObDu9K+iagEKME9kAbaP7r0Y9KtZJZ+NGndDvWoRAYNpeWafbpFeki3q9QoMD6gxyw==", + "version": "7.22.1", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.1.tgz", + "integrity": "sha512-lAWkdCoUFnmwLBhIRLciFntGYsIIoC6vIbN8zrLPqBnJmPu7Z6nzqnKd7FsxQUNAvZfVZ0x6KdNvNp8zWIOHSQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.21.1", - "@babel/helper-environment-visitor": "^7.18.9", + "@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.21.2", - "@babel/types": "^7.21.2", + "@babel/parser": "^7.22.0", + "@babel/types": "^7.22.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -13997,12 +13803,12 @@ } }, "@babel/types": { - "version": "7.21.2", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.2.tgz", - "integrity": "sha512-3wRZSs7jiFaB8AjxiiD+VqN5DTG2iRvJGQ+qYFrs/654lg6kGTQWIOFjlBo5RaXuAZjBmP3+OQH4dmhqiiyYxw==", + "version": "7.22.3", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.3.tgz", + "integrity": "sha512-P3na3xIQHTKY4L0YOG7pM8M8uoUIB910WQaSiiMCZUC2Cy8XFEQONGABFnHWBa2gpGKODTAJcNhi5Zk0sLRrzg==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } @@ -14049,15 +13855,30 @@ "kuler": "^2.0.0" } }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true + }, "@eslint/eslintrc": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.0.tgz", - "integrity": "sha512-fluIaaV+GyV24CCu/ggiHdV+j4RNh85yQnAYS/G2mZODZgGmmlrgCydjUcV3YvxCm9x8nMAfThsqTni4KiXT4A==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -14067,15 +13888,15 @@ } }, "@eslint/js": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.35.0.tgz", - "integrity": "sha512-JXdzbRiWclLVoD8sNUjR443VVlYqiYmDVT6rGUEIEHU5YJW0gaVZwV2xgM7D4arkvASqD0IlLUVjHiFuxaftRw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true }, "@godaddy/terminus": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.11.2.tgz", - "integrity": "sha512-e/kbOWpGKME42eltM/wXM3RxSUOrfureZxEd6Dt6NXyFoJ7E8lnmm7znXydJsL3B7ky4HRFZI+eHrep54NZbeQ==", + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/@godaddy/terminus/-/terminus-4.12.0.tgz", + "integrity": "sha512-zbl6gKxPAnAoAAGCyRN1kOMHTXgiW3C09w8McLKZWSSHQlsiRZlMZzBwSv1aK9PaRU25w80cnOlt3ow+uQwR1Q==", "requires": { "stoppable": "^1.1.0" } @@ -14193,123 +14014,123 @@ "dev": true }, "@jest/console": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.4.3.tgz", - "integrity": "sha512-W/o/34+wQuXlgqlPYTansOSiBnuxrTv61dEVkA6HNmpcgHLUjfaUbdqt6oVvOzaawwo9IdW9QOtMgQ1ScSZC4A==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.5.0.tgz", + "integrity": "sha512-NEpkObxPwyw/XxZVLPmAGKE89IQRp4puc6IQRPru6JKd1M3fW9v1xM1AnzIJE65hbCkzQAdnL8P47e9hzhiYLQ==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0" } }, "@jest/core": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.4.3.tgz", - "integrity": "sha512-56QvBq60fS4SPZCuM7T+7scNrkGIe7Mr6PVIXUpu48ouvRaWOFqRPV91eifvFM0ay2HmfswXiGf97NGUN5KofQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.5.0.tgz", + "integrity": "sha512-28UzQc7ulUrOQw1IsN/kv1QES3q2kkbl/wGslyhAclqZ/8cMdB5M68BffkIdSJgKBUt50d3hbwJ92XESlE7LiQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/reporters": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@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", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "ci-info": "^3.2.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.4.3", - "jest-config": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-message-util": "^29.4.3", + "jest-changed-files": "^29.5.0", + "jest-config": "^29.5.0", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-resolve-dependencies": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", - "jest-watcher": "^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", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-ansi": "^6.0.0" } }, "@jest/environment": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.4.3.tgz", - "integrity": "sha512-dq5S6408IxIa+lr54zeqce+QgI+CJT4nmmA+1yzFgtcsGK8c/EyiUb9XQOgz3BMKrRDfKseeOaxj2eO8LlD3lA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.5.0.tgz", + "integrity": "sha512-5FXw2+wD29YU1d4I2htpRX7jYnAyTRjP2CsXQdo9SAM8g3ifxWPSV0HnClSn71xwctr0U3oZIIH+dtbfmnbXVQ==", "dev": true, "requires": { - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3" + "jest-mock": "^29.5.0" } }, "@jest/expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-iktRU/YsxEtumI9zsPctYUk7ptpC+AVLLk1Ax3AsA4g1C+8OOnKDkIQBDHtD5hA/+VtgMd5AWI5gNlcAlt2vxQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-PueDR2HGihN3ciUNGr4uelropW7rqUfTiOn+8u0leg/42UhblPxHkfoh0Ruu3I9Y1962P3u2DY4+h7GVTSVU6g==", "dev": true, "requires": { - "expect": "^29.4.3", - "jest-snapshot": "^29.4.3" + "expect": "^29.5.0", + "jest-snapshot": "^29.5.0" } }, "@jest/expect-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.4.3.tgz", - "integrity": "sha512-/6JWbkxHOP8EoS8jeeTd9dTfc9Uawi+43oLKHfp6zzux3U2hqOOVnV3ai4RpDYHOccL6g+5nrxpoc8DmJxtXVQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.5.0.tgz", + "integrity": "sha512-fmKzsidoXQT2KwnrwE0SQq3uj8Z763vzR8LnLBwC2qYWEFpjX8daRsk6rHUM1QvNlEW/UJXNXm59ztmJJWs2Mg==", "dev": true, "requires": { "jest-get-type": "^29.4.3" } }, "@jest/fake-timers": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.4.3.tgz", - "integrity": "sha512-4Hote2MGcCTWSD2gwl0dwbCpBRHhE6olYEuTj8FMowdg3oQWNKr2YuxenPQYZ7+PfqPY1k98wKDU4Z+Hvd4Tiw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.5.0.tgz", + "integrity": "sha512-9ARvuAAQcBwDAqOnglWq2zwNIRUDtk/SCkp/ToGEhFv5r86K21l+VEs0qNTaXtyiY0lEePl3kylijSYJQqdbDg==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@sinonjs/fake-timers": "^10.0.2", "@types/node": "*", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, "@jest/globals": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.4.3.tgz", - "integrity": "sha512-8BQ/5EzfOLG7AaMcDh7yFCbfRLtsc+09E1RQmRBI4D6QQk4m6NSK/MXo+3bJrBN0yU8A2/VIcqhvsOLFmziioA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.5.0.tgz", + "integrity": "sha512-S02y0qMWGihdzNbUiqSAiKSpSozSuHX5UYc7QbnHP+D9Lyw8DgGGCinrN9uSuHPeKgSSzvPom2q1nAtBvUsvPQ==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/types": "^29.4.3", - "jest-mock": "^29.4.3" + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/types": "^29.5.0", + "jest-mock": "^29.5.0" } }, "@jest/reporters": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.4.3.tgz", - "integrity": "sha512-sr2I7BmOjJhyqj9ANC6CTLsL4emMoka7HkQpcoMRlhCbQJjz2zsRzw0BDPiPyEFDXAbxKgGFYuQZiSJ1Y6YoTg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.5.0.tgz", + "integrity": "sha512-D05STXqj/M8bP9hQNSICtPqz97u7ffGzZu+9XLucXhkOFBqKcXe04JLZOgIekOxdb73MAoBUFnqvf7MCpKk5OA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.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", "@types/node": "*", "chalk": "^4.0.0", @@ -14322,9 +14143,9 @@ "istanbul-lib-report": "^3.0.0", "istanbul-lib-source-maps": "^4.0.0", "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "slash": "^3.0.0", "string-length": "^4.0.1", "strip-ansi": "^6.0.0", @@ -14352,46 +14173,46 @@ } }, "@jest/test-result": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.4.3.tgz", - "integrity": "sha512-Oi4u9NfBolMq9MASPwuWTlC5WvmNRwI4S8YrQg5R5Gi47DYlBe3sh7ILTqi/LGrK1XUE4XY9KZcQJTH1WJCLLA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.5.0.tgz", + "integrity": "sha512-fGl4rfitnbfLsrfx1uUpDEESS7zM8JdgZgOCQuxQvL1Sn/I6ijeAVQWGfXI9zb1i9Mzo495cIpVZhA0yr60PkQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/console": "^29.5.0", + "@jest/types": "^29.5.0", "@types/istanbul-lib-coverage": "^2.0.0", "collect-v8-coverage": "^1.0.0" } }, "@jest/test-sequencer": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.4.3.tgz", - "integrity": "sha512-yi/t2nES4GB4G0mjLc0RInCq/cNr9dNwJxcGg8sslajua5Kb4kmozAc+qPLzplhBgfw1vLItbjyHzUN92UXicw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.5.0.tgz", + "integrity": "sha512-yPafQEcKjkSfDXyvtgiV4pevSeyuA6MQr6ZIdVkWJly9vkqjnFfcfhRQqpD5whjoU8EORki752xQmjaqoFjzMQ==", "dev": true, "requires": { - "@jest/test-result": "^29.4.3", + "@jest/test-result": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "slash": "^3.0.0" } }, "@jest/transform": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.4.3.tgz", - "integrity": "sha512-8u0+fBGWolDshsFgPQJESkDa72da/EVwvL+II0trN2DR66wMwiQ9/CihaGfHdlLGFzbBZwMykFtxuwFdZqlKwg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "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.4.3", + "jest-haste-map": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", @@ -14399,9 +14220,9 @@ } }, "@jest/types": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.4.3.tgz", - "integrity": "sha512-bPYfw8V65v17m2Od1cv44FH+SiKW7w2Xu7trhcdTLUmSv85rfKsP+qXSjO4KGJr4dtPSzl/gvslZBXctf1qGEA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "requires": { "@jest/schemas": "^29.4.3", @@ -14413,13 +14234,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, "@jridgewell/resolve-uri": { @@ -14435,25 +14257,33 @@ "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", "dev": true }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dev": true, "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==", + "dev": true + } } }, "@juanelas/base64": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.0.5.tgz", - "integrity": "sha512-gTIElNo4ohMcYUZzol/Hb6DYJzphxl0b1B4egJJ+JiqxqcOcWx4XLMAB+lhWuMsMX3uR1oc5hwPusU3lgc1FkQ==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@juanelas/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-mr2pfRQpWap0Uq4tlrCgp3W+Yjx1/Bpq4QJsYeAQUh1mExgyQvXz7xUhmYT2HcLLspuAL5dpnos8P2QhaCSXsQ==" }, "@mapbox/node-pre-gyp": { "version": "1.0.10", @@ -14595,9 +14425,9 @@ } }, "@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "requires": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -14619,9 +14449,9 @@ } }, "@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "requires": { "@octokit/request": "^6.0.0", "@octokit/types": "^9.0.0", @@ -14629,16 +14459,17 @@ } }, "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" }, "@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "requires": { - "@octokit/types": "^9.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" } }, "@octokit/plugin-request-log": { @@ -14648,18 +14479,18 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "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==", "requires": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "requires": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -14680,24 +14511,34 @@ } }, "@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "requires": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" } }, + "@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" + }, "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "requires": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^17.2.0" } }, + "@phc/format": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@phc/format/-/format-1.0.0.tgz", + "integrity": "sha512-m7X9U6BG2+J+R1lSOdCiITLLrxm+cWlNI3HUFA92oLO77ObGNzaKdh8pMLqdZcshtkKuV84olNNXDfMc4FezBQ==" + }, "@posthog/plugin-scaffold": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/@posthog/plugin-scaffold/-/plugin-scaffold-1.4.2.tgz", @@ -14761,44 +14602,56 @@ "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" }, - "@sentry/node": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.40.0.tgz", - "integrity": "sha512-S2pcLBUsCg3+WYlyQbXKPey3H1yaZPt9fpJTPAoabbidYXweBAbtFjSCRwPFwCQMzWusWxlYEwWRT77C07pHVg==", + "@sentry-internal/tracing": { + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.53.1.tgz", + "integrity": "sha512-a4H4rvVdz0XDGgNfRqc7zg6rMt2P1P05xBmgfIfztYy94Vciw1QMdboNiT7einr8ra8wogdEaK4Pe2AzYAPBJQ==", "requires": { - "@sentry/core": "7.40.0", - "@sentry/types": "7.40.0", - "@sentry/utils": "7.40.0", + "@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": { + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.53.1.tgz", + "integrity": "sha512-DAH8IJNORJJ7kQLqsZuhMkN6cwJjXzFuuUoZor7IIDHIHjtl51W+2F3Stg3+I3ZoKDfJfUNKqhipk2WZjG0FBg==", + "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/node": { + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.53.1.tgz", + "integrity": "sha512-B4ax8sRd54xj4ad+4eY2EOKNt0Mh1NjuLW1zUKS8HW3h0bmuaDFzGuhEVvEY5H4SaV6tZKj1c0dvnMnyUbYkhA==", + "requires": { + "@sentry-internal/tracing": "7.53.1", + "@sentry/core": "7.53.1", + "@sentry/types": "7.53.1", + "@sentry/utils": "7.53.1", "cookie": "^0.4.1", "https-proxy-agent": "^5.0.0", "lru_map": "^0.3.3", "tslib": "^1.9.3" }, "dependencies": { - "@sentry/core": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.40.0.tgz", - "integrity": "sha512-OPAobQG0GTY++r5LWUcOA1lS+2TY2Lmw/i5s4kL9WbY+f08dbLNEGNBObY7/V98OL4f7OG+nWaPFybgM7kqUTQ==", - "requires": { - "@sentry/types": "7.40.0", - "@sentry/utils": "7.40.0", - "tslib": "^1.9.3" - } - }, - "@sentry/types": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.40.0.tgz", - "integrity": "sha512-dIbqBenbmDx1F8pvfC11C88J83ecwumUhV+YOIxcmVd1fmlPF2hXWZ01+NTkTDkCu341sJx4wPQogByFy8FwGA==" - }, - "@sentry/utils": { - "version": "7.40.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.40.0.tgz", - "integrity": "sha512-ZdCbTpAXPiVVfvNJVftnDhsctOui71MDUhVIdLkgg4Cuic+WHGPRmmZ+H6uZdp7vRaeB+Uvnn5+t2iSAVo/mAA==", - "requires": { - "@sentry/types": "7.40.0", - "tslib": "^1.9.3" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -14807,40 +14660,27 @@ } }, "@sentry/tracing": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.39.0.tgz", - "integrity": "sha512-bSRdUMzp/n54J+Qf4hHC4WVvdv4vZEv3NEbNNsnIZNAhnVAq6QB9VzsGRJZ12PqxJU3StDuqLiZFVOmGxETCkQ==", + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.53.1.tgz", + "integrity": "sha512-1lpys/e19ee2gDTkcgIXyFNJySEqxdIxlu3Q1Oj+V0ORXVBfA9kFap2fHPWASaDJvmy1zpgGKlbzCpr+IEyfYQ==", "requires": { - "@sentry/core": "7.39.0", - "@sentry/types": "7.39.0", - "@sentry/utils": "7.39.0", + "@sentry-internal/tracing": "7.53.1" + } + }, + "@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==" + }, + "@sentry/utils": { + "version": "7.53.1", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.53.1.tgz", + "integrity": "sha512-DKJA1LSUOEv4KOR828MzVuLh+drjeAgzyKgN063OEKmnirgjgRgNNS8wUgwpG0Tn2k6ANZGCwrdfzPeSBxshKg==", + "requires": { + "@sentry/types": "7.53.1", "tslib": "^1.9.3" }, "dependencies": { - "@sentry/core": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.39.0.tgz", - "integrity": "sha512-45WJIcWWCQnZ8zhHtcrkJjQ4YydmzMWY4pmRuBG7Qp+zrCT6ISoyODcjY+SCHFdvXkiYFi8+bFZa1qG3YQnnYw==", - "requires": { - "@sentry/types": "7.39.0", - "@sentry/utils": "7.39.0", - "tslib": "^1.9.3" - } - }, - "@sentry/types": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.39.0.tgz", - "integrity": "sha512-5Y83Y8O3dT5zT2jTKEIPMcpn5lUm05KRMaCXuw0sRsv4r9TbBUKeqiSU1LjowT8rB/XNy8m7DHav8+NmogPaJw==" - }, - "@sentry/utils": { - "version": "7.39.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.39.0.tgz", - "integrity": "sha512-/ZxlPgm1mGgmuMckCTc9iyqDuFTEYNEoMB53IjVFz8ann+37OiWB7Py/QV1rEEsv3xKrGbA8thhRhV9E1sjTlQ==", - "requires": { - "@sentry/types": "7.39.0", - "tslib": "^1.9.3" - } - }, "tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", @@ -14855,21 +14695,38 @@ "dev": true }, "@sinonjs/commons": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-2.0.0.tgz", - "integrity": "sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, "requires": { "type-detect": "4.0.8" } }, "@sinonjs/fake-timers": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.0.2.tgz", - "integrity": "sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==", + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.2.0.tgz", + "integrity": "sha512-OPwQlEdg40HAj5KNF8WW6q2KG4Z+cBCZb3m4ninfTZKaBmbIJodviQsDBoYMPHkOyJJMHnOJo5j2+LKDOhOACg==", "dev": true, "requires": { - "@sinonjs/commons": "^2.0.0" + "@sinonjs/commons": "^3.0.0" + } + }, + "@smithy/protocol-http": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.0.1.tgz", + "integrity": "sha512-9OrEn0WfOVtBNYJUjUAn9AOiJ4lzERCJJ/JeZs8E6yajTGxBaFRxUnNBHiNqoDJVg076hY36UmEnPx7xXrvUSg==", + "requires": { + "@smithy/types": "^1.0.0", + "tslib": "^2.5.0" + } + }, + "@smithy/types": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.0.0.tgz", + "integrity": "sha512-kc1m5wPBHQCTixwuaOh9vnak/iJm21DrSf9UK6yDE5S3mQQ4u11pqAUiKWnlrZnYkeLfAI9UEHj9OaMT1v5Umg==", + "requires": { + "tslib": "^2.5.0" } }, "@tsconfig/node10": { @@ -14891,15 +14748,15 @@ "dev": true }, "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, "@types/babel__core": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", - "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", + "version": "7.20.1", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.1.tgz", + "integrity": "sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==", "dev": true, "requires": { "@babel/parser": "^7.20.7", @@ -14929,12 +14786,12 @@ } }, "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.0.tgz", + "integrity": "sha512-TBOjqAGf0hmaqRwpii5LLkJLg7c6OMm4nHLmpsUxwk9bBHtoTC6dAHdVWdGv4TBxj2CZOZY8Xfq8WmfoVi7n4Q==", "dev": true, "requires": { - "@babel/types": "^7.3.0" + "@babel/types": "^7.20.7" } }, "@types/bcrypt": { @@ -15013,14 +14870,15 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.33", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.33.tgz", - "integrity": "sha512-TPBqmR/HRYI3eC2E5hmiivIzv+bidAfXofM+sbonAGvyDhySGw9/PQZFt2BLOrjUUR++4eJVpx6KnLQK1Fk9tA==", + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dev": true, "requires": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "@types/graceful-fs": { @@ -15057,9 +14915,9 @@ } }, "@types/jest": { - "version": "29.4.0", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.4.0.tgz", - "integrity": "sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==", + "version": "29.5.1", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.1.tgz", + "integrity": "sha512-tEuVcHrpaixS36w7hpsfLBLpjtMRJUE09/MHXn923LOVojDwyC14cWcfc0rDs0VEfUyYmt/+iX1kxxp+gZMcaQ==", "dev": true, "requires": { "expect": "^29.0.0", @@ -15067,9 +14925,9 @@ } }, "@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", + "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", "dev": true }, "@types/jsonwebtoken": { @@ -15087,9 +14945,9 @@ "integrity": "sha512-BqI9B92u+cM3ccp8mpHf+HzJ8fBlRwdmyd6+fz3p99m3V6ifT5O3zmOMi612PGkpeFeG/G6loxUnzlDNhfjPSA==" }, "@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==", + "version": "4.14.195", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", + "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", "dev": true }, "@types/long": { @@ -15098,25 +14956,34 @@ "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" }, "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "@types/node": { - "version": "18.14.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.2.tgz", - "integrity": "sha512-1uEQxww3DaghA0RxqHx0O0ppVlo43pJhepY51OxuQIKHpjbnYLA7vcdwioNPzIqmC2u3I/dmylcqjlh0e7AyUA==" + "version": "18.16.16", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.16.tgz", + "integrity": "sha512-NpaM49IGQQAUlBhHMF82QH80J08os4ZmyF9MkpCzWAGuOHqE4gTEbhzd7L3l5LmWuZ6E0OiC1FweQ4tsiW35+g==" }, "@types/nodemailer": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.7.tgz", - "integrity": "sha512-f5qCBGAn/f0qtRcd4SEn88c8Fp3Swct1731X4ryPKqS61/A3LmmzN8zaEz7hneJvpjFbUUgY7lru/B/7ODTazg==", + "version": "6.4.8", + "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.8.tgz", + "integrity": "sha512-oVsJSCkqViCn8/pEu2hfjwVO+Gb3e+eTWjg3PcjeFKRItfKpKwHphQqbYmPQrlMk+op7pNNWPbsJIEthpFN/OQ==", "dev": true, "requires": { "@types/node": "*" } }, + "@types/passport": { + "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/prettier": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", @@ -15136,11 +15003,21 @@ "dev": true }, "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/serve-static": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", @@ -15158,9 +15035,9 @@ "dev": true }, "@types/superagent": { - "version": "4.1.16", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.16.tgz", - "integrity": "sha512-tLfnlJf6A5mB6ddqF159GqcDizfzbMUB1/DeT59/wBNqzRTNNKsaw79A/1TZ84X+f/EwWH8FeuSkjlCLyqS/zQ==", + "version": "4.1.18", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-4.1.18.tgz", + "integrity": "sha512-LOWgpacIV8GHhrsQU+QMZuomfqXiqzz3ILLkCtKx3Us6AmomFViuzKT9D693QTKgyut2oCytMG8/efOop+DB+w==", "dev": true, "requires": { "@types/cookiejar": "*", @@ -15212,9 +15089,9 @@ } }, "@types/yargs": { - "version": "17.0.22", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.22.tgz", - "integrity": "sha512-pet5WJ9U8yPVRhkwuEIp5ktAeAqRZOq4UdAyWLWzxbtpyXnzbtLdKiXAjJzi/KLmPGS9wk86lUFWZFN6sISo4g==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -15227,132 +15104,71 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.54.0.tgz", - "integrity": "sha512-+hSN9BdSr629RF02d7mMtXhAJvDTyCbprNYJKrXETlul/Aml6YZwd90XioVbjejQeHbb3R8Dg0CkRgoJDxo8aw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.7.tgz", + "integrity": "sha512-BL+jYxUFIbuYwy+4fF86k5vdT9lT0CNJ6HtwrIvGh0PhH8s0yy5rjaKH2fDCrz5ITHy07WCzVGNvAmjJh4IJFA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.54.0", - "@typescript-eslint/type-utils": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@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", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" - } - }, - "@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - } - } } }, "@typescript-eslint/parser": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.53.0.tgz", - "integrity": "sha512-MKBw9i0DLYlmdOb3Oq/526+al20AJZpANdT6Ct9ffxcV8nKCHz63t/S0IhlTFNsBIHJv+GY5SFJ0XfqVeydQrQ==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.7.tgz", + "integrity": "sha512-VhpsIEuq/8i5SF+mPg9jSdIwgMBBp0z9XqjiEay+81PYLJuroN+ET1hM5IhkiYMJd9MkTz8iJLt7aaGAgzWUbQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.53.0", - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/typescript-estree": "5.53.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.53.0.tgz", - "integrity": "sha512-Opy3dqNsp/9kBBeCPhkCNR7fmdSQqA+47r21hr9a14Bx0xnkElEQmhoHga+VoaoQ6uDHjDKmQPIYcUcKJifS7w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.7.tgz", + "integrity": "sha512-FL6hkYWK9zBGdxT2wWEd2W8ocXMu3K94i3gvMrjXpx+koFYdYV7KprKfirpgY34vTGzEPPuKoERpP8kD5h7vZQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0" + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7" } }, "@typescript-eslint/type-utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.54.0.tgz", - "integrity": "sha512-WI+WMJ8+oS+LyflqsD4nlXMsVdzTMYTxl16myXPaCXnSgc7LWwMsjxQFZCK/rVmTZ3FN71Ct78ehO9bRC7erYQ==", + "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==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.54.0", - "@typescript-eslint/utils": "5.54.0", + "@typescript-eslint/typescript-estree": "5.59.7", + "@typescript-eslint/utils": "5.59.7", "debug": "^4.3.4", "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - } - } } }, "@typescript-eslint/types": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.53.0.tgz", - "integrity": "sha512-5kcDL9ZUIP756K6+QOAfPkigJmCPHcLN7Zjdz76lQWWDdzfOhZDTj1irs6gPBKiXx5/6O3L0+AvupAut3z7D2A==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.7.tgz", + "integrity": "sha512-UnVS2MRRg6p7xOSATscWkKjlf/NDKuqo5TdbWck6rIRZbmKpVNTLALzNvcjIfHBE7736kZOFc/4Z3VcZwuOM/A==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.53.0.tgz", - "integrity": "sha512-eKmipH7QyScpHSkhbptBBYh9v8FxtngLquq292YTEQ1pxVs39yFBlLC1xeIZcPPz1RWGqb7YgERJRGkjw8ZV7w==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.7.tgz", + "integrity": "sha512-4A1NtZ1I3wMN2UGDkU9HMBL+TIQfbrh4uS0WDMMpf3xMRursDbqEf1ahh6vAAe3mObt8k3ZATnezwG4pdtWuUQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", - "@typescript-eslint/visitor-keys": "5.53.0", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/visitor-keys": "5.59.7", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -15361,71 +15177,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.54.0.tgz", - "integrity": "sha512-cuwm8D/Z/7AuyAeJ+T0r4WZmlnlxQ8wt7C7fLpFlKMR+dY6QO79Cq1WpJhvZbMA4ZeZGHiRWnht7ZJ8qkdAunw==", + "version": "5.59.7", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.7.tgz", + "integrity": "sha512-yCX9WpdQKaLufz5luG4aJbOpdXf/fjwGMcLFXZVPUz3QqLirG5QcwwnIHNf8cjLjxK4qtzTO8udUtMQSAToQnQ==", "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.54.0", - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/typescript-estree": "5.54.0", + "@typescript-eslint/scope-manager": "5.59.7", + "@typescript-eslint/types": "5.59.7", + "@typescript-eslint/typescript-estree": "5.59.7", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" - }, - "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.54.0.tgz", - "integrity": "sha512-VTPYNZ7vaWtYna9M4oD42zENOBrb+ZYyCNdFs949GcN8Miwn37b8b7eMj+EZaq7VK9fx0Jd+JhmkhjFhvnovhg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0" - } - }, - "@typescript-eslint/types": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.54.0.tgz", - "integrity": "sha512-nExy+fDCBEgqblasfeE3aQ3NuafBUxZxgxXcYfzYRZFHdVvk5q60KhCSkG0noHgHRo/xQ/BOzURLZAafFpTkmQ==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.54.0.tgz", - "integrity": "sha512-X2rJG97Wj/VRo5YxJ8Qx26Zqf0RRKsVHd4sav8NElhbZzhpBI8jU54i6hfo9eheumj4oO4dcRN1B/zIVEqR/MQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "@typescript-eslint/visitor-keys": "5.54.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.54.0.tgz", - "integrity": "sha512-xu4wT7aRCakGINTLGeyGqDn+78BwFlggwBjnHa1ar/KaGagnmwLYmlrXIrgAaQ3AE1Vd6nLfKASm7LrFHNbKGA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.54.0", - "eslint-visitor-keys": "^3.3.0" - } - } } }, "@typescript-eslint/visitor-keys": { - "version": "5.53.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.53.0.tgz", - "integrity": "sha512-JqNLnX3leaHFZEN0gCh81sIvgrp/2GOACZNgO4+Tkf64u51kTpAyWFOY8XHx8XuXr3N2C9zgPPHtcpMg6z1g0w==", + "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==", "dev": true, "requires": { - "@typescript-eslint/types": "5.53.0", + "@typescript-eslint/types": "5.59.7", "eslint-visitor-keys": "^3.3.0" } }, @@ -15543,6 +15316,16 @@ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", "dev": true }, + "argon2": { + "version": "0.30.3", + "resolved": "https://registry.npmjs.org/argon2/-/argon2-0.30.3.tgz", + "integrity": "sha512-DoH/kv8c9127ueJSBxAVJXinW9+EuPA3EMUxoV2sAY1qDE5H9BjTyVF/aD2XyHqbqUWabgBkIfcP3ZZuGhbJdg==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.10", + "@phc/format": "^1.0.0", + "node-addon-api": "^5.0.0" + } + }, "argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -15597,9 +15380,9 @@ "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==" }, "aws-sdk": { - "version": "2.1324.0", - "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1324.0.tgz", - "integrity": "sha512-7T9Jn6qtzCANdqRcdhxZ9Fx31/U+h/VPFxEU3+sFEnC7WtGtRlgmsJOY2lIdFKRXkHYT3Jw5MqDyjnb/i1QqbA==", + "version": "2.1386.0", + "resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1386.0.tgz", + "integrity": "sha512-bmUvpNRR4x1YvTaAm7WK/2lSNVPrNuiYlleU47GA5Xskh8PKaWedGHvGinH2YwhC720hM0Qc4f4/snUPGJ0eYg==", "requires": { "buffer": "4.9.2", "events": "1.1.1", @@ -15610,7 +15393,7 @@ "url": "0.10.3", "util": "^0.12.4", "uuid": "8.0.0", - "xml2js": "0.4.19" + "xml2js": "0.5.0" }, "dependencies": { "uuid": { @@ -15621,9 +15404,9 @@ } }, "axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -15631,24 +15414,24 @@ } }, "axios-retry": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.4.0.tgz", - "integrity": "sha512-VdgaP+gHH4iQYCCNUWF2pcqeciVOdGrBBAYUfTY+wPcO5Ltvp/37MLFNCmJKo7Gj3SHvCSdL8ouI1qLYJN3liA==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-3.5.0.tgz", + "integrity": "sha512-g48qNrLX30VU6ECWltpFCPegKK6dWzMDYv2o83W2zUL/Zh/SLXbT6ksGoKqYZHtghzqeeXhZBcSXJkO1fPbCcw==", "requires": { "@babel/runtime": "^7.15.4", "is-retry-allowed": "^2.2.0" } }, "babel-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.4.3.tgz", - "integrity": "sha512-o45Wyn32svZE+LnMVWv/Z4x0SwtLbh4FyGcYtR20kIWd+rdrDZ9Fzq8Ml3MYLD+mZvEdzCjZsCnYZ2jpJyQ+Nw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.5.0.tgz", + "integrity": "sha512-mA4eCDh5mSo2EcA9xQjVTpmbbNk32Zb3Q3QFQsNhaK56Q+yoXowzFodLux30HRgyOho5rsQ6B0P9QpMkvvnJ0Q==", "dev": true, "requires": { - "@jest/transform": "^29.4.3", + "@jest/transform": "^29.5.0", "@types/babel__core": "^7.1.14", "babel-plugin-istanbul": "^6.1.1", - "babel-preset-jest": "^29.4.3", + "babel-preset-jest": "^29.5.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "slash": "^3.0.0" @@ -15668,9 +15451,9 @@ } }, "babel-plugin-jest-hoist": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.4.3.tgz", - "integrity": "sha512-mB6q2q3oahKphy5V7CpnNqZOCkxxZ9aokf1eh82Dy3jQmg4xvM1tGrh5y6BQUJh4a3Pj9+eLfwvAZ7VNKg7H8Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz", + "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==", "dev": true, "requires": { "@babel/template": "^7.3.3", @@ -15700,12 +15483,12 @@ } }, "babel-preset-jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.4.3.tgz", - "integrity": "sha512-gWx6COtSuma6n9bw+8/F+2PCXrIgxV/D1TJFnp6OyBK2cxPWg0K9p/sriNYeifKjpUkMViWQ09DSWtzJQRETsw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz", + "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==", "dev": true, "requires": { - "babel-plugin-jest-hoist": "^29.4.3", + "babel-plugin-jest-hoist": "^29.5.0", "babel-preset-current-node-syntax": "^1.0.0" } }, @@ -15719,6 +15502,11 @@ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, "bcrypt": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", @@ -15734,11 +15522,11 @@ "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==" }, "bigint-conversion": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.3.0.tgz", - "integrity": "sha512-U4Yzg8ygZ3m78n9weKP/6NMxN/98Pdsw6YdnDYgQO8fffL7ila31fCZIy5lCMswr4kEcyl8bGHltcHT0QdG/MQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/bigint-conversion/-/bigint-conversion-2.4.1.tgz", + "integrity": "sha512-/DTRevseMZoqN4KLkN5BryOiom0KbwYajiXG5Vo+ZcEPAO0WBZyZoYyDZSgfeq/v/oegLo9bjdndDBlExvAhBQ==", "requires": { - "@juanelas/base64": "^1.0.1" + "@juanelas/base64": "^1.1.2" } }, "binary-extensions": { @@ -15747,6 +15535,44 @@ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, + "bl": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz", + "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -15805,15 +15631,15 @@ } }, "browserslist": { - "version": "4.21.5", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", - "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "version": "4.21.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.6.tgz", + "integrity": "sha512-PF07dKGXKR+/bljJzCB6rAYtHEu21TthLxmJagtQizx+rwiqdRDBO5971Xu1N7MgcMLi4+mr4Cnl76x7O3DHtA==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001449", - "electron-to-chromium": "^1.4.284", - "node-releases": "^2.0.8", - "update-browserslist-db": "^1.0.10" + "caniuse-lite": "^1.0.30001489", + "electron-to-chromium": "^1.4.411", + "node-releases": "^2.0.12", + "update-browserslist-db": "^1.0.11" } }, "bs-logger": { @@ -15923,9 +15749,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001458", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001458.tgz", - "integrity": "sha512-lQ1VlUUq5q9ro9X+5gOEyH7i3vm+AYVT1WDCVB69XOZ17KZRhnZ9J0Sqz7wTHQaLBJccNCHq8/Ww5LlOIZbB0w==", + "version": "1.0.30001489", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", + "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", "dev": true }, "chalk": { @@ -16008,6 +15834,11 @@ "wrap-ansi": "^7.0.0" } }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -16159,8 +15990,7 @@ "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==" }, "cors": { "version": "2.8.5", @@ -16240,9 +16070,9 @@ "dev": true }, "deepmerge": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.0.tgz", - "integrity": "sha512-z2wJZXrmeHdvYJp/Ux55wIjqo81G5Bp4c+oELTW+7ar6SogWHajt5a9gO3s3IDaGSAXjDk0vlQKN3rms8ab3og==" + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" }, "delayed-stream": { "version": "1.0.0", @@ -16254,6 +16084,11 @@ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" }, + "denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -16339,9 +16174,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "electron-to-chromium": { - "version": "1.4.311", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz", - "integrity": "sha512-RoDlZufvrtr2Nx3Yx5MB8jX3aHIxm8nRWPJm3yVvyHmyKaRvn90RjzB6hNnt0AkhS3IInJdyRfQb4mWhPvUjVw==", + "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==", "dev": true }, "emittery": { @@ -16392,13 +16227,15 @@ "dev": true }, "eslint": { - "version": "8.35.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.35.0.tgz", - "integrity": "sha512-BxAf1fVL7w+JLRQhWl2pzGeSiGqbWumV4WNvc9Rhp6tiCtm4oHnyPBSEtMGZwrQgudFQ+otqzWoPB7x+hxoWsw==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { - "@eslint/eslintrc": "^2.0.0", - "@eslint/js": "8.35.0", + "@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", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -16408,10 +16245,9 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -16419,13 +16255,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "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", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -16433,16 +16268,15 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" }, "dependencies": { "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -16467,38 +16301,21 @@ "estraverse": "^4.1.1" } }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true }, "espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" } }, "esprima": { @@ -16508,9 +16325,9 @@ "dev": true }, "esquery": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.2.tgz", - "integrity": "sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -16587,16 +16404,16 @@ "dev": true }, "expect": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/expect/-/expect-29.4.3.tgz", - "integrity": "sha512-uC05+Q7eXECFpgDrHdXA4k2rpMyStAYPItEDLyQDo5Ta7fVkJnNA/4zh/OIVkVVNZ1oOK1PipQoyNjuZ6sz6Dg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.5.0.tgz", + "integrity": "sha512-yM7xqUrCO2JdpFo4XpM82t+PJBFybdqoQuJLDGeDX2ij8NZzqRHyu3Hp188/JX7SWqud+7t4MUdvcgGBICMHZg==", "dev": true, "requires": { - "@jest/expect-utils": "^29.4.3", + "@jest/expect-utils": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3" + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0" } }, "express": { @@ -16657,6 +16474,12 @@ } } }, + "express-async-errors": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", + "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", + "requires": {} + }, "express-rate-limit": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-6.7.0.tgz", @@ -16954,12 +16777,13 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -17037,9 +16861,9 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "grapheme-splitter": { @@ -17048,6 +16872,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -17074,6 +16904,11 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==" + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -17198,11 +17033,12 @@ "dev": true }, "infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", + "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", "requires": { "axios": "^1.3.3", + "dotenv": "^16.0.3", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" } @@ -17277,9 +17113,9 @@ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dev": true, "requires": { "has": "^1.0.3" @@ -17429,21 +17265,21 @@ } }, "jest": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.4.3.tgz", - "integrity": "sha512-XvK65feuEFGZT8OO0fB/QAQS+LGHvQpaadkH5p47/j3Ocqq3xf2pK9R+G0GzgfuhXVxEv76qCOOcMb5efLk6PA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.5.0.tgz", + "integrity": "sha512-juMg3he2uru1QoXX078zTa7pO85QyB9xajZc6bU+d9yEGwrKX6+vGmJQ3UdVZsvTEUARIdObzH68QItim6OSSQ==", "dev": true, "requires": { - "@jest/core": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/types": "^29.5.0", "import-local": "^3.0.2", - "jest-cli": "^29.4.3" + "jest-cli": "^29.5.0" } }, "jest-changed-files": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.4.3.tgz", - "integrity": "sha512-Vn5cLuWuwmi2GNNbokPOEcvrXGSGrqVnPEZV7rC6P7ck07Dyw9RFnvWglnupSh+hGys0ajGtw/bc2ZgweljQoQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.5.0.tgz", + "integrity": "sha512-IFG34IUMUaNBIxjQXF/iu7g6EcdMrGRRxaUSw92I/2g2YC6vCdTltl4nHvt7Ci5nSJwXIkCu8Ka1DKF+X7Z1Ag==", "dev": true, "requires": { "execa": "^5.0.0", @@ -17451,92 +17287,93 @@ } }, "jest-circus": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.4.3.tgz", - "integrity": "sha512-Vw/bVvcexmdJ7MLmgdT3ZjkJ3LKu8IlpefYokxiqoZy6OCQ2VAm6Vk3t/qHiAGUXbdbJKJWnc8gH3ypTbB/OBw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.5.0.tgz", + "integrity": "sha512-gq/ongqeQKAplVxqJmbeUOJJKkW3dDNPY8PjhJ5G0lBRvu0e3EWGxGy5cI4LAGA7gV2UHCtWBI4EMXK8c9nQKA==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/expect": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/expect": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "co": "^4.6.0", "dedent": "^0.7.0", "is-generator-fn": "^2.0.0", - "jest-each": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "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", "p-limit": "^3.1.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", + "pure-rand": "^6.0.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-cli": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.4.3.tgz", - "integrity": "sha512-PiiAPuFNfWWolCE6t3ZrDXQc6OsAuM3/tVW0u27UWc1KE+n/HSn5dSE6B2juqN7WP+PP0jAcnKtGmI4u8GMYCg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.5.0.tgz", + "integrity": "sha512-L1KcP1l4HtfwdxXNFCL5bmUbLQiKrakMUriBEcc1Vfz6gx31ORKdreuWvmQVBit+1ss9NNR3yxjwfwzZNdQXJw==", "dev": true, "requires": { - "@jest/core": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/core": "^29.5.0", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "exit": "^0.1.2", "graceful-fs": "^4.2.9", "import-local": "^3.0.2", - "jest-config": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-config": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "prompts": "^2.0.1", "yargs": "^17.3.1" } }, "jest-config": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.4.3.tgz", - "integrity": "sha512-eCIpqhGnIjdUCXGtLhz4gdDoxKSWXKjzNcc5r+0S1GKOp2fwOipx5mRcwa9GB/ArsxJ1jlj2lmlD9bZAsBxaWQ==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.5.0.tgz", + "integrity": "sha512-kvDUKBnNJPNBmFFOhDbm59iu1Fii1Q6SxyhXfvylq3UTHbg6o7j/g8k2dZyXWLvfdKB1vAPxNZnMgtKJcmu3kA==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/test-sequencer": "^29.4.3", - "@jest/types": "^29.4.3", - "babel-jest": "^29.4.3", + "@jest/test-sequencer": "^29.5.0", + "@jest/types": "^29.5.0", + "babel-jest": "^29.5.0", "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.4.3", - "jest-environment-node": "^29.4.3", + "jest-circus": "^29.5.0", + "jest-environment-node": "^29.5.0", "jest-get-type": "^29.4.3", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runner": "^29.4.3", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-runner": "^29.5.0", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "micromatch": "^4.0.4", "parse-json": "^5.2.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "strip-json-comments": "^3.1.1" } }, "jest-diff": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.4.3.tgz", - "integrity": "sha512-YB+ocenx7FZ3T5O9lMVMeLYV4265socJKtkwgk/6YUz/VsEzYDkiMuMhWzZmxm3wDRQvayJu/PjkjjSkjoHsCA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.5.0.tgz", + "integrity": "sha512-LtxijLLZBduXnHSniy0WMdaHjmQnt3g5sa16W4p0HqukYTTsyTW3GD1q41TyGl5YFXj/5B2U6dlh5FM1LIMgxw==", "dev": true, "requires": { "chalk": "^4.0.0", "diff-sequences": "^29.4.3", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-docblock": { @@ -17549,30 +17386,30 @@ } }, "jest-each": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.4.3.tgz", - "integrity": "sha512-1ElHNAnKcbJb/b+L+7j0/w7bDvljw4gTv1wL9fYOczeJrbTbkMGQ5iQPFJ3eFQH19VPTx1IyfePdqSpePKss7Q==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", - "jest-util": "^29.4.3", - "pretty-format": "^29.4.3" + "jest-util": "^29.5.0", + "pretty-format": "^29.5.0" } }, "jest-environment-node": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.4.3.tgz", - "integrity": "sha512-gAiEnSKF104fsGDXNkwk49jD/0N0Bqu2K9+aMQXA6avzsA9H3Fiv1PW2D+gzbOSR705bWd2wJZRFEFpV0tXISg==", + "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==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/environment": "^29.5.0", + "@jest/fake-timers": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-mock": "^29.4.3", - "jest-util": "^29.4.3" + "jest-mock": "^29.5.0", + "jest-util": "^29.5.0" } }, "jest-get-type": { @@ -17582,12 +17419,12 @@ "dev": true }, "jest-haste-map": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.4.3.tgz", - "integrity": "sha512-eZIgAS8tvm5IZMtKlR8Y+feEOMfo2pSQkmNbufdbMzMSn9nitgGxF1waM/+LbryO3OkMcKS98SUb+j/cQxp/vQ==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", @@ -17595,8 +17432,8 @@ "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", "jest-regex-util": "^29.4.3", - "jest-util": "^29.4.3", - "jest-worker": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } @@ -17614,53 +17451,53 @@ } }, "jest-leak-detector": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.4.3.tgz", - "integrity": "sha512-9yw4VC1v2NspMMeV3daQ1yXPNxMgCzwq9BocCwYrRgXe4uaEJPAN0ZK37nFBhcy3cUwEVstFecFLaTHpF7NiGA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.5.0.tgz", + "integrity": "sha512-u9YdeeVnghBUtpN5mVxjID7KbkKE1QU4f6uUwuxiY0vYRi9BUCLKlPEZfDGR67ofdFmDz9oPAy2G92Ujrntmow==", "dev": true, "requires": { "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-matcher-utils": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.4.3.tgz", - "integrity": "sha512-TTciiXEONycZ03h6R6pYiZlSkvYgT0l8aa49z/DLSGYjex4orMUcafuLXYyyEDWB1RKglq00jzwY00Ei7yFNVg==", + "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==", "dev": true, "requires": { "chalk": "^4.0.0", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-message-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.4.3.tgz", - "integrity": "sha512-1Y8Zd4ZCN7o/QnWdMmT76If8LuDv23Z1DRovBj/vcSFNlGCJGoO8D1nJDw1AdyAGUk0myDLFGN5RbNeJyCRGCw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.5.0.tgz", + "integrity": "sha512-Kijeg9Dag6CKtIDA7O21zNTACqD5MD/8HfIV8pdD94vFyFuer52SigdC3IQMhab3vACxXMiFk+yMHNdbqtyTGA==", "dev": true, "requires": { "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/stack-utils": "^2.0.0", "chalk": "^4.0.0", "graceful-fs": "^4.2.9", "micromatch": "^4.0.4", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "slash": "^3.0.0", "stack-utils": "^2.0.3" } }, "jest-mock": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.4.3.tgz", - "integrity": "sha512-LjFgMg+xed9BdkPMyIJh+r3KeHt1klXPJYBULXVVAkbTaaKjPX1o1uVCAZADMEp/kOxGTwy/Ot8XbvgItOrHEg==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.5.0.tgz", + "integrity": "sha512-GqOzvdWDE4fAV2bWQLQCkujxYWL7RxjCnj71b5VhDAGOevB3qj3Ovg26A5NI84ZpODxyzaozXLOh2NCgkbvyaw==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", - "jest-util": "^29.4.3" + "jest-util": "^29.5.0" } }, "jest-pnp-resolver": { @@ -17677,95 +17514,95 @@ "dev": true }, "jest-resolve": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.4.3.tgz", - "integrity": "sha512-GPokE1tzguRyT7dkxBim4wSx6E45S3bOQ7ZdKEG+Qj0Oac9+6AwJPCk0TZh5Vu0xzeX4afpb+eDmgbmZFFwpOw==", + "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==", "dev": true, "requires": { "chalk": "^4.0.0", "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.4.3", + "jest-haste-map": "^29.5.0", "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.4.3", - "jest-validate": "^29.4.3", + "jest-util": "^29.5.0", + "jest-validate": "^29.5.0", "resolve": "^1.20.0", "resolve.exports": "^2.0.0", "slash": "^3.0.0" } }, "jest-resolve-dependencies": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.4.3.tgz", - "integrity": "sha512-uvKMZAQ3nmXLH7O8WAOhS5l0iWyT3WmnJBdmIHiV5tBbdaDZ1wqtNX04FONGoaFvSOSHBJxnwAVnSn1WHdGVaw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.5.0.tgz", + "integrity": "sha512-sjV3GFr0hDJMBpYeUuGduP+YeCRbd7S/ck6IvL3kQ9cpySYKqcqhdLLC2rFwrcL7tz5vYibomBrsFYWkIGGjOg==", "dev": true, "requires": { "jest-regex-util": "^29.4.3", - "jest-snapshot": "^29.4.3" + "jest-snapshot": "^29.5.0" } }, "jest-runner": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.4.3.tgz", - "integrity": "sha512-GWPTEiGmtHZv1KKeWlTX9SIFuK19uLXlRQU43ceOQ2hIfA5yPEJC7AMkvFKpdCHx6pNEdOD+2+8zbniEi3v3gA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.5.0.tgz", + "integrity": "sha512-m7b6ypERhFghJsslMLhydaXBiLf7+jXy8FwGRHO3BGV1mcQpPbwiqiKUR2zU2NJuNeMenJmlFZCsIqzJCTeGLQ==", "dev": true, "requires": { - "@jest/console": "^29.4.3", - "@jest/environment": "^29.4.3", - "@jest/test-result": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@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", "@types/node": "*", "chalk": "^4.0.0", "emittery": "^0.13.1", "graceful-fs": "^4.2.9", "jest-docblock": "^29.4.3", - "jest-environment-node": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-leak-detector": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-runtime": "^29.4.3", - "jest-util": "^29.4.3", - "jest-watcher": "^29.4.3", - "jest-worker": "^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", "p-limit": "^3.1.0", "source-map-support": "0.5.13" } }, "jest-runtime": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.4.3.tgz", - "integrity": "sha512-F5bHvxSH+LvLV24vVB3L8K467dt3y3dio6V3W89dUz9nzvTpqd/HcT9zfYKL2aZPvD63vQFgLvaUX/UpUhrP6Q==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.5.0.tgz", + "integrity": "sha512-1Hr6Hh7bAgXQP+pln3homOiEZtCDZFqwmle7Ew2j8OlbkIu6uE3Y/etJQG8MLQs3Zy90xrp2C0BRrtPHG4zryw==", "dev": true, "requires": { - "@jest/environment": "^29.4.3", - "@jest/fake-timers": "^29.4.3", - "@jest/globals": "^29.4.3", + "@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.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@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.4.3", - "jest-message-util": "^29.4.3", - "jest-mock": "^29.4.3", + "jest-haste-map": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-mock": "^29.5.0", "jest-regex-util": "^29.4.3", - "jest-resolve": "^29.4.3", - "jest-snapshot": "^29.4.3", - "jest-util": "^29.4.3", + "jest-resolve": "^29.5.0", + "jest-snapshot": "^29.5.0", + "jest-util": "^29.5.0", "slash": "^3.0.0", "strip-bom": "^4.0.0" } }, "jest-snapshot": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.4.3.tgz", - "integrity": "sha512-NGlsqL0jLPDW91dz304QTM/SNO99lpcSYYAjNiX0Ou+sSGgkanKBcSjCfp/pqmiiO1nQaOyLp6XQddAzRcx3Xw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.5.0.tgz", + "integrity": "sha512-x7Wolra5V0tt3wRs3/ts3S6ciSQVypgGQlJpz2rsdQYoUKxMxPNaoHMGJN6qAuPJqS+2iQ1ZUn5kl7HCyls84g==", "dev": true, "requires": { "@babel/core": "^7.11.6", @@ -17774,33 +17611,32 @@ "@babel/plugin-syntax-typescript": "^7.7.2", "@babel/traverse": "^7.7.2", "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.4.3", - "@jest/transform": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/expect-utils": "^29.5.0", + "@jest/transform": "^29.5.0", + "@jest/types": "^29.5.0", "@types/babel__traverse": "^7.0.6", "@types/prettier": "^2.1.5", "babel-preset-current-node-syntax": "^1.0.0", "chalk": "^4.0.0", - "expect": "^29.4.3", + "expect": "^29.5.0", "graceful-fs": "^4.2.9", - "jest-diff": "^29.4.3", + "jest-diff": "^29.5.0", "jest-get-type": "^29.4.3", - "jest-haste-map": "^29.4.3", - "jest-matcher-utils": "^29.4.3", - "jest-message-util": "^29.4.3", - "jest-util": "^29.4.3", + "jest-matcher-utils": "^29.5.0", + "jest-message-util": "^29.5.0", + "jest-util": "^29.5.0", "natural-compare": "^1.4.0", - "pretty-format": "^29.4.3", + "pretty-format": "^29.5.0", "semver": "^7.3.5" } }, "jest-util": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.4.3.tgz", - "integrity": "sha512-ToSGORAz4SSSoqxDSylWX8JzkOQR7zoBtNRsA7e+1WUX5F8jrOwaNpuh1YfJHJKDHXLHmObv5eOjejUd+/Ws+Q==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -17809,43 +17645,43 @@ } }, "jest-validate": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.4.3.tgz", - "integrity": "sha512-J3u5v7aPQoXPzaar6GndAVhdQcZr/3osWSgTeKg5v574I9ybX/dTyH0AJFb5XgXIB7faVhf+rS7t4p3lL9qFaw==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.4.3", + "@jest/types": "^29.5.0", "camelcase": "^6.2.0", "chalk": "^4.0.0", "jest-get-type": "^29.4.3", "leven": "^3.1.0", - "pretty-format": "^29.4.3" + "pretty-format": "^29.5.0" } }, "jest-watcher": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.4.3.tgz", - "integrity": "sha512-zwlXH3DN3iksoIZNk73etl1HzKyi5FuQdYLnkQKm5BW4n8HpoG59xSwpVdFrnh60iRRaRBGw0gcymIxjJENPcA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.5.0.tgz", + "integrity": "sha512-KmTojKcapuqYrKDpRwfqcQ3zjMlwu27SYext9pt4GlF5FUgB+7XE1mcCnSm6a4uUpFyQIkb6ZhzZvHl+jiBCiA==", "dev": true, "requires": { - "@jest/test-result": "^29.4.3", - "@jest/types": "^29.4.3", + "@jest/test-result": "^29.5.0", + "@jest/types": "^29.5.0", "@types/node": "*", "ansi-escapes": "^4.2.1", "chalk": "^4.0.0", "emittery": "^0.13.1", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "string-length": "^4.0.1" } }, "jest-worker": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.4.3.tgz", - "integrity": "sha512-GLHN/GTAAMEy5BFdvpUfzr9Dr80zQqBrh0fz1mtRMe05hqP45+HfQltu7oTBfduD0UeZs09d+maFtFYAXFWvAA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.4.3", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -17866,12 +17702,6 @@ "resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz", "integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==" }, - "js-sdsl": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.3.0.tgz", - "integrity": "sha512-mifzlm2+5nZ+lEcLJMoBK0/IH/bDg8XnJfd/Wq6IP+xoCjLZsTOnV2QpxlVbX9bMnkl5PdEjNtBJ9Cj1NjifhQ==", - "dev": true - }, "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -18124,13 +17954,13 @@ "dev": true }, "maxmind": { - "version": "4.3.8", - "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.8.tgz", - "integrity": "sha512-HrfxEu5yPBPtTy/OT+W5bPQwEfLUX0EHqe2EbJiB47xQMumHqXvSP7PAwzV8Z++NRCmQwy4moQrTSt0+dH+Jmg==", + "version": "4.3.11", + "resolved": "https://registry.npmjs.org/maxmind/-/maxmind-4.3.11.tgz", + "integrity": "sha512-tJDrKbUzN6PSA88tWgg0L2R4Ln00XwecYQJPFI+RvlF2k1sx6VQYtuQ1SVxm8+bw5tF7GWV4xyb+3/KyzEpPUw==", "dev": true, "requires": { "mmdb-lib": "2.0.2", - "tiny-lru": "9.0.3" + "tiny-lru": "11.0.1" } }, "md5.js": { @@ -18224,9 +18054,9 @@ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.4.tgz", - "integrity": "sha512-lwycX3cBMTvcejsHITUgYj6Gy6A7Nh4Q6h9NP4sTHY1ccJlC7yKzDmiShEHsJ16Jf1nKGDEaiHxiltsJEvk0nQ==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" }, "minizlib": { "version": "2.1.2", @@ -18264,12 +18094,12 @@ "dev": true }, "mongodb": { - "version": "4.14.0", - "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.14.0.tgz", - "integrity": "sha512-coGKkWXIBczZPr284tYKFLg+KbGPPLlSbdgfKAb6QqCFt5bo5VFZ50O3FFzsw4rnkqjwT6D8Qcoo9nshYKM7Mg==", + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.16.0.tgz", + "integrity": "sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g==", "requires": { "@aws-sdk/credential-providers": "^3.186.0", - "bson": "^4.7.0", + "bson": "^4.7.2", "mongodb-connection-string-url": "^2.5.4", "saslprep": "^1.0.3", "socks": "^2.7.1" @@ -18285,13 +18115,13 @@ } }, "mongoose": { - "version": "6.10.2", - "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.10.2.tgz", - "integrity": "sha512-9/AbheG2PiVVBWLx3S6LgCIEQNdMppjdnp/WH9nLGjFzjJeb9LiHNPEtsOGOm8qXmuICHMdbn5iUFAsLWWvpEw==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-6.11.1.tgz", + "integrity": "sha512-AvQ8C5ZGF6GcsQhoRg/i7pbNZpb96qLGU5ICBllckp7qMOxcfUF1nA6JstZw841BqRcE6myZ/mx9CluEESaw5Q==", "requires": { - "bson": "^4.7.0", + "bson": "^4.7.2", "kareem": "2.5.1", - "mongodb": "4.14.0", + "mongodb": "4.16.0", "mpath": "0.9.0", "mquery": "4.0.3", "ms": "2.1.3", @@ -18323,6 +18153,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "nanoid": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -18350,10 +18185,18 @@ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, "node-fetch": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.9.tgz", - "integrity": "sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "requires": { "whatwg-url": "^5.0.0" }, @@ -18386,20 +18229,20 @@ "dev": true }, "node-releases": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", - "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==", + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.12.tgz", + "integrity": "sha512-QzsYKWhXTWx8h1kIvqfnC++o0pEmpRQA/aenALsL2F4pqNVr7YzcdMlDij5WBnwftRbJCNJL/O7zdKaxKPHqgQ==", "dev": true }, "nodemailer": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.1.tgz", - "integrity": "sha512-qHw7dOiU5UKNnQpXktdgQ1d3OFgRAekuvbJLcdG5dnEo/GtcTHRYM7+UfJARdOFU9WUQO8OiIamgWPmiSFHYAA==" + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.2.tgz", + "integrity": "sha512-4+TYaa/e1nIxQfyw/WzNPYTEZ5OvHIDEnmjs4LPmIfccPQN+2CYKmGHjWixn/chzD3bmUTu5FMfpltizMxqzdg==" }, "nodemon": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", - "integrity": "sha512-Km2mWHKKY5GzRg6i1j5OxOHQtuvVsgskLfigG25yTtbyfRGn/GNvIbRyOf1PSCKJ2aT/58TiuUsuOU5UToVViw==", + "version": "2.0.22", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.22.tgz", + "integrity": "sha512-B8YqaKMmyuCO7BowF1Z1/mkPqLk6cs/l63Ojtd6otKjMx47Dq1utxfRxcavH1I7VSaL8n5BUaoutadnsX3AAVQ==", "dev": true, "requires": { "chokidar": "^3.5.2", @@ -20269,6 +20112,11 @@ "set-blocking": "^2.0.0" } }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha512-a5ERWK1kh38ExDEfoO6qUHJb32rd7aYmPHuyCu3Fta/cnICvYmgd2uhuKXvPD+PXB+gCEYYEaQdIRAjCOwAKNA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -20312,6 +20160,14 @@ "mimic-fn": "^2.1.0" } }, + "optional-require": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/optional-require/-/optional-require-1.1.8.tgz", + "integrity": "sha512-jq83qaUb0wNg9Krv1c5OQ+58EK+vHde6aBPzLvPPqJm89UQWsvSuFy9X/OSNJnFeSOKo7btE0n8Nl2+nE+z5nA==", + "requires": { + "require-at": "^1.0.6" + } + }, "optionator": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", @@ -20376,6 +20232,41 @@ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + } + }, + "passport-google-oauth20": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz", + "integrity": "sha512-KSk6IJ15RoxuGq7D1UKK/8qKhNfzbLeLrG3gkLZ7p4A6DBCcv7xpyQwuXtWdpyR0+E0mwkpjY1VfPOhxQrKzdQ==", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.7.0.tgz", + "integrity": "sha512-j2gf34szdTF2Onw3+76alNnaAExlUmHvkc7cL+cmaS5NzHzDP/BvFHJruueQ9XAeNOdpI+CH+PWid8RA7KCwAQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==" + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -20410,6 +20301,11 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -20477,9 +20373,9 @@ } }, "posthog-node": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.5.4.tgz", - "integrity": "sha512-CdywlVh0CZU05/3MrBc0qY/zsLdU2X9XSz/yL1qMRhbyZhD8lrnuGlI69G2cpzZtli6S/nu64wcmULz/mFFA5w==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/posthog-node/-/posthog-node-2.6.0.tgz", + "integrity": "sha512-/BiFw/jwdP0uJSRAIoYqLoBTjZ612xv74b1L/a3T/p1nJVL8e0OrHuxbJW56c6WVW/IKm9gBF/zhbqfaz0XgJQ==", "requires": { "axios": "^0.27.0" }, @@ -20502,9 +20398,9 @@ "dev": true }, "pretty-format": { - "version": "29.4.3", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.4.3.tgz", - "integrity": "sha512-cvpcHTc42lcsvOOAzd3XuNWTcvk1Jmnzqeu+WsOuiPmxUJTnkbAcFNsRKvEpBEUFVUgy/GTZLulZDcDEi+CIlA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", "dev": true, "requires": { "@jest/schemas": "^29.4.3", @@ -20520,6 +20416,11 @@ } } }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "prompts": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", @@ -20575,6 +20476,12 @@ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" }, + "pure-rand": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.2.tgz", + "integrity": "sha512-6Yg0ekpKICSjPswYOuC5sku/TSWaRYlA0qsXqJgM/d/4pLPHPuTxK7Nbf7jFKzAeedUhR8C7K9Uv63FBsSo8xQ==", + "dev": true + }, "qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -20624,6 +20531,36 @@ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" }, + "rate-limit-mongo": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/rate-limit-mongo/-/rate-limit-mongo-2.3.2.tgz", + "integrity": "sha512-dLck0j5N/AX9ycVHn5lX9Ti2Wrrwi1LfbXitu/mMBZOo2nC26RgYKJVbcb2mYgb9VMaPI2IwJVzIa2hAQrMaDA==", + "requires": { + "mongodb": "^3.6.7", + "twostep": "0.4.2", + "underscore": "1.12.1" + }, + "dependencies": { + "bson": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.6.tgz", + "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==", + "requires": { + "bl": "^2.2.1", + "bson": "^1.1.4", + "denque": "^1.4.1", + "optional-require": "^1.1.8", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + } + } + }, "raw-body": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", @@ -20642,9 +20579,9 @@ "dev": true }, "readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "requires": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -20665,16 +20602,10 @@ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "request-ip": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/request-ip/-/request-ip-3.3.0.tgz", - "integrity": "sha512-cA6Xh6e0fDBBBwH77SLJaJPBmD3nWVAcF9/XAcsrIHdjhFzFiB5aNQFytdjCGPezU3ROwrR11IddKAM08vohxA==" + "require-at": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/require-at/-/require-at-1.0.6.tgz", + "integrity": "sha512-7i1auJbMUrXEAZCOQ0VNJgmcT2VOKPRl2YGJwgpHpC9CE91Mv4/4UYIUm4chGJaI381ZDq1JUicFii64Hapd8g==" }, "require-directory": { "version": "2.1.1", @@ -20683,12 +20614,12 @@ "dev": true }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -20717,9 +20648,9 @@ "dev": true }, "resolve.exports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.0.tgz", - "integrity": "sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", "dev": true }, "reusify": { @@ -20760,9 +20691,9 @@ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, "safe-stable-stringify": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.2.tgz", - "integrity": "sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==" + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==" }, "safer-buffer": { "version": "2.1.2", @@ -20784,9 +20715,9 @@ "integrity": "sha512-8I2a3LovHTOpm7NV5yOyO8IHqgVsfK4+UuySrXU8YXkSRX7k6hCV9b3HrkKCr3nMpgj+0bmocaJJWpvp1oc7ZA==" }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "requires": { "lru-cache": "^6.0.0" }, @@ -21202,26 +21133,26 @@ } }, "swagger-ui-dist": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.16.1.tgz", - "integrity": "sha512-4J4XekQG0ol4/TyUzMfksrWsMTbw/7JYlT+SFaX7H0xamd1OeuVlUSb/Cbq4qdDx1lc+uLZQW7u2mlImcE8c+w==" + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-4.19.0.tgz", + "integrity": "sha512-9C9fJGI18gK5AhaU5YRyPY1lXJH4lmWh8h9zFMrJBkYzdRjCbAzYl1ayWPYgwFvag/Luqi3Co599OK/39IS2QQ==" }, "swagger-ui-express": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.2.tgz", - "integrity": "sha512-MHIOaq9JrTTB3ygUJD+08PbjM5Tt/q7x80yz9VTFIatw8j5uIWKcr90S0h5NLMzFEDC6+eVprtoeA5MDZXCUKQ==", + "version": "4.6.3", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-4.6.3.tgz", + "integrity": "sha512-CDje4PndhTD2HkgyKH3pab+LKspDeB/NhPN2OF1j+piYIamQqBYwAXWESOT1Yju2xFg51bRW9sUng2WxDjzArw==", "requires": { "swagger-ui-dist": ">=4.11.0" } }, "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -21257,9 +21188,9 @@ "dev": true }, "tiny-lru": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-9.0.3.tgz", - "integrity": "sha512-/i9GruRjXsnDgehxvy6iZ4AFNVxngEFbwzirhdulomMNPGPVV3ECMZOWSw0w4sRMZ9Al9m4jy08GPvRxRUGYlw==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/tiny-lru/-/tiny-lru-11.0.1.tgz", + "integrity": "sha512-iNgFugVuQgBKrqeO/mpiTTgmBsTP0WL6yeuLfLs/Ctf0pI/ixGqIRm8sDCwMcXGe9WWvt2sGXI5mNqZbValmJg==", "dev": true }, "tmpl": { @@ -21322,9 +21253,9 @@ "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" }, "ts-jest": { - "version": "29.0.5", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.0.5.tgz", - "integrity": "sha512-PL3UciSgIpQ7f6XjVOmbi96vmDHUqAyqDr8YxzopDqX3kfgYtX1cuNeBjP+L9sFXi6nzsGGA6R3fP3DDDJyrxA==", + "version": "29.1.0", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.1.0.tgz", + "integrity": "sha512-ZhNr7Z4PcYa+JjMl62ir+zPiNJfXJN6E8hSLnaUKhOgqcn8vb3e537cpkd0FuAfRK3sR1LSqM1MOhliXNgOFPA==", "dev": true, "requires": { "bs-logger": "0.x", @@ -21359,9 +21290,9 @@ } }, "tslib": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", - "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "tsutils": { "version": "3.21.0", @@ -21390,6 +21321,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" }, + "twostep": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/twostep/-/twostep-0.4.2.tgz", + "integrity": "sha512-O/wdPYk9ey04qcCiw8AQN74DbvLFZLAgnryrNTpV7T/sxB4lcGkCMHynx5xCcA6fCh739ZAqp3HcGhy770X1qA==" + }, "type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -21431,12 +21367,22 @@ "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", "optional": true }, + "uid2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.4.tgz", + "integrity": "sha512-IevTus0SbGwQzYh3+fRsAMTVVPOoIVufzacXcHPmdlle1jUpq7BRL+mw3dgeLanvGZdwwbWhRV6XrcFNdBmjWA==" + }, "undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", "dev": true }, + "underscore": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz", + "integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==" + }, "universal-user-agent": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", @@ -21448,9 +21394,9 @@ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" }, "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", "dev": true, "requires": { "escalade": "^3.1.1", @@ -21614,9 +21560,9 @@ } }, "winston": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/winston/-/winston-3.8.2.tgz", - "integrity": "sha512-MsE1gRx1m5jdTTO9Ld/vND4krP2To+lgDoMEHGGa4HIlAUyXJtfc7CxQcGXVyz2IBpw5hbFkj2b/AtUdQwyRew==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.9.0.tgz", + "integrity": "sha512-jW51iW/X95BCW6MMtZWr2jKQBP4hV5bIDq9QrIjfDk6Q9QuxvTKEAlpUNAzP+HYHFFCeENhph16s0zEunu4uuQ==", "requires": { "@colors/colors": "1.5.0", "@dabh/diagnostics": "^2.0.2", @@ -21697,18 +21643,18 @@ "dev": true }, "xml2js": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz", - "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", + "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", "requires": { "sax": ">=0.6.0", - "xmlbuilder": "~9.0.1" + "xmlbuilder": "~11.0.0" } }, "xmlbuilder": { - "version": "9.0.7", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz", - "integrity": "sha512-7YXTQc3P2l9+0rjaUbLwMKRhtmwg1M1eDf6nag7urC7pIPYLD9W/jmzQ4ptRSUbodw5S0jfoGTflLemQibSpeQ==" + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" }, "y18n": { "version": "5.0.8", @@ -21723,9 +21669,9 @@ "dev": true }, "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", diff --git a/backend/package.json b/backend/package.json index af252211b..6d855001e 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,39 +1,45 @@ { "dependencies": { - "@aws-sdk/client-secrets-manager": "^3.281.0", - "@godaddy/terminus": "^4.11.2", + "@aws-sdk/client-secrets-manager": "^3.319.0", + "@godaddy/terminus": "^4.12.0", "@octokit/rest": "^19.0.5", - "@sentry/tracing": "^7.39.0", - "@sentry/node": "^7.40.0", + "@sentry/node": "^7.49.0", + "@sentry/tracing": "^7.48.0", "@types/crypto-js": "^4.1.1", "@types/libsodium-wrappers": "^0.7.10", + "argon2": "^0.30.3", "await-to-js": "^3.0.0", - "aws-sdk": "^2.1324.0", - "axios": "^1.1.3", + "aws-sdk": "^2.1364.0", + "axios": "^1.3.5", "axios-retry": "^3.4.0", "bcrypt": "^5.1.0", - "bigint-conversion": "^2.2.2", + "bigint-conversion": "^2.4.0", "builder-pattern": "^2.2.0", "cookie-parser": "^1.4.6", "cors": "^2.8.5", "crypto-js": "^4.1.1", "dotenv": "^16.0.1", "express": "^4.18.1", + "express-async-errors": "^3.1.1", "express-rate-limit": "^6.7.0", "express-validator": "^6.14.2", "handlebars": "^4.7.7", "helmet": "^5.1.1", - "infisical-node": "^1.0.37", + "infisical-node": "^1.2.1", "js-yaml": "^4.1.0", "jsonwebtoken": "^9.0.0", "jsrp": "^0.2.4", "libsodium-wrappers": "^0.7.10", "lodash": "^4.17.21", - "mongoose": "^6.10.2", + "mongoose": "^6.10.5", + "nanoid": "^3.3.6", + "node-cache": "^5.1.2", "nodemailer": "^6.8.0", - "posthog-node": "^2.5.4", + "passport": "^0.6.0", + "passport-google-oauth20": "^2.0.0", + "posthog-node": "^2.6.0", "query-string": "^7.1.3", - "request-ip": "^3.3.0", + "rate-limit-mongo": "^2.3.2", "rimraf": "^3.0.2", "stripe": "^10.7.0", "swagger-autogen": "^2.22.0", @@ -52,12 +58,12 @@ "start": "node build/index.js", "dev": "nodemon", "swagger-autogen": "node ./swagger/index.ts", - "build": "rimraf ./build && tsc && cp -R ./src/templates ./build", + "build": "rimraf ./build && tsc && cp -R ./src/templates ./build && cp -R ./src/data ./build", "lint": "eslint . --ext .ts", "lint-and-fix": "eslint . --ext .ts --fix", "lint-staged": "lint-staged", "pretest": "docker compose -f test-resources/docker-compose.test.yml up -d", - "test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles", + "test": "cross-env NODE_ENV=test jest --verbose --testTimeout=10000 --detectOpenHandles; npm run posttest", "test:ci": "npm test -- --watchAll=false --ci --reporters=default --reporters=jest-junit --reporters=github-actions --coverage --testLocationInResults --json --outputFile=coverage/report.json", "posttest": "docker compose -f test-resources/docker-compose.test.yml down" }, @@ -80,11 +86,12 @@ "@types/cookie-parser": "^1.4.3", "@types/cors": "^2.8.12", "@types/express": "^4.17.14", - "@types/jest": "^29.2.4", + "@types/jest": "^29.5.0", "@types/jsonwebtoken": "^8.5.9", "@types/lodash": "^4.14.191", "@types/node": "^18.11.3", "@types/nodemailer": "^6.4.6", + "@types/passport": "^1.0.12", "@types/supertest": "^2.0.12", "@types/swagger-jsdoc": "^6.0.1", "@types/swagger-ui-express": "^4.1.3", diff --git a/backend/spec.json b/backend/spec.json index f0af8d903..013b5fd4d 100644 --- a/backend/spec.json +++ b/backend/spec.json @@ -1532,7 +1532,15 @@ "/api/v1/invite-org/signup": { "post": { "description": "", - "parameters": [], + "parameters": [ + { + "name": "host", + "in": "header", + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK" @@ -2071,6 +2079,15 @@ "targetEnvironment": { "example": "any" }, + "targetEnvironmentId": { + "example": "any" + }, + "targetService": { + "example": "any" + }, + "targetServiceId": { + "example": "any" + }, "owner": { "example": "any" }, @@ -2297,6 +2314,13 @@ "schema": { "type": "string" } + }, + { + "name": "teamId", + "in": "query", + "schema": { + "type": "string" + } } ], "responses": { @@ -2309,6 +2333,107 @@ } } }, + "/api/v1/integration-auth/{integrationAuthId}/teams": { + "get": { + "description": "", + "parameters": [ + { + "name": "integrationAuthId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/integration-auth/{integrationAuthId}/vercel/branches": { + "get": { + "description": "", + "parameters": [ + { + "name": "integrationAuthId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "appId", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/integration-auth/{integrationAuthId}/railway/environments": { + "get": { + "description": "", + "parameters": [ + { + "name": "integrationAuthId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "appId", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v1/integration-auth/{integrationAuthId}/railway/services": { + "get": { + "description": "", + "parameters": [ + { + "name": "integrationAuthId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "appId", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v2/signup/complete-account/signup": { "post": { "description": "", @@ -2870,9 +2995,6 @@ } } } - }, - "400": { - "description": "Bad Request" } }, "security": [ @@ -2882,6 +3004,26 @@ ] } }, + "/api/v2/organizations/{organizationId}/service-accounts": { + "get": { + "description": "", + "parameters": [ + { + "name": "organizationId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, "/api/v2/workspace/{workspaceId}/environments": { "post": { "description": "", @@ -4018,9 +4160,6 @@ "responses": { "200": { "description": "OK" - }, - "400": { - "description": "Bad Request" } }, "requestBody": { @@ -4073,6 +4212,138 @@ } } ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v2/service-accounts/me": { + "get": { + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v2/service-accounts/{serviceAccountId}": { + "get": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "delete": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v2/service-accounts/": { + "post": { + "description": "", + "parameters": [], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v2/service-accounts/{serviceAccountId}/name": { + "patch": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "example": "any" + } + } + } + } + } + } + } + }, + "/api/v2/service-accounts/{serviceAccountId}/permissions/workspace": { + "get": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "post": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], "responses": { "200": { "description": "OK" @@ -4080,6 +4351,90 @@ "400": { "description": "Bad Request" } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "environment": { + "example": "any" + }, + "workspaceId": { + "example": "any" + }, + "read": { + "example": "any" + }, + "write": { + "example": "any" + }, + "encryptedKey": { + "example": "any" + }, + "nonce": { + "example": "any" + } + } + } + } + } + } + } + }, + "/api/v2/service-accounts/{serviceAccountId}/permissions/workspace/{serviceAccountWorkspacePermissionId}": { + "delete": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "serviceAccountWorkspacePermissionId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v2/service-accounts/{serviceAccountId}/keys": { + "get": { + "description": "", + "parameters": [ + { + "name": "serviceAccountId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "workspaceId", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } } } }, @@ -4149,6 +4504,297 @@ } } }, + "/api/v3/secrets/": { + "get": { + "description": "", + "parameters": [ + { + "name": "workspaceId", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "environment", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v3/secrets/{secretName}": { + "post": { + "description": "", + "parameters": [ + { + "name": "secretName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "workspaceId": { + "example": "any" + }, + "environment": { + "example": "any" + }, + "type": { + "example": "any" + }, + "secretKeyCiphertext": { + "example": "any" + }, + "secretKeyIV": { + "example": "any" + }, + "secretKeyTag": { + "example": "any" + }, + "secretValueCiphertext": { + "example": "any" + }, + "secretValueIV": { + "example": "any" + }, + "secretValueTag": { + "example": "any" + }, + "secretCommentCiphertext": { + "example": "any" + }, + "secretCommentIV": { + "example": "any" + }, + "secretCommentTag": { + "example": "any" + } + } + } + } + } + } + }, + "get": { + "description": "", + "parameters": [ + { + "name": "secretName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "workspaceId", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "environment", + "in": "query", + "schema": { + "type": "string" + } + }, + { + "name": "type", + "in": "query", + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + }, + "patch": { + "description": "", + "parameters": [ + { + "name": "secretName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "workspaceId": { + "example": "any" + }, + "environment": { + "example": "any" + }, + "type": { + "example": "any" + }, + "secretValueCiphertext": { + "example": "any" + }, + "secretValueIV": { + "example": "any" + }, + "secretValueTag": { + "example": "any" + } + } + } + } + } + } + }, + "delete": { + "description": "", + "parameters": [ + { + "name": "secretName", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "workspaceId": { + "example": "any" + }, + "environment": { + "example": "any" + }, + "type": { + "example": "any" + } + } + } + } + } + } + } + }, + "/api/v3/workspaces/{workspaceId}/secrets/blind-index-status": { + "get": { + "description": "", + "parameters": [ + { + "name": "workspaceId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v3/workspaces/{workspaceId}/secrets": { + "get": { + "description": "", + "parameters": [ + { + "name": "workspaceId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/api/v3/workspaces/{workspaceId}/secrets/names": { + "post": { + "description": "", + "parameters": [ + { + "name": "workspaceId", + "in": "path", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "description": "OK" + } + }, + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "secretsToUpdate": { + "example": "any" + } + } + } + } + } + } + } + }, "/api/status": { "get": { "description": "", diff --git a/backend/src/config/index.ts b/backend/src/config/index.ts index 33066f613..4613a05c9 100644 --- a/backend/src/config/index.ts +++ b/backend/src/config/index.ts @@ -1,51 +1,93 @@ -import infisical from 'infisical-node'; -export const getPort = () => infisical.get('PORT')! || 4000; -export const getInviteOnlySignup = () => infisical.get('INVITE_ONLY_SIGNUP')! == undefined ? false : infisical.get('INVITE_ONLY_SIGNUP'); -export const getEncryptionKey = () => infisical.get('ENCRYPTION_KEY')!; -export const getSaltRounds = () => parseInt(infisical.get('SALT_ROUNDS')!) || 10; -export const getJwtAuthLifetime = () => infisical.get('JWT_AUTH_LIFETIME')! || '10d'; -export const getJwtAuthSecret = () => infisical.get('JWT_AUTH_SECRET')!; -export const getJwtMfaLifetime = () => infisical.get('JWT_MFA_LIFETIME')! || '5m'; -export const getJwtMfaSecret = () => infisical.get('JWT_MFA_LIFETIME')! || '5m'; -export const getJwtRefreshLifetime = () => infisical.get('JWT_REFRESH_LIFETIME')! || '90d'; -export const getJwtRefreshSecret = () => infisical.get('JWT_REFRESH_SECRET')!; -export const getJwtServiceSecret = () => infisical.get('JWT_SERVICE_SECRET')!; -export const getJwtSignupLifetime = () => infisical.get('JWT_SIGNUP_LIFETIME')! || '15m'; -export const getJwtSignupSecret = () => infisical.get('JWT_SIGNUP_SECRET')!; -export const getMongoURL = () => infisical.get('MONGO_URL')!; -export const getNodeEnv = () => infisical.get('NODE_ENV')!; -export const getVerboseErrorOutput = () => infisical.get('VERBOSE_ERROR_OUTPUT')! === 'true' && true; -export const getLokiHost = () => infisical.get('LOKI_HOST')!; -export const getClientIdAzure = () => infisical.get('CLIENT_ID_AZURE')!; -export const getClientIdHeroku = () => infisical.get('CLIENT_ID_HEROKU')!; -export const getClientIdVercel = () => infisical.get('CLIENT_ID_VERCEL')!; -export const getClientIdNetlify = () => infisical.get('CLIENT_ID_NETLIFY')!; -export const getClientIdGitHub = () => infisical.get('CLIENT_ID_GITHUB')!; -export const getClientIdGitLab = () => infisical.get('CLIENT_ID_GITLAB')!; -export const getClientSecretAzure = () => infisical.get('CLIENT_SECRET_AZURE')!; -export const getClientSecretHeroku = () => infisical.get('CLIENT_SECRET_HEROKU')!; -export const getClientSecretVercel = () => infisical.get('CLIENT_SECRET_VERCEL')!; -export const getClientSecretNetlify = () => infisical.get('CLIENT_SECRET_NETLIFY')!; -export const getClientSecretGitHub = () => infisical.get('CLIENT_SECRET_GITHUB')!; -export const getClientSecretGitLab = () => infisical.get('CLIENT_SECRET_GITLAB')!; -export const getClientSlugVercel = () => infisical.get('CLIENT_SLUG_VERCEL')!; -export const getPostHogHost = () => infisical.get('POSTHOG_HOST')! || 'https://app.posthog.com'; -export const getPostHogProjectApiKey = () => infisical.get('POSTHOG_PROJECT_API_KEY')! || 'phc_nSin8j5q2zdhpFDI1ETmFNUIuTG4DwKVyIigrY10XiE'; -export const getSentryDSN = () => infisical.get('SENTRY_DSN')!; -export const getSiteURL = () => infisical.get('SITE_URL')!; -export const getSmtpHost = () => infisical.get('SMTP_HOST')!; -export const getSmtpSecure = () => infisical.get('SMTP_SECURE')! === 'true' || false; -export const getSmtpPort = () => parseInt(infisical.get('SMTP_PORT')!) || 587; -export const getSmtpUsername = () => infisical.get('SMTP_USERNAME')!; -export const getSmtpPassword = () => infisical.get('SMTP_PASSWORD')!; -export const getSmtpFromAddress = () => infisical.get('SMTP_FROM_ADDRESS')!; -export const getSmtpFromName = () => infisical.get('SMTP_FROM_NAME')! || 'Infisical'; -export const getStripeProductStarter = () => infisical.get('STRIPE_PRODUCT_STARTER')!; -export const getStripeProductPro = () => infisical.get('STRIPE_PRODUCT_PRO')!; -export const getStripeProductTeam = () => infisical.get('STRIPE_PRODUCT_TEAM')!; -export const getStripePublishableKey = () => infisical.get('STRIPE_PUBLISHABLE_KEY')!; -export const getStripeSecretKey = () => infisical.get('STRIPE_SECRET_KEY')!; -export const getStripeWebhookSecret = () => infisical.get('STRIPE_WEBHOOK_SECRET')!; -export const getTelemetryEnabled = () => infisical.get('TELEMETRY_ENABLED')! !== 'false' && true; -export const getLoopsApiKey = () => infisical.get('LOOPS_API_KEY')!; -export const getSmtpConfigured = () => infisical.get('SMTP_HOST') == '' || infisical.get('SMTP_HOST') == undefined ? false : true \ No newline at end of file +import InfisicalClient from 'infisical-node'; + +export const client = new InfisicalClient({ + token: process.env.INFISICAL_TOKEN! +}); + +export const getPort = async () => (await client.getSecret('PORT')).secretValue || 4000; +export const getEncryptionKey = async () => { + const secretValue = (await client.getSecret('ENCRYPTION_KEY')).secretValue; + return secretValue === '' ? undefined : secretValue; +} +export const getRootEncryptionKey = async () => { + const secretValue = (await client.getSecret('ROOT_ENCRYPTION_KEY')).secretValue; + return secretValue === '' ? undefined : secretValue; +} +export const getInviteOnlySignup = async () => (await client.getSecret('INVITE_ONLY_SIGNUP')).secretValue === 'true' +export const getSaltRounds = async () => parseInt((await client.getSecret('SALT_ROUNDS')).secretValue) || 10; +export const getJwtAuthLifetime = async () => (await client.getSecret('JWT_AUTH_LIFETIME')).secretValue || '10d'; +export const getJwtAuthSecret = async () => (await client.getSecret('JWT_AUTH_SECRET')).secretValue; +export const getJwtMfaLifetime = async () => (await client.getSecret('JWT_MFA_LIFETIME')).secretValue || '5m'; +export const getJwtMfaSecret = async () => (await client.getSecret('JWT_MFA_LIFETIME')).secretValue || '5m'; +export const getJwtRefreshLifetime = async () => (await client.getSecret('JWT_REFRESH_LIFETIME')).secretValue || '90d'; +export const getJwtRefreshSecret = async () => (await client.getSecret('JWT_REFRESH_SECRET')).secretValue; +export const getJwtServiceSecret = async () => (await client.getSecret('JWT_SERVICE_SECRET')).secretValue; +export const getJwtSignupLifetime = async () => (await client.getSecret('JWT_SIGNUP_LIFETIME')).secretValue || '15m'; +export const getJwtProviderAuthSecret = async () => (await client.getSecret('JWT_PROVIDER_AUTH_SECRET')).secretValue; +export const getJwtProviderAuthLifetime = async () => (await client.getSecret('JWT_PROVIDER_AUTH_LIFETIME')).secretValue || '15m'; +export const getJwtSignupSecret = async () => (await client.getSecret('JWT_SIGNUP_SECRET')).secretValue; +export const getMongoURL = async () => (await client.getSecret('MONGO_URL')).secretValue; +export const getNodeEnv = async () => (await client.getSecret('NODE_ENV')).secretValue || 'production'; +export const getVerboseErrorOutput = async () => (await client.getSecret('VERBOSE_ERROR_OUTPUT')).secretValue === 'true' && true; +export const getLokiHost = async () => (await client.getSecret('LOKI_HOST')).secretValue; +export const getClientIdAzure = async () => (await client.getSecret('CLIENT_ID_AZURE')).secretValue; +export const getClientIdHeroku = async () => (await client.getSecret('CLIENT_ID_HEROKU')).secretValue; +export const getClientIdVercel = async () => (await client.getSecret('CLIENT_ID_VERCEL')).secretValue; +export const getClientIdNetlify = async () => (await client.getSecret('CLIENT_ID_NETLIFY')).secretValue; +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 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; +export const getClientSecretNetlify = async () => (await client.getSecret('CLIENT_SECRET_NETLIFY')).secretValue; +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 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'; +export const getSentryDSN = async () => (await client.getSecret('SENTRY_DSN')).secretValue; +export const getSiteURL = async () => (await client.getSecret('SITE_URL')).secretValue; +export const getSmtpHost = async () => (await client.getSecret('SMTP_HOST')).secretValue; +export const getSmtpSecure = async () => (await client.getSecret('SMTP_SECURE')).secretValue === 'true' || false; +export const getSmtpPort = async () => parseInt((await client.getSecret('SMTP_PORT')).secretValue) || 587; +export const getSmtpUsername = async () => (await client.getSecret('SMTP_USERNAME')).secretValue; +export const getSmtpPassword = async () => (await client.getSecret('SMTP_PASSWORD')).secretValue; +export const getSmtpFromAddress = async () => (await client.getSecret('SMTP_FROM_ADDRESS')).secretValue; +export const getSmtpFromName = async () => (await client.getSecret('SMTP_FROM_NAME')).secretValue || 'Infisical'; + +export const getLicenseKey = async () => { + const secretValue = (await client.getSecret('LICENSE_KEY')).secretValue; + return secretValue === '' ? undefined : secretValue; +} +export const getLicenseServerKey = async () => { + const secretValue = (await client.getSecret('LICENSE_SERVER_KEY')).secretValue; + return secretValue === '' ? undefined : secretValue; +} +export const getLicenseServerUrl = async () => (await client.getSecret('LICENSE_SERVER_URL')).secretValue || 'https://portal.infisical.com'; + +// TODO: deprecate from here +export const getStripeProductStarter = async () => (await client.getSecret('STRIPE_PRODUCT_STARTER')).secretValue; +export const getStripeProductPro = async () => (await client.getSecret('STRIPE_PRODUCT_PRO')).secretValue; +export const getStripeProductTeam = async () => (await client.getSecret('STRIPE_PRODUCT_TEAM')).secretValue; +export const getStripePublishableKey = async () => (await client.getSecret('STRIPE_PUBLISHABLE_KEY')).secretValue; +export const getStripeSecretKey = async () => (await client.getSecret('STRIPE_SECRET_KEY')).secretValue; +export const getStripeWebhookSecret = async () => (await client.getSecret('STRIPE_WEBHOOK_SECRET')).secretValue; + +export const getTelemetryEnabled = async () => (await client.getSecret('TELEMETRY_ENABLED')).secretValue !== 'false' && true; +export const getLoopsApiKey = async () => (await client.getSecret('LOOPS_API_KEY')).secretValue; +export const getSmtpConfigured = async () => (await client.getSecret('SMTP_HOST')).secretValue == '' || (await client.getSecret('SMTP_HOST')).secretValue == undefined ? false : true +export const getHttpsEnabled = async () => { + if ((await getNodeEnv()) != "production") { + // no https for anything other than prod + return false + } + + if ((await client.getSecret('HTTPS_ENABLED')).secretValue == undefined || (await client.getSecret('HTTPS_ENABLED')).secretValue == "") { + // default when no value present + return true + } + + return (await client.getSecret('HTTPS_ENABLED')).secretValue === 'true' && true +} \ No newline at end of file diff --git a/backend/src/config/request.ts b/backend/src/config/request.ts index 2a9a8279a..e13469657 100644 --- a/backend/src/config/request.ts +++ b/backend/src/config/request.ts @@ -1,10 +1,24 @@ import axios from 'axios'; import axiosRetry from 'axios-retry'; +import { + getLicenseServerKeyAuthToken, + setLicenseServerKeyAuthToken, + getLicenseKeyAuthToken, + setLicenseKeyAuthToken +} from './storage'; +import { + getLicenseKey, + getLicenseServerKey, + getLicenseServerUrl +} from './index'; -const axiosInstance = axios.create(); +// should have JWT to interact with the license server +export const licenseServerKeyRequest = axios.create(); +export const licenseKeyRequest = axios.create(); +export const standardRequest = axios.create(); // add retry functionality to the axios instance -axiosRetry(axiosInstance, { +axiosRetry(standardRequest, { retries: 3, retryDelay: axiosRetry.exponentialDelay, // exponential back-off delay between retries retryCondition: (error) => { @@ -13,4 +27,98 @@ axiosRetry(axiosInstance, { }, }); -export default axiosInstance; \ No newline at end of file +export const refreshLicenseServerKeyToken = async () => { + const licenseServerKey = await getLicenseServerKey(); + const licenseServerUrl = await getLicenseServerUrl(); + + const { data: { token } } = await standardRequest.post( + `${licenseServerUrl}/api/auth/v1/license-server-login`, {}, + { + headers: { + 'X-API-KEY': licenseServerKey + } + } + ); + + setLicenseServerKeyAuthToken(token); + + return token; +} + +export const refreshLicenseKeyToken = async () => { + const licenseKey = await getLicenseKey(); + const licenseServerUrl = await getLicenseServerUrl(); + + const { data: { token } } = await standardRequest.post( + `${licenseServerUrl}/api/auth/v1/license-login`, {}, + { + headers: { + 'X-API-KEY': licenseKey + } + } + ); + + setLicenseKeyAuthToken(token); + + return token; +} + +licenseServerKeyRequest.interceptors.request.use((config) => { + const token = getLicenseServerKeyAuthToken(); + + if (token && config.headers) { + // eslint-disable-next-line no-param-reassign + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}, (err) => { + return Promise.reject(err); +}); + +licenseServerKeyRequest.interceptors.response.use((response) => { + return response +}, async function (err) { + const originalRequest = err.config; + + if (err.response.status === 401 && !originalRequest._retry) { + originalRequest._retry = true; + + // refresh + const token = await refreshLicenseServerKeyToken(); + + axios.defaults.headers.common['Authorization'] = 'Bearer ' + token; + return licenseServerKeyRequest(originalRequest); + } + + return Promise.reject(err); +}); + +licenseKeyRequest.interceptors.request.use((config) => { + const token = getLicenseKeyAuthToken(); + + if (token && config.headers) { + // eslint-disable-next-line no-param-reassign + config.headers.Authorization = `Bearer ${token}`; + } + return config; +}, (err) => { + return Promise.reject(err); +}); + +licenseKeyRequest.interceptors.response.use((response) => { + return response +}, async function (err) { + const originalRequest = err.config; + + if (err.response.status === 401 && !originalRequest._retry) { + originalRequest._retry = true; + + // refresh + const token = await refreshLicenseKeyToken(); + + axios.defaults.headers.common['Authorization'] = 'Bearer ' + token; + return licenseKeyRequest(originalRequest); + } + + return Promise.reject(err); +}); \ No newline at end of file diff --git a/backend/src/config/storage.ts b/backend/src/config/storage.ts new file mode 100644 index 000000000..5638561ac --- /dev/null +++ b/backend/src/config/storage.ts @@ -0,0 +1,30 @@ +const MemoryLicenseServerKeyTokenStorage = () => { + let authToken: string; + + return { + setToken: (token: string) => { + authToken = token; + }, + getToken: () => authToken + }; +}; + +const MemoryLicenseKeyTokenStorage = () => { + let authToken: string; + + return { + setToken: (token: string) => { + authToken = token; + }, + getToken: () => authToken + }; +}; + +const licenseServerTokenStorage = MemoryLicenseServerKeyTokenStorage(); +const licenseTokenStorage = MemoryLicenseKeyTokenStorage(); + +export const getLicenseServerKeyAuthToken = licenseServerTokenStorage.getToken; +export const setLicenseServerKeyAuthToken = licenseServerTokenStorage.setToken; + +export const getLicenseKeyAuthToken = licenseTokenStorage.getToken; +export const setLicenseKeyAuthToken = licenseTokenStorage.setToken; \ No newline at end of file diff --git a/backend/src/controllers/v1/authController.ts b/backend/src/controllers/v1/authController.ts index 3c6ec523a..8a70e016e 100644 --- a/backend/src/controllers/v1/authController.ts +++ b/backend/src/controllers/v1/authController.ts @@ -1,29 +1,39 @@ -import * as Sentry from '@sentry/node'; import { Request, Response } from 'express'; +import fs from 'fs'; +import path from 'path'; import jwt from 'jsonwebtoken'; import * as bigintConversion from 'bigint-conversion'; // eslint-disable-next-line @typescript-eslint/no-var-requires const jsrp = require('jsrp'); -import { User, LoginSRPDetail } from '../../models'; +import { + User, + LoginSRPDetail, + TokenVersion +} from '../../models'; import { createToken, issueAuthTokens, clearTokens } from '../../helpers/auth'; import { checkUserDevice } from '../../helpers/user'; import { ACTION_LOGIN, - ACTION_LOGOUT + ACTION_LOGOUT, + AUTH_MODE_JWT } from '../../variables'; -import { BadRequestError } from '../../utils/errors'; +import { + BadRequestError, + UnauthorizedRequestError +} from '../../utils/errors'; import { EELogService } from '../../ee/services'; -import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this +import { getChannelFromUserAgent } from '../../utils/posthog'; import { - getNodeEnv, getJwtRefreshSecret, getJwtAuthLifetime, - getJwtAuthSecret + getJwtAuthSecret, + getHttpsEnabled } from '../../config'; declare module 'jsonwebtoken' { export interface UserIDJwtPayload extends jwt.JwtPayload { userId: string; + refreshVersion?: number; } } @@ -34,47 +44,39 @@ declare module 'jsonwebtoken' { * @returns */ export const login1 = async (req: Request, res: Response) => { - try { - const { - email, - clientPublicKey - }: { email: string; clientPublicKey: string } = req.body; + const { + email, + clientPublicKey + }: { email: string; clientPublicKey: string } = req.body; - const user = await User.findOne({ - email - }).select('+salt +verifier'); + const user = await User.findOne({ + email + }).select('+salt +verifier'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier + }, + async () => { + // generate server-side public key + const serverPublicKey = server.getPublicKey(); - await LoginSRPDetail.findOneAndReplace({ email: email }, { - email: email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt), - }, { upsert: true, returnNewDocument: false }) + await LoginSRPDetail.findOneAndReplace({ email: email }, { + email: email, + clientPublicKey: clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt), + }, { upsert: true, returnNewDocument: false }) - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to start authentication process' - }); - } + return res.status(200).send({ + serverPublicKey, + salt: user.salt + }); + } + ); }; /** @@ -85,84 +87,80 @@ export const login1 = async (req: Request, res: Response) => { * @returns */ export const login2 = async (req: Request, res: Response) => { - try { - const { email, clientProof } = req.body; - const user = await User.findOne({ - email - }).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag'); + const { email, clientProof } = req.body; + const user = await User.findOne({ + email + }).select('+salt +verifier +publicKey +encryptedPrivateKey +iv +tag'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email }) + const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: email }) - if (!loginSRPDetailFromDB) { - return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) - } + if (!loginSRPDetailFromDB) { + return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) + } - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: loginSRPDetailFromDB.serverBInt + }, + async () => { + server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // issue tokens + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + // issue tokens - await checkUserDevice({ - user, - ip: req.ip, - userAgent: req.headers['user-agent'] ?? '' - }); + await checkUserDevice({ + user, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); - const tokens = await issueAuthTokens({ userId: user._id.toString() }); + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); - // store (refresh) token in httpOnly cookie - res.cookie('jid', tokens.refreshToken, { - httpOnly: true, - path: '/', - sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false - }); + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); - const loginAction = await EELogService.createAction({ - name: ACTION_LOGIN, - userId: user._id - }); - - loginAction && await EELogService.createLog({ - userId: user._id, - actions: [loginAction], - channel: getChannelFromUserAgent(req.headers['user-agent']), - ipAddress: req.ip - }); - - // return (access) token in response - return res.status(200).send({ - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - }); - } + const loginAction = await EELogService.createAction({ + name: ACTION_LOGIN, + userId: user._id + }); - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' + loginAction && await EELogService.createLog({ + userId: user._id, + actions: [loginAction], + channel: getChannelFromUserAgent(req.headers['user-agent']), + ipAddress: req.realIP + }); + + // return (access) token in response + return res.status(200).send({ + token: tokens.token, + publicKey: user.publicKey, + encryptedPrivateKey: user.encryptedPrivateKey, + iv: user.iv, + tag: user.tag }); } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' - }); - } + + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } + ); }; /** @@ -172,44 +170,59 @@ export const login2 = async (req: Request, res: Response) => { * @returns */ export const logout = async (req: Request, res: Response) => { - try { - await clearTokens({ - userId: req.user._id.toString() - }); - - // clear httpOnly cookie - res.cookie('jid', '', { - httpOnly: true, - path: '/', - sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false - }); - - const logoutAction = await EELogService.createAction({ - name: ACTION_LOGOUT, - userId: req.user._id - }); - - logoutAction && await EELogService.createLog({ - userId: req.user._id, - actions: [logoutAction], - channel: getChannelFromUserAgent(req.headers['user-agent']), - ipAddress: req.ip - }); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to logout' - }); + if (req.authData.authMode === AUTH_MODE_JWT && req.authData.authPayload instanceof User && req.authData.tokenVersionId) { + await clearTokens(req.authData.tokenVersionId) } + // clear httpOnly cookie + res.cookie('jid', '', { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: (await getHttpsEnabled()) as boolean + }); + + const logoutAction = await EELogService.createAction({ + name: ACTION_LOGOUT, + userId: req.user._id + }); + + logoutAction && await EELogService.createLog({ + userId: req.user._id, + actions: [logoutAction], + channel: getChannelFromUserAgent(req.headers['user-agent']), + ipAddress: req.realIP + }); + return res.status(200).send({ message: 'Successfully logged out.' }); }; +export const getCommonPasswords = async (req: Request, res: Response) => { + const commonPasswords = fs.readFileSync( + path.resolve(__dirname, '../../data/' + 'common_passwords.txt'), + 'utf8' + ).split('\n'); + + return res.status(200).send(commonPasswords); +} + +export const revokeAllSessions = async (req: Request, res: Response) => { + await TokenVersion.updateMany({ + user: req.user._id + }, { + $inc: { + refreshVersion: 1, + accessVersion: 1 + } + }); + + return res.status(200).send({ + message: 'Successfully revoked all sessions.' + }); +} + /** * Return user is authenticated * @param req @@ -223,47 +236,55 @@ export const checkAuth = async (req: Request, res: Response) => { } /** - * Return new token by redeeming refresh token + * Return new JWT access token by first validating the refresh token * @param req * @param res * @returns */ export const getNewToken = async (req: Request, res: Response) => { - try { - const refreshToken = req.cookies.jid; + const refreshToken = req.cookies.jid; - if (!refreshToken) { - throw new Error('Failed to find token in request cookies'); - } - - const decodedToken = ( - jwt.verify(refreshToken, getJwtRefreshSecret()) - ); - - const user = await User.findOne({ - _id: decodedToken.userId - }).select('+publicKey'); - - if (!user) throw new Error('Failed to authenticate unfound user'); - if (!user?.publicKey) - throw new Error('Failed to authenticate not fully set up account'); - - const token = createToken({ - payload: { - userId: decodedToken.userId - }, - expiresIn: getJwtAuthLifetime(), - secret: getJwtAuthSecret() - }); - - return res.status(200).send({ - token - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Invalid request' - }); + if (!refreshToken) { + throw new Error('Failed to find refresh token in request cookies'); } + + const decodedToken = ( + jwt.verify(refreshToken, await getJwtRefreshSecret()) + ); + + const user = await User.findOne({ + _id: decodedToken.userId + }).select('+publicKey +refreshVersion +accessVersion'); + + if (!user) throw new Error('Failed to authenticate unfound user'); + if (!user?.publicKey) + throw new Error('Failed to authenticate not fully set up account'); + + const tokenVersion = await TokenVersion.findById(decodedToken.tokenVersionId); + + if (!tokenVersion) throw UnauthorizedRequestError({ + message: 'Failed to validate refresh token' + }); + + if (decodedToken.refreshVersion !== tokenVersion.refreshVersion) throw BadRequestError({ + message: 'Failed to validate refresh token' + }); + + const token = createToken({ + payload: { + userId: decodedToken.userId, + tokenVersionId: tokenVersion._id.toString(), + accessVersion: tokenVersion.refreshVersion + }, + expiresIn: await getJwtAuthLifetime(), + secret: await getJwtAuthSecret() + }); + + return res.status(200).send({ + token + }); }; + +export const handleAuthProviderCallback = (req: Request, res: Response) => { + res.redirect(`/login/provider/success?token=${encodeURIComponent(req.providerAuthToken)}`); +} diff --git a/backend/src/controllers/v1/botController.ts b/backend/src/controllers/v1/botController.ts index ab86897cb..f155f58a5 100644 --- a/backend/src/controllers/v1/botController.ts +++ b/backend/src/controllers/v1/botController.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Bot, BotKey } from '../../models'; import { createBot } from '../../helpers/bot'; @@ -16,33 +16,24 @@ interface BotKey { * @returns */ export const getBotByWorkspaceId = async (req: Request, res: Response) => { - let bot; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - bot = await Bot.findOne({ - workspace: workspaceId - }); - - if (!bot) { - // case: bot doesn't exist for workspace with id [workspaceId] - // -> create a new bot and return it - bot = await createBot({ - name: 'Infisical Bot', - workspaceId - }); - } - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get bot for workspace' - }); - } + let bot = await Bot.findOne({ + workspace: workspaceId + }); + + if (!bot) { + // case: bot doesn't exist for workspace with id [workspaceId] + // -> create a new bot and return it + bot = await createBot({ + name: 'Infisical Bot', + workspaceId: new Types.ObjectId(workspaceId) + }); + } - return res.status(200).send({ - bot - }); + return res.status(200).send({ + bot + }); }; /** @@ -52,54 +43,44 @@ export const getBotByWorkspaceId = async (req: Request, res: Response) => { * @returns */ export const setBotActiveState = async (req: Request, res: Response) => { - let bot; - try { - const { isActive, botKey }: { isActive: boolean, botKey: BotKey } = req.body; - - if (isActive) { - // bot state set to active -> share workspace key with bot - if (!botKey?.encryptedKey || !botKey?.nonce) { - return res.status(400).send({ - message: 'Failed to set bot state to active - missing bot key' - }); - } - - await BotKey.findOneAndUpdate({ - workspace: req.bot.workspace - }, { - encryptedKey: botKey.encryptedKey, - nonce: botKey.nonce, - sender: req.user._id, - bot: req.bot._id, - workspace: req.bot.workspace - }, { - upsert: true, - new: true - }); - } else { - // case: bot state set to inactive -> delete bot's workspace key - await BotKey.deleteOne({ - bot: req.bot._id + const { isActive, botKey }: { isActive: boolean, botKey: BotKey } = req.body; + + if (isActive) { + // bot state set to active -> share workspace key with bot + if (!botKey?.encryptedKey || !botKey?.nonce) { + return res.status(400).send({ + message: 'Failed to set bot state to active - missing bot key' }); } - - bot = await Bot.findOneAndUpdate({ - _id: req.bot._id + + await BotKey.findOneAndUpdate({ + workspace: req.bot.workspace }, { - isActive + encryptedKey: botKey.encryptedKey, + nonce: botKey.nonce, + sender: req.user._id, + bot: req.bot._id, + workspace: req.bot.workspace }, { + upsert: true, new: true }); - - if (!bot) throw new Error('Failed to update bot active state'); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to update bot active state' - }); - } + } else { + // case: bot state set to inactive -> delete bot's workspace key + await BotKey.deleteOne({ + bot: req.bot._id + }); + } + + let bot = await Bot.findOneAndUpdate({ + _id: req.bot._id + }, { + isActive + }, { + new: true + }); + + if (!bot) throw new Error('Failed to update bot active state'); return res.status(200).send({ bot diff --git a/backend/src/controllers/v1/integrationAuthController.ts b/backend/src/controllers/v1/integrationAuthController.ts index da8fc5570..fc79e22cf 100644 --- a/backend/src/controllers/v1/integrationAuthController.ts +++ b/backend/src/controllers/v1/integrationAuthController.ts @@ -1,45 +1,40 @@ import { Request, Response } from 'express'; import { Types } from 'mongoose'; -import * as Sentry from '@sentry/node'; import { IntegrationAuth, Bot } from '../../models'; -import { INTEGRATION_SET, getIntegrationOptions as getIntegrationOptionsFunc } from '../../variables'; +import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_UTF8, INTEGRATION_SET, getIntegrationOptions as getIntegrationOptionsFunc } from '../../variables'; import { IntegrationService } from '../../services'; import { getApps, getTeams, revokeAccess } from '../../integrations'; +import { + INTEGRATION_VERCEL_API_URL, + INTEGRATION_RAILWAY_API_URL +} from '../../variables'; +import { standardRequest } from '../../config/request'; /*** * Return integration authorization with id [integrationAuthId] */ export const getIntegrationAuth = async (req: Request, res: Response) => { - let integrationAuth; - try { - const { integrationAuthId } = req.params; - integrationAuth = await IntegrationAuth.findById(integrationAuthId); - - if (!integrationAuth) return res.status(400).send({ - message: 'Failed to find integration authorization' - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get integration authorization' - }); - } - + const { integrationAuthId } = req.params; + const integrationAuth = await IntegrationAuth.findById(integrationAuthId); + + if (!integrationAuth) return res.status(400).send({ + message: 'Failed to find integration authorization' + }); + return res.status(200).send({ integrationAuth }); } export const getIntegrationOptions = async (req: Request, res: Response) => { - const INTEGRATION_OPTIONS = getIntegrationOptionsFunc(); + const INTEGRATION_OPTIONS = await getIntegrationOptionsFunc(); return res.status(200).send({ integrationOptions: INTEGRATION_OPTIONS, @@ -56,33 +51,25 @@ export const oAuthExchange = async ( req: Request, res: Response ) => { - try { - const { workspaceId, code, integration } = req.body; - if (!INTEGRATION_SET.has(integration)) - throw new Error('Failed to validate integration'); - - const environments = req.membership.workspace?.environments || []; - if(environments.length === 0){ - throw new Error("Failed to get environments") - } - - const integrationAuth = await IntegrationService.handleOAuthExchange({ - workspaceId, - integration, - code, - environment: environments[0].slug, - }); - - return res.status(200).send({ - integrationAuth - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get OAuth2 code-token exchange' - }); - } + const { workspaceId, code, integration } = req.body; + if (!INTEGRATION_SET.has(integration)) + throw new Error('Failed to validate integration'); + + const environments = req.membership.workspace?.environments || []; + if(environments.length === 0){ + throw new Error("Failed to get environments") + } + + const integrationAuth = await IntegrationService.handleOAuthExchange({ + workspaceId, + integration, + code, + environment: environments[0].slug, + }); + + return res.status(200).send({ + integrationAuth + }); }; /** @@ -99,53 +86,53 @@ export const saveIntegrationAccessToken = async ( // TODO: check if access token is valid for each integration let integrationAuth; - try { - const { - workspaceId, - accessId, - accessToken, - integration - }: { - workspaceId: string; - accessId: string | null; - accessToken: string; - integration: string; - } = req.body; + const { + workspaceId, + accessId, + accessToken, + url, + namespace, + integration + }: { + workspaceId: string; + accessId: string | null; + accessToken: string; + url: string; + namespace: string; + integration: string; + } = req.body; - const bot = await Bot.findOne({ - workspace: new Types.ObjectId(workspaceId), - isActive: true - }); - - if (!bot) throw new Error('Bot must be enabled to save integration access token'); + const bot = await Bot.findOne({ + workspace: new Types.ObjectId(workspaceId), + isActive: true + }); + + if (!bot) throw new Error('Bot must be enabled to save integration access token'); - integrationAuth = await IntegrationAuth.findOneAndUpdate({ - workspace: new Types.ObjectId(workspaceId), - integration - }, { - workspace: new Types.ObjectId(workspaceId), - integration - }, { - new: true, - upsert: true - }); - - // encrypt and save integration access details - integrationAuth = await IntegrationService.setIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString(), - accessId, - accessToken, - accessExpiresAt: undefined - }); - - if (!integrationAuth) throw new Error('Failed to save integration access token'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to save access token for integration' - }); - } + integrationAuth = await IntegrationAuth.findOneAndUpdate({ + workspace: new Types.ObjectId(workspaceId), + integration + }, { + workspace: new Types.ObjectId(workspaceId), + integration, + url, + namespace, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }, { + new: true, + upsert: true + }); + + // encrypt and save integration access details + integrationAuth = await IntegrationService.setIntegrationAuthAccess({ + integrationAuthId: integrationAuth._id.toString(), + accessId, + accessToken, + accessExpiresAt: undefined + }); + + if (!integrationAuth) throw new Error('Failed to save integration access token'); return res.status(200).send({ integrationAuth @@ -159,22 +146,13 @@ export const saveIntegrationAccessToken = async ( * @returns */ export const getIntegrationAuthApps = async (req: Request, res: Response) => { - let apps; - try { - const teamId = req.query.teamId as string; - - apps = await getApps({ - integrationAuth: req.integrationAuth, - accessToken: req.accessToken, - ...teamId && { teamId } - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get integration authorization applications", - }); - } + const teamId = req.query.teamId as string; + + const apps = await getApps({ + integrationAuth: req.integrationAuth, + accessToken: req.accessToken, + ...teamId && { teamId } + }); return res.status(200).send({ apps @@ -188,22 +166,203 @@ export const getIntegrationAuthApps = async (req: Request, res: Response) => { * @returns */ export const getIntegrationAuthTeams = async (req: Request, res: Response) => { - let teams; - try { - teams = await getTeams({ - integrationAuth: req.integrationAuth, - accessToken: req.accessToken + const teams = await getTeams({ + integrationAuth: req.integrationAuth, + accessToken: req.accessToken + }); + + return res.status(200).send({ + teams + }); +} + +/** + * Return list of available Vercel (preview) branches for Vercel project with + * id [appId] + * @param req + * @param res + */ +export const getIntegrationAuthVercelBranches = async (req: Request, res: Response) => { + const { integrationAuthId } = req.params; + const appId = req.query.appId as string; + + interface VercelBranch { + ref: string; + lastCommit: string; + isProtected: boolean; + } + + const params = new URLSearchParams({ + projectId: appId, + ...(req.integrationAuth.teamId ? { + teamId: req.integrationAuth.teamId + } : {}) + }); + + let branches: string[] = []; + + if (appId && appId !== '') { + const { data }: { data: VercelBranch[] } = await standardRequest.get( + `${INTEGRATION_VERCEL_API_URL}/v1/integrations/git-branches`, + { + params, + headers: { + Authorization: `Bearer ${req.accessToken}`, + 'Accept-Encoding': 'application/json' + } + } + ); + + branches = data.map((b) => b.ref); + } + + return res.status(200).send({ + branches + }); +} + +/** + * Return list of Railway environments for Railway project with + * id [appId] + * @param req + * @param res + */ +export const getIntegrationAuthRailwayEnvironments = async (req: Request, res: Response) => { + const { integrationAuthId } = req.params; + const appId = req.query.appId as string; + + interface RailwayEnvironment { + node: { + id: string; + name: string; + isEphemeral: boolean; + } + } + + interface Environment { + environmentId: string; + name: string; + } + + let environments: Environment[] = []; + + if (appId && appId !== '') { + const query = ` + query GetEnvironments($projectId: String!, $after: String, $before: String, $first: Int, $isEphemeral: Boolean, $last: Int) { + environments(projectId: $projectId, after: $after, before: $before, first: $first, isEphemeral: $isEphemeral, last: $last) { + edges { + node { + id + name + isEphemeral + } + } + } + } + `; + + const variables = { + projectId: appId + } + + const { data: { data: { environments: { edges } } } } = await standardRequest.post(INTEGRATION_RAILWAY_API_URL, { + query, + variables, + }, { + headers: { + 'Authorization': `Bearer ${req.accessToken}`, + 'Content-Type': 'application/json', + }, }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get integration authorization teams" + + environments = edges.map((e: RailwayEnvironment) => { + return ({ + name: e.node.name, + environmentId: e.node.id + }); }); } return res.status(200).send({ - teams + environments + }); +} + +/** + * Return list of Railway services for Railway project with id + * [appId] + * @param req + * @param res + */ +export const getIntegrationAuthRailwayServices = async (req: Request, res: Response) => { + const { integrationAuthId } = req.params; + const appId = req.query.appId as string; + + interface RailwayService { + node: { + id: string; + name: string; + } + } + + interface Service { + name: string; + serviceId: string; + } + + let services: Service[] = []; + + const query = ` + query project($id: String!) { + project(id: $id) { + createdAt + deletedAt + id + description + expiredAt + isPublic + isTempProject + isUpdatable + name + prDeploys + teamId + updatedAt + upstreamUrl + services { + edges { + node { + id + name + } + } + } + } + } + `; + + if (appId && appId !== '') { + const variables = { + id: appId + } + + const { data: { data: { project: { services: { edges } } } } } = await standardRequest.post(INTEGRATION_RAILWAY_API_URL, { + query, + variables + }, { + headers: { + 'Authorization': `Bearer ${req.accessToken}`, + 'Content-Type': 'application/json', + }, + }); + + services = edges.map((e: RailwayService) => ({ + name: e.node.name, + serviceId: e.node.id + })); + } + + return res.status(200).send({ + services }); } @@ -214,19 +373,10 @@ export const getIntegrationAuthTeams = async (req: Request, res: Response) => { * @returns */ export const deleteIntegrationAuth = async (req: Request, res: Response) => { - let integrationAuth; - try { - integrationAuth = await revokeAccess({ - integrationAuth: req.integrationAuth, - accessToken: req.accessToken, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to delete integration authorization", - }); - } + const integrationAuth = await revokeAccess({ + integrationAuth: req.integrationAuth, + accessToken: req.accessToken, + }); return res.status(200).send({ integrationAuth, diff --git a/backend/src/controllers/v1/integrationController.ts b/backend/src/controllers/v1/integrationController.ts index 827ce21b9..5119761d0 100644 --- a/backend/src/controllers/v1/integrationController.ts +++ b/backend/src/controllers/v1/integrationController.ts @@ -1,6 +1,5 @@ import { Request, Response } from 'express'; import { Types } from 'mongoose'; -import * as Sentry from '@sentry/node'; import { Integration } from '../../models'; @@ -14,54 +13,50 @@ import { eventPushSecrets } from '../../events'; * @returns */ export const createIntegration = async (req: Request, res: Response) => { - let integration; + const { + integrationAuthId, + app, + appId, + isActive, + sourceEnvironment, + targetEnvironment, + targetEnvironmentId, + targetService, + targetServiceId, + owner, + path, + region + } = req.body; + + // TODO: validate [sourceEnvironment] and [targetEnvironment] - try { - const { - integrationAuthId, - app, - appId, - isActive, - sourceEnvironment, - targetEnvironment, - owner, - path, - region - } = req.body; - - // TODO: validate [sourceEnvironment] and [targetEnvironment] - - // initialize new integration after saving integration access token - integration = await new Integration({ - workspace: req.integrationAuth.workspace._id, - environment: sourceEnvironment, - isActive, - app, - appId, - targetEnvironment, - owner, - path, - region, - integration: req.integrationAuth.integration, - integrationAuth: new Types.ObjectId(integrationAuthId) - }).save(); - - if (integration) { - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: integration.workspace.toString() - }) - }); - } - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to create integration' - }); - } + // initialize new integration after saving integration access token + const integration = await new Integration({ + workspace: req.integrationAuth.workspace._id, + environment: sourceEnvironment, + isActive, + app, + appId, + targetEnvironment, + targetEnvironmentId, + targetService, + targetServiceId, + owner, + path, + region, + integration: req.integrationAuth.integration, + integrationAuth: new Types.ObjectId(integrationAuthId) + }).save(); + + if (integration) { + // trigger event - push secrets + EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: integration.workspace, + environment: sourceEnvironment + }) + }); + } return res.status(200).send({ integration, @@ -75,51 +70,43 @@ export const createIntegration = async (req: Request, res: Response) => { * @returns */ export const updateIntegration = async (req: Request, res: Response) => { - let integration; // TODO: add integration-specific validation to ensure that each // integration has the correct fields populated in [Integration] - try { - const { + const { + environment, + isActive, + app, + appId, + targetEnvironment, + owner, // github-specific integration param + } = req.body; + + const integration = await Integration.findOneAndUpdate( + { + _id: req.integration._id, + }, + { environment, isActive, app, appId, targetEnvironment, - owner, // github-specific integration param - } = req.body; - - integration = await Integration.findOneAndUpdate( - { - _id: req.integration._id, - }, - { - environment, - isActive, - app, - appId, - targetEnvironment, - owner, - }, - { - new: true, - } - ); - - if (integration) { - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: integration.workspace.toString(), - }), - }); + owner, + }, + { + new: true, } - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to update integration", + ); + + if (integration) { + // trigger event - push secrets + EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: integration.workspace, + environment + }), }); } @@ -136,22 +123,13 @@ export const updateIntegration = async (req: Request, res: Response) => { * @returns */ export const deleteIntegration = async (req: Request, res: Response) => { - let integration; - try { - const { integrationId } = req.params; + const { integrationId } = req.params; - integration = await Integration.findOneAndDelete({ - _id: integrationId, - }); + const integration = await Integration.findOneAndDelete({ + _id: integrationId, + }); - if (!integration) throw new Error("Failed to find integration"); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to delete integration", - }); - } + if (!integration) throw new Error("Failed to find integration"); return res.status(200).send({ integration, diff --git a/backend/src/controllers/v1/keyController.ts b/backend/src/controllers/v1/keyController.ts index ffcb16d9c..beb4d0d07 100644 --- a/backend/src/controllers/v1/keyController.ts +++ b/backend/src/controllers/v1/keyController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { Key } from '../../models'; import { findMembership } from '../../helpers/membership'; @@ -11,34 +10,26 @@ import { findMembership } from '../../helpers/membership'; * @returns */ export const uploadKey = async (req: Request, res: Response) => { - try { - const { workspaceId } = req.params; - const { key } = req.body; + const { workspaceId } = req.params; + const { key } = req.body; - // validate membership of receiver - const receiverMembership = await findMembership({ - user: key.userId, - workspace: workspaceId - }); + // validate membership of receiver + const receiverMembership = await findMembership({ + user: key.userId, + workspace: workspaceId + }); - if (!receiverMembership) { - throw new Error('Failed receiver membership validation for workspace'); - } + if (!receiverMembership) { + throw new Error('Failed receiver membership validation for workspace'); + } - await new Key({ - encryptedKey: key.encryptedKey, - nonce: key.nonce, - sender: req.user._id, - receiver: key.userId, - workspace: workspaceId - }).save(); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to upload key to workspace' - }); - } + await new Key({ + encryptedKey: key.encryptedKey, + nonce: key.nonce, + sender: req.user._id, + receiver: key.userId, + workspace: workspaceId + }).save(); return res.status(200).send({ message: 'Successfully uploaded key to workspace' @@ -52,25 +43,16 @@ export const uploadKey = async (req: Request, res: Response) => { * @returns */ export const getLatestKey = async (req: Request, res: Response) => { - let latestKey; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - // get latest key - latestKey = await Key.find({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .limit(1) - .populate('sender', '+publicKey'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get latest key' - }); - } + // get latest key + const latestKey = await Key.find({ + workspace: workspaceId, + receiver: req.user._id + }) + .sort({ createdAt: -1 }) + .limit(1) + .populate('sender', '+publicKey'); const resObj: any = {}; @@ -79,4 +61,4 @@ export const getLatestKey = async (req: Request, res: Response) => { } return res.status(200).send(resObj); -}; \ No newline at end of file +}; diff --git a/backend/src/controllers/v1/membershipController.ts b/backend/src/controllers/v1/membershipController.ts index 436be9dc4..d7e512adb 100644 --- a/backend/src/controllers/v1/membershipController.ts +++ b/backend/src/controllers/v1/membershipController.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Request, Response } from 'express'; import { Membership, MembershipOrg, User, Key } from '../../models'; import { @@ -16,25 +15,16 @@ import { getSiteURL } from '../../config'; * @returns */ export const validateMembership = async (req: Request, res: Response) => { - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; + // validate membership + const membership = await findMembership({ + user: req.user._id, + workspace: workspaceId + }); - // validate membership - const membership = await findMembership({ - user: req.user._id, - workspace: workspaceId - }); - - if (!membership) { - throw new Error('Failed to validate membership'); - } - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed workspace connection check' - }); - } + if (!membership) { + throw new Error('Failed to validate membership'); + } return res.status(200).send({ message: 'Workspace membership confirmed' @@ -48,48 +38,39 @@ export const validateMembership = async (req: Request, res: Response) => { * @returns */ export const deleteMembership = async (req: Request, res: Response) => { - let deletedMembership; - try { - const { membershipId } = req.params; + const { membershipId } = req.params; - // check if membership to delete exists - const membershipToDelete = await Membership.findOne({ - _id: membershipId - }).populate('user'); + // check if membership to delete exists + const membershipToDelete = await Membership.findOne({ + _id: membershipId + }).populate('user'); - if (!membershipToDelete) { - throw new Error( - "Failed to delete workspace membership that doesn't exist" - ); - } + if (!membershipToDelete) { + throw new Error( + "Failed to delete workspace membership that doesn't exist" + ); + } - // check if user is a member and admin of the workspace - // whose membership we wish to delete - const membership = await Membership.findOne({ - user: req.user._id, - workspace: membershipToDelete.workspace - }); + // check if user is a member and admin of the workspace + // whose membership we wish to delete + const membership = await Membership.findOne({ + user: req.user._id, + workspace: membershipToDelete.workspace + }); - if (!membership) { - throw new Error('Failed to validate workspace membership'); - } + if (!membership) { + throw new Error('Failed to validate workspace membership'); + } - if (membership.role !== ADMIN) { - // user is not an admin member of the workspace - throw new Error('Insufficient role for deleting workspace membership'); - } + if (membership.role !== ADMIN) { + // user is not an admin member of the workspace + throw new Error('Insufficient role for deleting workspace membership'); + } - // delete workspace membership - deletedMembership = await deleteMember({ - membershipId: membershipToDelete._id.toString() - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete membership' - }); - } + // delete workspace membership + const deletedMembership = await deleteMember({ + membershipId: membershipToDelete._id.toString() + }); return res.status(200).send({ deletedMembership @@ -103,49 +84,40 @@ export const deleteMembership = async (req: Request, res: Response) => { * @returns */ export const changeMembershipRole = async (req: Request, res: Response) => { - let membershipToChangeRole; - try { - const { membershipId } = req.params; - const { role } = req.body; + const { membershipId } = req.params; + const { role } = req.body; - if (![ADMIN, MEMBER].includes(role)) { - throw new Error('Failed to validate role'); - } + if (![ADMIN, MEMBER].includes(role)) { + throw new Error('Failed to validate role'); + } - // validate target membership - membershipToChangeRole = await findMembership({ - _id: membershipId - }); + // validate target membership + const membershipToChangeRole = await findMembership({ + _id: membershipId + }); - if (!membershipToChangeRole) { - throw new Error('Failed to find membership to change role'); - } + if (!membershipToChangeRole) { + throw new Error('Failed to find membership to change role'); + } - // check if user is a member and admin of target membership's - // workspace - const membership = await findMembership({ - user: req.user._id, - workspace: membershipToChangeRole.workspace - }); + // check if user is a member and admin of target membership's + // workspace + const membership = await findMembership({ + user: req.user._id, + workspace: membershipToChangeRole.workspace + }); - if (!membership) { - throw new Error('Failed to validate membership'); - } + if (!membership) { + throw new Error('Failed to validate membership'); + } - if (membership.role !== ADMIN) { - // user is not an admin member of the workspace - throw new Error('Insufficient role for changing member roles'); - } + if (membership.role !== ADMIN) { + // user is not an admin member of the workspace + throw new Error('Insufficient role for changing member roles'); + } - membershipToChangeRole.role = role; - await membershipToChangeRole.save(); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to change membership role' - }); - } + membershipToChangeRole.role = role; + await membershipToChangeRole.save(); return res.status(200).send({ membership: membershipToChangeRole @@ -159,75 +131,66 @@ export const changeMembershipRole = async (req: Request, res: Response) => { * @returns */ export const inviteUserToWorkspace = async (req: Request, res: Response) => { - let invitee, latestKey; - try { - const { workspaceId } = req.params; - const { email }: { email: string } = req.body; + const { workspaceId } = req.params; + const { email }: { email: string } = req.body; - invitee = await User.findOne({ - email - }).select('+publicKey'); + const invitee = await User.findOne({ + email + }).select('+publicKey'); - if (!invitee || !invitee?.publicKey) - throw new Error('Failed to validate invitee'); + if (!invitee || !invitee?.publicKey) + throw new Error('Failed to validate invitee'); - // validate invitee's workspace membership - ensure member isn't - // already a member of the workspace - const inviteeMembership = await Membership.findOne({ - user: invitee._id, - workspace: workspaceId - }); + // validate invitee's workspace membership - ensure member isn't + // already a member of the workspace + const inviteeMembership = await Membership.findOne({ + user: invitee._id, + workspace: workspaceId + }); - if (inviteeMembership) - throw new Error('Failed to add existing member of workspace'); + if (inviteeMembership) + throw new Error('Failed to add existing member of workspace'); - // validate invitee's organization membership - ensure that only - // (accepted) organization members can be added to the workspace - const membershipOrg = await MembershipOrg.findOne({ - user: invitee._id, - organization: req.membership.workspace.organization, - status: ACCEPTED - }); + // validate invitee's organization membership - ensure that only + // (accepted) organization members can be added to the workspace + const membershipOrg = await MembershipOrg.findOne({ + user: invitee._id, + organization: req.membership.workspace.organization, + status: ACCEPTED + }); - if (!membershipOrg) - throw new Error("Failed to validate invitee's organization membership"); + if (!membershipOrg) + throw new Error("Failed to validate invitee's organization membership"); - // get latest key - latestKey = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .populate('sender', '+publicKey'); + // get latest key + const latestKey = await Key.findOne({ + workspace: workspaceId, + receiver: req.user._id + }) + .sort({ createdAt: -1 }) + .populate('sender', '+publicKey'); - // create new workspace membership - const m = await new Membership({ - user: invitee._id, - workspace: workspaceId, - role: MEMBER - }).save(); + // create new workspace membership + const m = await new Membership({ + user: invitee._id, + workspace: workspaceId, + role: MEMBER + }).save(); - await sendMail({ - template: 'workspaceInvitation.handlebars', - subjectLine: 'Infisical workspace invitation', - recipients: [invitee.email], - substitutions: { - inviterFirstName: req.user.firstName, - inviterEmail: req.user.email, - workspaceName: req.membership.workspace.name, - callback_url: getSiteURL() + '/login' - } - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to invite user to workspace' - }); - } + await sendMail({ + template: 'workspaceInvitation.handlebars', + subjectLine: 'Infisical workspace invitation', + recipients: [invitee.email], + substitutions: { + inviterFirstName: req.user.firstName, + inviterEmail: req.user.email, + workspaceName: req.membership.workspace.name, + callback_url: (await getSiteURL()) + '/login' + } + }); return res.status(200).send({ invitee, latestKey }); -}; \ No newline at end of file +}; diff --git a/backend/src/controllers/v1/membershipOrgController.ts b/backend/src/controllers/v1/membershipOrgController.ts index 5a2b41b2b..0d4c1436d 100644 --- a/backend/src/controllers/v1/membershipOrgController.ts +++ b/backend/src/controllers/v1/membershipOrgController.ts @@ -1,13 +1,15 @@ +import { Types } from 'mongoose'; import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { MembershipOrg, Organization, User } from '../../models'; import { deleteMembershipOrg as deleteMemberFromOrg } from '../../helpers/membershipOrg'; import { createToken } from '../../helpers/auth'; import { updateSubscriptionOrgQuantity } from '../../helpers/organization'; import { sendMail } from '../../helpers/nodemailer'; import { TokenService } from '../../services'; +import { EELicenseService } from '../../ee/services'; import { OWNER, ADMIN, MEMBER, ACCEPTED, INVITED, TOKEN_EMAIL_ORG_INVITATION } from '../../variables'; import { getSiteURL, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured } from '../../config'; +import { validateUserEmail } from '../../validation'; /** * Delete organization membership with id [membershipOrgId] from organization @@ -16,52 +18,43 @@ import { getSiteURL, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured * @returns */ export const deleteMembershipOrg = async (req: Request, res: Response) => { - let membershipOrgToDelete; - try { - const { membershipOrgId } = req.params; + const { membershipOrgId } = req.params; - // check if organization membership to delete exists - membershipOrgToDelete = await MembershipOrg.findOne({ - _id: membershipOrgId - }).populate('user'); + // check if organization membership to delete exists + const membershipOrgToDelete = await MembershipOrg.findOne({ + _id: membershipOrgId + }).populate('user'); - if (!membershipOrgToDelete) { - throw new Error( - "Failed to delete organization membership that doesn't exist" - ); - } + if (!membershipOrgToDelete) { + throw new Error( + "Failed to delete organization membership that doesn't exist" + ); + } - // check if user is a member and admin of the organization - // whose membership we wish to delete - const membershipOrg = await MembershipOrg.findOne({ - user: req.user._id, - organization: membershipOrgToDelete.organization - }); + // check if user is a member and admin of the organization + // whose membership we wish to delete + const membershipOrg = await MembershipOrg.findOne({ + user: req.user._id, + organization: membershipOrgToDelete.organization + }); - if (!membershipOrg) { - throw new Error('Failed to validate organization membership'); - } + if (!membershipOrg) { + throw new Error('Failed to validate organization membership'); + } - if (membershipOrg.role !== OWNER && membershipOrg.role !== ADMIN) { - // user is not an admin member of the organization - throw new Error('Insufficient role for deleting organization membership'); - } + if (membershipOrg.role !== OWNER && membershipOrg.role !== ADMIN) { + // user is not an admin member of the organization + throw new Error('Insufficient role for deleting organization membership'); + } - // delete organization membership - const deletedMembershipOrg = await deleteMemberFromOrg({ - membershipOrgId: membershipOrgToDelete._id.toString() - }); + // delete organization membership + const deletedMembershipOrg = await deleteMemberFromOrg({ + membershipOrgId: membershipOrgToDelete._id.toString() + }); - await updateSubscriptionOrgQuantity({ - organizationId: membershipOrg.organization.toString() - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete organization membership' - }); - } + await updateSubscriptionOrgQuantity({ + organizationId: membershipOrg.organization.toString() + }); return membershipOrgToDelete; }; @@ -77,14 +70,6 @@ export const changeMembershipOrgRole = async (req: Request, res: Response) => { // [membershipOrgId] let membershipToChangeRole; - // try { - // } catch (err) { - // Sentry.setUser({ email: req.user.email }); - // Sentry.captureException(err); - // return res.status(400).send({ - // message: 'Failed to change organization membership role' - // }); - // } return res.status(200).send({ membershipOrg: membershipToChangeRole @@ -100,103 +85,114 @@ export const changeMembershipOrgRole = async (req: Request, res: Response) => { */ export const inviteUserToOrganization = async (req: Request, res: Response) => { let invitee, inviteeMembershipOrg, completeInviteLink; - try { - const { organizationId, inviteeEmail } = req.body; - const host = req.headers.host; - const siteUrl = `${req.protocol}://${host}`; + const { organizationId, inviteeEmail } = req.body; + const host = req.headers.host; + const siteUrl = `${req.protocol}://${host}`; - // validate membership - const membershipOrg = await MembershipOrg.findOne({ - user: req.user._id, - organization: organizationId - }); + // validate membership + const membershipOrg = await MembershipOrg.findOne({ + user: req.user._id, + organization: organizationId + }); - if (!membershipOrg) { - throw new Error('Failed to validate organization membership'); - } + if (!membershipOrg) { + throw new Error('Failed to validate organization membership'); + } + + const plan = await EELicenseService.getPlan(organizationId); + + if (plan.memberLimit !== null) { + // case: limit imposed on number of members allowed + + if (plan.membersUsed >= plan.memberLimit) { + // case: number of members used exceeds the number of members allowed + return res.status(400).send({ + message: 'Failed to invite member due to member limit reached. Upgrade plan to invite more members.' + }); + } + } - invitee = await User.findOne({ - email: inviteeEmail - }).select('+publicKey'); + invitee = await User.findOne({ + email: inviteeEmail + }).select('+publicKey'); - if (invitee) { - // case: invitee is an existing user + if (invitee) { + // case: invitee is an existing user - inviteeMembershipOrg = await MembershipOrg.findOne({ - user: invitee._id, - organization: organizationId - }); + inviteeMembershipOrg = await MembershipOrg.findOne({ + user: invitee._id, + organization: organizationId + }); - if (inviteeMembershipOrg && inviteeMembershipOrg.status === ACCEPTED) { - throw new Error( - 'Failed to invite an existing member of the organization' - ); - } + if (inviteeMembershipOrg && inviteeMembershipOrg.status === ACCEPTED) { + throw new Error( + 'Failed to invite an existing member of the organization' + ); + } - if (!inviteeMembershipOrg) { - await new MembershipOrg({ - user: invitee, - inviteEmail: inviteeEmail, - organization: organizationId, - role: MEMBER, - status: invitee?.publicKey ? ACCEPTED : INVITED - }).save(); - } - } else { - // check if invitee has been invited before - inviteeMembershipOrg = await MembershipOrg.findOne({ - inviteEmail: inviteeEmail, - organization: organizationId - }); + if (!inviteeMembershipOrg) { + + await new MembershipOrg({ + user: invitee, + inviteEmail: inviteeEmail, + organization: organizationId, + role: MEMBER, + status: INVITED + }).save(); + } + } else { + // check if invitee has been invited before + inviteeMembershipOrg = await MembershipOrg.findOne({ + inviteEmail: inviteeEmail, + organization: organizationId + }); - if (!inviteeMembershipOrg) { - // case: invitee has never been invited before + if (!inviteeMembershipOrg) { + // case: invitee has never been invited before + + // validate that email is not disposable + validateUserEmail(inviteeEmail); - await new MembershipOrg({ - inviteEmail: inviteeEmail, - organization: organizationId, - role: MEMBER, - status: INVITED - }).save(); - } - } + await new MembershipOrg({ + inviteEmail: inviteeEmail, + organization: organizationId, + role: MEMBER, + status: INVITED + }).save(); + } + } - const organization = await Organization.findOne({ _id: organizationId }); + const organization = await Organization.findOne({ _id: organizationId }); - if (organization) { - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_ORG_INVITATION, - email: inviteeEmail, - organizationId: organization._id - }); + if (organization) { - await sendMail({ - template: 'organizationInvitation.handlebars', - subjectLine: 'Infisical organization invitation', - recipients: [inviteeEmail], - substitutions: { - inviterFirstName: req.user.firstName, - inviterEmail: req.user.email, - organizationName: organization.name, - email: inviteeEmail, - token, - callback_url: getSiteURL() + '/signupinvite' - } - }); + const token = await TokenService.createToken({ + type: TOKEN_EMAIL_ORG_INVITATION, + email: inviteeEmail, + organizationId: organization._id + }); - if (!getSmtpConfigured()) { - completeInviteLink = `${siteUrl + '/signupinvite'}?token=${token}&to=${inviteeEmail}` - } - } + await sendMail({ + template: 'organizationInvitation.handlebars', + subjectLine: 'Infisical organization invitation', + recipients: [inviteeEmail], + substitutions: { + inviterFirstName: req.user.firstName, + inviterEmail: req.user.email, + organizationName: organization.name, + email: inviteeEmail, + organizationId: organization._id.toString(), + token, + callback_url: (await getSiteURL()) + '/signupinvite' + } + }); - await updateSubscriptionOrgQuantity({ organizationId }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to send organization invite' - }); - } + if (!(await getSmtpConfigured())) { + completeInviteLink = `${siteUrl + '/signupinvite'}?token=${token}&to=${inviteeEmail}&organization_id=${organization._id}` + } + } + + await updateSubscriptionOrgQuantity({ organizationId }); return res.status(200).send({ message: `Sent an invite link to ${req.body.inviteeEmail}`, @@ -212,61 +208,62 @@ export const inviteUserToOrganization = async (req: Request, res: Response) => { * @returns */ export const verifyUserToOrganization = async (req: Request, res: Response) => { - let user, token; - try { - const { email, code } = req.body; + let user; + const { + email, + organizationId, + code + } = req.body; - user = await User.findOne({ email }).select('+publicKey'); + user = await User.findOne({ email }).select('+publicKey'); - const membershipOrg = await MembershipOrg.findOne({ - inviteEmail: email, - status: INVITED - }); + const membershipOrg = await MembershipOrg.findOne({ + inviteEmail: email, + status: INVITED, + organization: new Types.ObjectId(organizationId) + }); - if (!membershipOrg) - throw new Error('Failed to find any invitations for email'); + if (!membershipOrg) + throw new Error('Failed to find any invitations for email'); - await TokenService.validateToken({ - type: TOKEN_EMAIL_ORG_INVITATION, - email, - organizationId: membershipOrg.organization, - token: code - }); + await TokenService.validateToken({ + type: TOKEN_EMAIL_ORG_INVITATION, + email, + organizationId: membershipOrg.organization, + token: code + }); - if (user && user?.publicKey) { - // case: user has already completed account - // membership can be approved and redirected to login/dashboard - membershipOrg.status = ACCEPTED; - await membershipOrg.save(); + if (user && user?.publicKey) { + // case: user has already completed account + // membership can be approved and redirected to login/dashboard + membershipOrg.status = ACCEPTED; + await membershipOrg.save(); + + await updateSubscriptionOrgQuantity({ + organizationId + }); - return res.status(200).send({ - message: 'Successfully verified email', - user, - }); - } + return res.status(200).send({ + message: 'Successfully verified email', + user, + }); + } - if (!user) { - // initialize user account - user = await new User({ - email - }).save(); - } + if (!user) { + // initialize user account + user = await new User({ + email + }).save(); + } - // generate temporary signup token - token = createToken({ - payload: { - userId: user._id.toString() - }, - expiresIn: getJwtSignupLifetime(), - secret: getJwtSignupSecret() - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed email magic link verification for organization invitation' - }); - } + // generate temporary signup token + const token = createToken({ + payload: { + userId: user._id.toString() + }, + expiresIn: await getJwtSignupLifetime(), + secret: await getJwtSignupSecret() + }); return res.status(200).send({ message: 'Successfully verified email', diff --git a/backend/src/controllers/v1/organizationController.ts b/backend/src/controllers/v1/organizationController.ts index 00ad87b82..f0c73d75c 100644 --- a/backend/src/controllers/v1/organizationController.ts +++ b/backend/src/controllers/v1/organizationController.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Request, Response } from 'express'; import Stripe from 'stripe'; import { @@ -15,20 +14,12 @@ import _ from 'lodash'; import { getStripeSecretKey, getSiteURL } from '../../config'; export const getOrganizations = async (req: Request, res: Response) => { - let organizations; - try { - organizations = ( - await MembershipOrg.find({ - user: req.user._id - }).populate('organization') - ).map((m) => m.organization); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organizations' - }); - } + const organizations = ( + await MembershipOrg.find({ + user: req.user._id, + status: ACCEPTED + }).populate('organization') + ).map((m) => m.organization); return res.status(200).send({ organizations @@ -43,33 +34,24 @@ export const getOrganizations = async (req: Request, res: Response) => { * @returns */ export const createOrganization = async (req: Request, res: Response) => { - let organization; - try { - const { organizationName } = req.body; + const { organizationName } = req.body; - if (organizationName.length < 1) { - throw new Error('Organization names must be at least 1-character long'); - } + if (organizationName.length < 1) { + throw new Error('Organization names must be at least 1-character long'); + } - // create organization and add user as member - organization = await create({ - email: req.user.email, - name: organizationName - }); + // create organization and add user as member + const organization = await create({ + email: req.user.email, + name: organizationName + }); - await addMembershipsOrg({ - userIds: [req.user._id.toString()], - organizationId: organization._id.toString(), - roles: [OWNER], - statuses: [ACCEPTED] - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to create organization' - }); - } + await addMembershipsOrg({ + userIds: [req.user._id.toString()], + organizationId: organization._id.toString(), + roles: [OWNER], + statuses: [ACCEPTED] + }); return res.status(200).send({ organization @@ -83,17 +65,7 @@ export const createOrganization = async (req: Request, res: Response) => { * @returns */ export const getOrganization = async (req: Request, res: Response) => { - let organization; - try { - organization = req.membershipOrg.organization; - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to find organization' - }); - } - + const organization = req.organization return res.status(200).send({ organization }); @@ -106,20 +78,11 @@ export const getOrganization = async (req: Request, res: Response) => { * @returns */ export const getOrganizationMembers = async (req: Request, res: Response) => { - let users; - try { - const { organizationId } = req.params; + const { organizationId } = req.params; - users = await MembershipOrg.find({ - organization: organizationId - }).populate('user', '+publicKey'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organization members' - }); - } + const users = await MembershipOrg.find({ + organization: organizationId + }).populate('user', '+publicKey'); return res.status(200).send({ users @@ -136,35 +99,26 @@ export const getOrganizationWorkspaces = async ( req: Request, res: Response ) => { - let workspaces; - try { - const { organizationId } = req.params; + const { organizationId } = req.params; - const workspacesSet = new Set( - ( - await Workspace.find( - { - organization: organizationId - }, - '_id' - ) - ).map((w) => w._id.toString()) - ); + const workspacesSet = new Set( + ( + await Workspace.find( + { + organization: organizationId + }, + '_id' + ) + ).map((w) => w._id.toString()) + ); - workspaces = ( - await Membership.find({ - user: req.user._id - }).populate('workspace') - ) - .filter((m) => workspacesSet.has(m.workspace._id.toString())) - .map((m) => m.workspace); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get my workspaces' - }); - } + const workspaces = ( + await Membership.find({ + user: req.user._id + }).populate('workspace') + ) + .filter((m) => workspacesSet.has(m.workspace._id.toString())) + .map((m) => m.workspace); return res.status(200).send({ workspaces @@ -178,29 +132,20 @@ export const getOrganizationWorkspaces = async ( * @returns */ export const changeOrganizationName = async (req: Request, res: Response) => { - let organization; - try { - const { organizationId } = req.params; - const { name } = req.body; + const { organizationId } = req.params; + const { name } = req.body; - organization = await Organization.findOneAndUpdate( - { - _id: organizationId - }, - { - name - }, - { - new: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to change organization name' - }); - } + const organization = await Organization.findOneAndUpdate( + { + _id: organizationId + }, + { + name + }, + { + new: true + } + ); return res.status(200).send({ message: 'Successfully changed organization name', @@ -218,20 +163,11 @@ export const getOrganizationIncidentContacts = async ( req: Request, res: Response ) => { - let incidentContactsOrg; - try { - const { organizationId } = req.params; + const { organizationId } = req.params; - incidentContactsOrg = await IncidentContactOrg.find({ - organization: organizationId - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organization incident contacts' - }); - } + const incidentContactsOrg = await IncidentContactOrg.find({ + organization: organizationId + }); return res.status(200).send({ incidentContactsOrg @@ -248,23 +184,14 @@ export const addOrganizationIncidentContact = async ( req: Request, res: Response ) => { - let incidentContactOrg; - try { - const { organizationId } = req.params; - const { email } = req.body; + const { organizationId } = req.params; + const { email } = req.body; - incidentContactOrg = await IncidentContactOrg.findOneAndUpdate( - { email, organization: organizationId }, - { email, organization: organizationId }, - { upsert: true, new: true } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to add incident contact for organization' - }); - } + const incidentContactOrg = await IncidentContactOrg.findOneAndUpdate( + { email, organization: organizationId }, + { email, organization: organizationId }, + { upsert: true, new: true } + ); return res.status(200).send({ incidentContactOrg @@ -281,22 +208,13 @@ export const deleteOrganizationIncidentContact = async ( req: Request, res: Response ) => { - let incidentContactOrg; - try { - const { organizationId } = req.params; - const { email } = req.body; + const { organizationId } = req.params; + const { email } = req.body; - incidentContactOrg = await IncidentContactOrg.findOneAndDelete({ - email, - organization: organizationId - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete organization incident contact' - }); - } + const incidentContactOrg = await IncidentContactOrg.findOneAndDelete({ + email, + organization: organizationId + }); return res.status(200).send({ message: 'Successfully deleted organization incident contact', @@ -316,41 +234,33 @@ export const createOrganizationPortalSession = async ( res: Response ) => { let session; - try { - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: '2022-08-01' + }); - // check if there is a payment method on file - const paymentMethods = await stripe.paymentMethods.list({ - customer: req.membershipOrg.organization.customerId, - type: 'card' - }); + // check if there is a payment method on file + const paymentMethods = await stripe.paymentMethods.list({ + customer: req.organization.customerId, + type: 'card' + }); + + if (paymentMethods.data.length < 1) { + // case: no payment method on file + session = await stripe.checkout.sessions.create({ + customer: req.organization.customerId, + mode: 'setup', + payment_method_types: ['card'], + success_url: (await getSiteURL()) + '/dashboard', + cancel_url: (await getSiteURL()) + '/dashboard' + }); + } else { + session = await stripe.billingPortal.sessions.create({ + customer: req.organization.customerId, + return_url: (await getSiteURL()) + '/dashboard' + }); + } - if (paymentMethods.data.length < 1) { - // case: no payment method on file - session = await stripe.checkout.sessions.create({ - customer: req.membershipOrg.organization.customerId, - mode: 'setup', - payment_method_types: ['card'], - success_url: getSiteURL() + '/dashboard', - cancel_url: getSiteURL() + '/dashboard' - }); - } else { - session = await stripe.billingPortal.sessions.create({ - customer: req.membershipOrg.organization.customerId, - return_url: getSiteURL() + '/dashboard' - }); - } - - return res.status(200).send({ url: session.url }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to redirect to organization billing portal' - }); - } + return res.status(200).send({ url: session.url }); }; /** @@ -363,22 +273,13 @@ export const getOrganizationSubscriptions = async ( req: Request, res: Response ) => { - let subscriptions; - try { - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); - - subscriptions = await stripe.subscriptions.list({ - customer: req.membershipOrg.organization.customerId - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organization subscriptions' - }); - } + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: '2022-08-01' + }); + + const subscriptions = await stripe.subscriptions.list({ + customer: req.organization.customerId + }); return res.status(200).send({ subscriptions @@ -424,4 +325,4 @@ export const getOrganizationMembersAndTheirWorkspaces = async ( }); return res.json(userToWorkspaceIds); -}; \ No newline at end of file +}; diff --git a/backend/src/controllers/v1/passwordController.ts b/backend/src/controllers/v1/passwordController.ts index fed24419c..da1903eba 100644 --- a/backend/src/controllers/v1/passwordController.ts +++ b/backend/src/controllers/v1/passwordController.ts @@ -1,15 +1,25 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; // eslint-disable-next-line @typescript-eslint/no-var-requires const jsrp = require('jsrp'); import * as bigintConversion from 'bigint-conversion'; import { User, BackupPrivateKey, LoginSRPDetail } from '../../models'; -import { createToken } from '../../helpers/auth'; -import { sendMail } from '../../helpers/nodemailer'; +import { + createToken, + sendMail, + clearTokens +} from '../../helpers'; import { TokenService } from '../../services'; -import { TOKEN_EMAIL_PASSWORD_RESET } from '../../variables'; +import { + TOKEN_EMAIL_PASSWORD_RESET, + AUTH_MODE_JWT +} from '../../variables'; import { BadRequestError } from '../../utils/errors'; -import { getSiteURL, getJwtSignupLifetime, getJwtSignupSecret } from '../../config'; +import { + getSiteURL, + getJwtSignupLifetime, + getJwtSignupSecret, + getHttpsEnabled +} from '../../config'; /** * Password reset step 1: Send email verification link to email [email] @@ -20,43 +30,35 @@ import { getSiteURL, getJwtSignupLifetime, getJwtSignupSecret } from '../../conf */ export const emailPasswordReset = async (req: Request, res: Response) => { let email: string; - try { - email = req.body.email; + email = req.body.email; - const user = await User.findOne({ email }).select('+publicKey'); - if (!user || !user?.publicKey) { - // case: user has already completed account + const user = await User.findOne({ email }).select('+publicKey'); + if (!user || !user?.publicKey) { + // case: user has already completed account - return res.status(403).send({ - error: 'Failed to send email verification for password reset' - }); - } - - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_PASSWORD_RESET, - email - }); - - await sendMail({ - template: 'passwordReset.handlebars', - subjectLine: 'Infisical password reset', - recipients: [email], - substitutions: { - email, - token, - callback_url: getSiteURL() + '/password-reset' - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to send email for account recovery' - }); - } + return res.status(200).send({ + message:"If an account exists with this email, a password reset link has been sent" + }); + } + + const token = await TokenService.createToken({ + type: TOKEN_EMAIL_PASSWORD_RESET, + email + }); + + await sendMail({ + template: 'passwordReset.handlebars', + subjectLine: 'Infisical password reset', + recipients: [email], + substitutions: { + email, + token, + callback_url: (await getSiteURL()) + '/password-reset' + } + }); return res.status(200).send({ - message: `Sent an email for account recovery to ${email}` + message:"If an account exists with this email, a password reset link has been sent" }); } @@ -67,40 +69,31 @@ export const emailPasswordReset = async (req: Request, res: Response) => { * @returns */ export const emailPasswordResetVerify = async (req: Request, res: Response) => { - let user, token; - try { - const { email, code } = req.body; + const { email, code } = req.body; - user = await User.findOne({ email }).select('+publicKey'); - if (!user || !user?.publicKey) { - // case: user doesn't exist with email [email] or - // hasn't even completed their account - return res.status(403).send({ - error: 'Failed email verification for password reset' - }); - } - - await TokenService.validateToken({ - type: TOKEN_EMAIL_PASSWORD_RESET, - email, - token: code - }); + const user = await User.findOne({ email }).select('+publicKey'); + if (!user || !user?.publicKey) { + // case: user doesn't exist with email [email] or + // hasn't even completed their account + return res.status(403).send({ + error: 'Failed email verification for password reset' + }); + } + + await TokenService.validateToken({ + type: TOKEN_EMAIL_PASSWORD_RESET, + email, + token: code + }); - // generate temporary password-reset token - token = createToken({ - payload: { - userId: user._id.toString() - }, - expiresIn: getJwtSignupLifetime(), - secret: getJwtSignupSecret() - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed email verification for password reset' - }); - } + // generate temporary password-reset token + const token = createToken({ + payload: { + userId: user._id.toString() + }, + expiresIn: await getJwtSignupLifetime(), + secret: await getJwtSignupSecret() + }); return res.status(200).send({ message: 'Successfully verified email', @@ -117,44 +110,38 @@ export const emailPasswordResetVerify = async (req: Request, res: Response) => { */ export const srp1 = async (req: Request, res: Response) => { // return salt, serverPublicKey as part of first step of SRP protocol - try { - const { clientPublicKey } = req.body; - const user = await User.findOne({ - email: req.user.email - }).select('+salt +verifier'); + + const { clientPublicKey } = req.body; + const user = await User.findOne({ + email: req.user.email + }).select('+salt +verifier'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier + }, + async () => { + // generate server-side public key + const serverPublicKey = server.getPublicKey(); - await LoginSRPDetail.findOneAndReplace({ email: req.user.email }, { - email: req.user.email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt), - }, { upsert: true, returnNewDocument: false }) + await LoginSRPDetail.findOneAndReplace({ email: req.user.email }, { + email: req.user.email, + clientPublicKey: clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt), + }, { upsert: true, returnNewDocument: false }) + + return res.status(200).send({ + serverPublicKey, + salt: user.salt + }); + } + ); +} - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed to start change password process' - }); - } -}; /** * Change account SRP authentication information for user @@ -165,80 +152,85 @@ export const srp1 = async (req: Request, res: Response) => { * @returns */ export const changePassword = async (req: Request, res: Response) => { - try { - const { - clientProof, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - } = req.body; + const { + clientProof, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier + } = req.body; - const user = await User.findOne({ - email: req.user.email - }).select('+salt +verifier'); + const user = await User.findOne({ + email: req.user.email + }).select('+salt +verifier'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }) + const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }) - if (!loginSRPDetailFromDB) { - return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) - } + if (!loginSRPDetailFromDB) { + return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) + } - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: loginSRPDetailFromDB.serverBInt + }, + async () => { + server.setClientPublicKey(loginSRPDetailFromDB.clientPublicKey); - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // change password + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + // change password - await User.findByIdAndUpdate( - req.user._id.toString(), - { - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - { - new: true - } - ); + await User.findByIdAndUpdate( + req.user._id.toString(), + { + encryptionVersion: 2, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag, + salt, + verifier + }, + { + new: true + } + ); + + if (req.authData.authMode === AUTH_MODE_JWT && req.authData.authPayload instanceof User && req.authData.tokenVersionId) { + await clearTokens(req.authData.tokenVersionId) + } - return res.status(200).send({ - message: 'Successfully changed password' - }); - } + // clear httpOnly cookie + + res.cookie('jid', '', { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: (await getHttpsEnabled()) as boolean + }); - return res.status(400).send({ - error: 'Failed to change password. Try again?' - }); - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed to change password. Try again?' - }); - } + return res.status(200).send({ + message: 'Successfully changed password' + }); + } + + return res.status(400).send({ + error: 'Failed to change password. Try again?' + }); + } + ); }; /** @@ -252,69 +244,61 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => { // requires verifying [clientProof] as part of second step of SRP protocol // as initiated in /srp1 - try { - const { clientProof, encryptedPrivateKey, iv, tag, salt, verifier } = - req.body; - const user = await User.findOne({ - email: req.user.email - }).select('+salt +verifier'); + const { clientProof, encryptedPrivateKey, iv, tag, salt, verifier } = + req.body; + const user = await User.findOne({ + email: req.user.email + }).select('+salt +verifier'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }) + const loginSRPDetailFromDB = await LoginSRPDetail.findOneAndDelete({ email: req.user.email }) - if (!loginSRPDetailFromDB) { - return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) - } + if (!loginSRPDetailFromDB) { + return BadRequestError(Error("It looks like some details from the first login are not found. Please try login one again")) + } - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetailFromDB.serverBInt - }, - async () => { - server.setClientPublicKey( - loginSRPDetailFromDB.clientPublicKey - ); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: loginSRPDetailFromDB.serverBInt + }, + async () => { + server.setClientPublicKey( + loginSRPDetailFromDB.clientPublicKey + ); - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - // create new or replace backup private key + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + // create new or replace backup private key - const backupPrivateKey = await BackupPrivateKey.findOneAndUpdate( - { user: req.user._id }, - { - user: req.user._id, - encryptedPrivateKey, - iv, - tag, - salt, - verifier - }, - { upsert: true, new: true } - ).select('+user, encryptedPrivateKey'); + const backupPrivateKey = await BackupPrivateKey.findOneAndUpdate( + { user: req.user._id }, + { + user: req.user._id, + encryptedPrivateKey, + iv, + tag, + salt, + verifier + }, + { upsert: true, new: true } + ).select('+user, encryptedPrivateKey'); - // issue tokens - return res.status(200).send({ - message: 'Successfully updated backup private key', - backupPrivateKey - }); - } + // issue tokens + return res.status(200).send({ + message: 'Successfully updated backup private key', + backupPrivateKey + }); + } - return res.status(400).send({ - message: 'Failed to update backup private key' - }); - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to update backup private key' - }); - } + return res.status(400).send({ + message: 'Failed to update backup private key' + }); + } + ); }; /** @@ -324,20 +308,11 @@ export const createBackupPrivateKey = async (req: Request, res: Response) => { * @returns */ export const getBackupPrivateKey = async (req: Request, res: Response) => { - let backupPrivateKey; - try { - backupPrivateKey = await BackupPrivateKey.findOne({ - user: req.user._id - }).select('+encryptedPrivateKey +iv +tag'); + const backupPrivateKey = await BackupPrivateKey.findOne({ + user: req.user._id + }).select('+encryptedPrivateKey +iv +tag'); - if (!backupPrivateKey) throw new Error('Failed to find backup private key'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get backup private key' - }); - } + if (!backupPrivateKey) throw new Error('Failed to find backup private key'); return res.status(200).send({ backupPrivateKey @@ -345,44 +320,36 @@ export const getBackupPrivateKey = async (req: Request, res: Response) => { } export const resetPassword = async (req: Request, res: Response) => { - try { - const { - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - } = req.body; + const { + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier, + } = req.body; - await User.findByIdAndUpdate( - req.user._id.toString(), - { - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - { - new: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get backup private key' - }); - } + await User.findByIdAndUpdate( + req.user._id.toString(), + { + encryptionVersion: 2, + protectedKey, + protectedKeyIV, + protectedKeyTag, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag, + salt, + verifier + }, + { + new: true + } + ); return res.status(200).send({ message: 'Successfully reset password' }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/v1/secretController.ts b/backend/src/controllers/v1/secretController.ts index 1d1f8981c..074e29454 100644 --- a/backend/src/controllers/v1/secretController.ts +++ b/backend/src/controllers/v1/secretController.ts @@ -1,5 +1,5 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Key, Secret } from '../../models'; import { v1PushSecrets as push, @@ -9,7 +9,7 @@ import { import { pushKeys } from '../../helpers/key'; import { eventPushSecrets } from '../../events'; import { EventService } from '../../services'; -import { getPostHogClient } from '../../services'; +import { TelemetryService } from '../../services'; interface PushSecret { ciphertextKey: string; @@ -36,65 +36,56 @@ interface PushSecret { */ export const pushSecrets = async (req: Request, res: Response) => { // upload (encrypted) secrets to workspace with id [workspaceId] + const postHogClient = await TelemetryService.getPostHogClient(); + let { secrets }: { secrets: PushSecret[] } = req.body; + const { keys, environment, channel } = req.body; + const { workspaceId } = req.params; - try { - const postHogClient = getPostHogClient(); - let { secrets }: { secrets: PushSecret[] } = req.body; - const { keys, environment, channel } = req.body; - const { workspaceId } = req.params; + // validate environment + const workspaceEnvs = req.membership.workspace.environments; + if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { + throw new Error('Failed to validate environment'); + } - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error('Failed to validate environment'); - } + // sanitize secrets + secrets = secrets.filter( + (s: PushSecret) => s.ciphertextKey !== '' && s.ciphertextValue !== '' + ); - // sanitize secrets - secrets = secrets.filter( - (s: PushSecret) => s.ciphertextKey !== '' && s.ciphertextValue !== '' - ); + await push({ + userId: req.user._id, + workspaceId, + environment, + secrets + }); - await push({ - userId: req.user._id, - workspaceId, - environment, - secrets - }); + await pushKeys({ + userId: req.user._id, + workspaceId, + keys + }); + + + if (postHogClient) { + postHogClient.capture({ + event: 'secrets pushed', + distinctId: req.user.email, + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + channel: channel ? channel : 'cli' + } + }); + } - await pushKeys({ - userId: req.user._id, - workspaceId, - keys - }); - - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets pushed', - distinctId: req.user.email, - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : 'cli' - } - }); - } - - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId - }) - }); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to upload workspace secrets' - }); - } + // trigger event - push secrets + EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment + }) + }); return res.status(200).send({ message: 'Successfully uploaded workspace secrets' @@ -111,55 +102,48 @@ export const pushSecrets = async (req: Request, res: Response) => { export const pullSecrets = async (req: Request, res: Response) => { let secrets; let key; - try { - const postHogClient = getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error('Failed to validate environment'); - } + const postHogClient = await TelemetryService.getPostHogClient(); + const environment: string = req.query.environment as string; + const channel: string = req.query.channel as string; + const { workspaceId } = req.params; - secrets = await pull({ - userId: req.user._id.toString(), - workspaceId, - environment, - channel: channel ? channel : 'cli', - ipAddress: req.ip - }); + // validate environment + const workspaceEnvs = req.membership.workspace.environments; + if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { + throw new Error('Failed to validate environment'); + } - key = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }) - .sort({ createdAt: -1 }) - .populate('sender', '+publicKey'); - - if (channel !== 'cli') { - secrets = reformatPullSecrets({ secrets }); - } + secrets = await pull({ + userId: req.user._id.toString(), + workspaceId, + environment, + channel: channel ? channel : 'cli', + ipAddress: req.realIP + }); - if (postHogClient) { - // capture secrets pushed event in production - postHogClient.capture({ - distinctId: req.user.email, - event: 'secrets pulled', - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : 'cli' - } - }); - } - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to pull workspace secrets' + key = await Key.findOne({ + workspace: workspaceId, + receiver: req.user._id + }) + .sort({ createdAt: -1 }) + .populate('sender', '+publicKey'); + + if (channel !== 'cli') { + secrets = reformatPullSecrets({ secrets }); + } + + if (postHogClient) { + // capture secrets pushed event in production + postHogClient.capture({ + distinctId: req.user.email, + event: 'secrets pulled', + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + channel: channel ? channel : 'cli' + } }); } @@ -180,54 +164,47 @@ export const pullSecrets = async (req: Request, res: Response) => { export const pullSecretsServiceToken = async (req: Request, res: Response) => { let secrets; let key; - try { - const postHogClient = getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error('Failed to validate environment'); - } + const postHogClient = await TelemetryService.getPostHogClient(); + const environment: string = req.query.environment as string; + const channel: string = req.query.channel as string; + const { workspaceId } = req.params; - secrets = await pull({ - userId: req.serviceToken.user._id.toString(), - workspaceId, - environment, - channel: 'cli', - ipAddress: req.ip - }); + // validate environment + const workspaceEnvs = req.membership.workspace.environments; + if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { + throw new Error('Failed to validate environment'); + } - key = { - encryptedKey: req.serviceToken.encryptedKey, - nonce: req.serviceToken.nonce, - sender: { - publicKey: req.serviceToken.publicKey - }, - receiver: req.serviceToken.user, - workspace: req.serviceToken.workspace - }; + secrets = await pull({ + userId: req.serviceToken.user._id.toString(), + workspaceId, + environment, + channel: 'cli', + ipAddress: req.realIP + }); - if (postHogClient) { - // capture secrets pulled event in production - postHogClient.capture({ - distinctId: req.serviceToken.user.email, - event: 'secrets pulled', - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : 'cli' - } - }); - } - } catch (err) { - Sentry.setUser({ email: req.serviceToken.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to pull workspace secrets' + key = { + encryptedKey: req.serviceToken.encryptedKey, + nonce: req.serviceToken.nonce, + sender: { + publicKey: req.serviceToken.publicKey + }, + receiver: req.serviceToken.user, + workspace: req.serviceToken.workspace + }; + + if (postHogClient) { + // capture secrets pulled event in production + postHogClient.capture({ + distinctId: req.serviceToken.user.email, + event: 'secrets pulled', + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + channel: channel ? channel : 'cli' + } }); } @@ -235,4 +212,4 @@ export const pullSecretsServiceToken = async (req: Request, res: Response) => { secrets: reformatPullSecrets({ secrets }), key }); -}; \ No newline at end of file +}; diff --git a/backend/src/controllers/v1/secretsFolderController.ts b/backend/src/controllers/v1/secretsFolderController.ts new file mode 100644 index 000000000..06d68a41d --- /dev/null +++ b/backend/src/controllers/v1/secretsFolderController.ts @@ -0,0 +1,218 @@ +import { Request, Response } from "express"; +import { Secret } from "../../models"; +import Folder from "../../models/folder"; +import { BadRequestError } from "../../utils/errors"; +import { + appendFolder, + deleteFolderById, + getAllFolderIds, + searchByFolderIdWithDir, + searchByFolderId, + validateFolderName, + generateFolderId, + getParentFromFolderId, +} from "../../services/FolderService"; +import { ADMIN, MEMBER } from "../../variables"; +import { validateMembership } from "../../helpers/membership"; +import { FolderVersion } from "../../ee/models"; +import { EESecretService } from "../../ee/services"; + +// TODO +// verify workspace id/environment +export const createFolder = async (req: Request, res: Response) => { + const { workspaceId, environment, folderName, parentFolderId } = req.body; + if (!validateFolderName(folderName)) { + throw BadRequestError({ + message: "Folder name cannot contain spaces. Only underscore and dashes", + }); + } + + const folders = await Folder.findOne({ + workspace: workspaceId, + environment, + }).lean(); + // space has no folders initialized + if (!folders) { + const id = generateFolderId(); + const folder = new Folder({ + workspace: workspaceId, + environment, + nodes: { + id: "root", + name: "root", + version: 1, + children: [{ id, name: folderName, children: [], version: 1 }], + }, + }); + await folder.save(); + const folderVersion = new FolderVersion({ + workspace: workspaceId, + environment, + nodes: folder.nodes, + }); + await folderVersion.save(); + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + }); + return res.json({ folder: { id, name: folderName } }); + } + + const folder = appendFolder(folders.nodes, { folderName, parentFolderId }); + await Folder.findByIdAndUpdate(folders._id, folders); + + const parentFolder = searchByFolderId(folders.nodes, parentFolderId); + const folderVersion = new FolderVersion({ + workspace: workspaceId, + environment, + nodes: parentFolder, + }); + await folderVersion.save(); + + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId: parentFolderId, + }); + + return res.json({ folder }); +}; + +export const updateFolderById = async (req: Request, res: Response) => { + const { folderId } = req.params; + const { name, workspaceId, environment } = req.body; + + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + if (!folders) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + + // check that user is a member of the workspace + await validateMembership({ + userId: req.user._id.toString(), + workspaceId, + acceptedRoles: [ADMIN, MEMBER], + }); + + const parentFolder = getParentFromFolderId(folders.nodes, folderId); + if (!parentFolder) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + const folder = parentFolder.children.find(({ id }) => id === folderId); + if (!folder) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + + parentFolder.version += 1; + folder.name = name; + + await Folder.findByIdAndUpdate(folders._id, folders); + const folderVersion = new FolderVersion({ + workspace: workspaceId, + environment, + nodes: parentFolder, + }); + await folderVersion.save(); + + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId: parentFolder.id, + }); + + return res.json({ + message: "Successfully updated folder", + folder: { name: folder.name, id: folder.id }, + }); +}; + +export const deleteFolder = async (req: Request, res: Response) => { + const { folderId } = req.params; + const { workspaceId, environment } = req.body; + + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + if (!folders) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + + // check that user is a member of the workspace + await validateMembership({ + userId: req.user._id.toString(), + workspaceId, + acceptedRoles: [ADMIN, MEMBER], + }); + + const delOp = deleteFolderById(folders.nodes, folderId); + if (!delOp) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + const { deletedNode: delFolder, parent: parentFolder } = delOp; + + parentFolder.version += 1; + const delFolderIds = getAllFolderIds(delFolder); + + await Folder.findByIdAndUpdate(folders._id, folders); + const folderVersion = new FolderVersion({ + workspace: workspaceId, + environment, + nodes: parentFolder, + }); + await folderVersion.save(); + if (delFolderIds.length) { + await Secret.deleteMany({ + folder: { $in: delFolderIds.map(({ id }) => id) }, + workspace: workspaceId, + environment, + }); + } + + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId: parentFolder.id, + }); + + res.send({ message: "successfully deleted folders", folders: delFolderIds }); +}; + +// TODO: validate workspace +export const getFolders = async (req: Request, res: Response) => { + const { workspaceId, environment, parentFolderId } = req.query as { + workspaceId: string; + environment: string; + parentFolderId?: string; + }; + + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + if (!folders) { + res.send({ folders: [], dir: [] }); + return; + } + + // check that user is a member of the workspace + await validateMembership({ + userId: req.user._id.toString(), + workspaceId, + acceptedRoles: [ADMIN, MEMBER], + }); + + if (!parentFolderId) { + const rootFolders = folders.nodes.children.map(({ id, name }) => ({ + id, + name, + })); + res.send({ folders: rootFolders }); + return; + } + + const folderBySearch = searchByFolderIdWithDir(folders.nodes, parentFolderId); + if (!folderBySearch) { + throw BadRequestError({ message: "The folder doesn't exist" }); + } + const { folder, dir } = folderBySearch; + + res.send({ + folders: folder.children.map(({ id, name }) => ({ id, name })), + dir, + }); +}; diff --git a/backend/src/controllers/v1/serviceTokenController.ts b/backend/src/controllers/v1/serviceTokenController.ts index 9f241349a..86a87f372 100644 --- a/backend/src/controllers/v1/serviceTokenController.ts +++ b/backend/src/controllers/v1/serviceTokenController.ts @@ -61,7 +61,7 @@ export const createServiceToken = async (req: Request, res: Response) => { workspaceId }, expiresIn: expiresIn, - secret: getJwtServiceSecret() + secret: await getJwtServiceSecret() }); } catch (err) { return res.status(400).send({ diff --git a/backend/src/controllers/v1/signupController.ts b/backend/src/controllers/v1/signupController.ts index 6adb0e7a8..19bf94e61 100644 --- a/backend/src/controllers/v1/signupController.ts +++ b/backend/src/controllers/v1/signupController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { User } from '../../models'; import { sendEmailVerification, @@ -8,6 +7,7 @@ import { import { createToken } from '../../helpers/auth'; import { BadRequestError } from '../../utils/errors'; import { getInviteOnlySignup, getJwtSignupLifetime, getJwtSignupSecret, getSmtpConfigured } from '../../config'; +import { validateUserEmail } from '../../validation'; /** * Signup step 1: Initialize account for user under email [email] and send a verification code @@ -18,35 +18,22 @@ import { getInviteOnlySignup, getJwtSignupLifetime, getJwtSignupSecret, getSmtpC */ export const beginEmailSignup = async (req: Request, res: Response) => { let email: string; - try { - email = req.body.email; + email = req.body.email; + + // validate that email is not disposable + validateUserEmail(email); - if (getInviteOnlySignup()) { - // Only one user can create an account without being invited. The rest need to be invited in order to make an account - const userCount = await User.countDocuments({}) - if (userCount != 0) { - throw BadRequestError({ message: "New user sign ups are not allowed at this time. You must be invited to sign up." }) - } - } + const user = await User.findOne({ email }).select('+publicKey'); + if (user && user?.publicKey) { + // case: user has already completed account - const user = await User.findOne({ email }).select('+publicKey'); - if (user && user?.publicKey) { - // case: user has already completed account + return res.status(403).send({ + error: 'Failed to send email verification code for complete account' + }); + } - return res.status(403).send({ - error: 'Failed to send email verification code for complete account' - }); - } - - // send send verification email - await sendEmailVerification({ email }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed to send email verification code' - }); - } + // send send verification email + await sendEmailVerification({ email }); return res.status(200).send({ message: `Sent an email verification code to ${email}` @@ -62,47 +49,47 @@ export const beginEmailSignup = async (req: Request, res: Response) => { */ export const verifyEmailSignup = async (req: Request, res: Response) => { let user, token; - try { - const { email, code } = req.body; + const { email, code } = req.body; - // initialize user account - user = await User.findOne({ email }).select('+publicKey'); - if (user && user?.publicKey) { - // case: user has already completed account - return res.status(403).send({ - error: 'Failed email verification for complete user' - }); - } + // initialize user account + user = await User.findOne({ email }).select('+publicKey'); + if (user && user?.publicKey) { + // case: user has already completed account + return res.status(403).send({ + error: 'Failed email verification for complete user' + }); + } - // verify email - if (getSmtpConfigured()) { - await checkEmailVerification({ - email, - code - }); - } + if (await getInviteOnlySignup()) { + // Only one user can create an account without being invited. The rest need to be invited in order to make an account + const userCount = await User.countDocuments({}) + if (userCount != 0) { + throw BadRequestError({ message: "New user sign ups are not allowed at this time. You must be invited to sign up." }) + } + } - if (!user) { - user = await new User({ - email - }).save(); - } + // verify email + if (await getSmtpConfigured()) { + await checkEmailVerification({ + email, + code + }); + } - // generate temporary signup token - token = createToken({ - payload: { - userId: user._id.toString() - }, - expiresIn: getJwtSignupLifetime(), - secret: getJwtSignupSecret() - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed email verification' - }); - } + if (!user) { + user = await new User({ + email + }).save(); + } + + // generate temporary signup token + token = createToken({ + payload: { + userId: user._id.toString() + }, + expiresIn: await getJwtSignupLifetime(), + secret: await getJwtSignupSecret() + }); return res.status(200).send({ message: 'Successfuly verified email', diff --git a/backend/src/controllers/v1/stripeController.ts b/backend/src/controllers/v1/stripeController.ts index 1a981c088..4aa7adce9 100644 --- a/backend/src/controllers/v1/stripeController.ts +++ b/backend/src/controllers/v1/stripeController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import Stripe from 'stripe'; import { getStripeSecretKey, getStripeWebhookSecret } from '../../config'; @@ -10,26 +9,17 @@ import { getStripeSecretKey, getStripeWebhookSecret } from '../../config'; * @returns */ export const handleWebhook = async (req: Request, res: Response) => { - let event; - try { - // check request for valid stripe signature - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + // check request for valid stripe signature + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: '2022-08-01' + }); - const sig = req.headers['stripe-signature'] as string; - event = stripe.webhooks.constructEvent( - req.body, - sig, - getStripeWebhookSecret() - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed to process webhook' - }); - } + const sig = req.headers['stripe-signature'] as string; + const event = stripe.webhooks.constructEvent( + req.body, + sig, + await getStripeWebhookSecret() + ); switch (event.type) { case '': diff --git a/backend/src/controllers/v1/userActionController.ts b/backend/src/controllers/v1/userActionController.ts index c7a3c2337..cba78c7b8 100644 --- a/backend/src/controllers/v1/userActionController.ts +++ b/backend/src/controllers/v1/userActionController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { UserAction } from '../../models'; /** @@ -11,28 +10,19 @@ import { UserAction } from '../../models'; export const addUserAction = async (req: Request, res: Response) => { // add/record new action [action] for user with id [req.user._id] - let userAction; - try { - const { action } = req.body; + const { action } = req.body; - userAction = await UserAction.findOneAndUpdate( - { - user: req.user._id, - action - }, - { user: req.user._id, action }, - { - new: true, - upsert: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to record user action' - }); - } + const userAction = await UserAction.findOneAndUpdate( + { + user: req.user._id, + action + }, + { user: req.user._id, action }, + { + new: true, + upsert: true + } + ); return res.status(200).send({ message: 'Successfully recorded user action', @@ -48,21 +38,12 @@ export const addUserAction = async (req: Request, res: Response) => { */ export const getUserAction = async (req: Request, res: Response) => { // get user action [action] for user with id [req.user._id] - let userAction; - try { - const action: string = req.query.action as string; + const action: string = req.query.action as string; - userAction = await UserAction.findOne({ - user: req.user._id, - action - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get user action' - }); - } + const userAction = await UserAction.findOne({ + user: req.user._id, + action + }); return res.status(200).send({ userAction diff --git a/backend/src/controllers/v1/workspaceController.ts b/backend/src/controllers/v1/workspaceController.ts index 2b0a89f43..2faac0d68 100644 --- a/backend/src/controllers/v1/workspaceController.ts +++ b/backend/src/controllers/v1/workspaceController.ts @@ -1,5 +1,4 @@ import { Request, Response } from "express"; -import * as Sentry from "@sentry/node"; import { Workspace, Membership, @@ -14,6 +13,7 @@ import { createWorkspace as create, deleteWorkspace as deleteWork, } from "../../helpers/workspace"; +import { EELicenseService } from '../../ee/services'; import { addMemberships } from "../../helpers/membership"; import { ADMIN } from "../../variables"; @@ -24,27 +24,18 @@ import { ADMIN } from "../../variables"; * @returns */ export const getWorkspacePublicKeys = async (req: Request, res: Response) => { - let publicKeys; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - publicKeys = ( - await Membership.find({ - workspace: workspaceId, - }).populate<{ user: IUser }>("user", "publicKey") - ).map((member) => { - return { - publicKey: member.user.publicKey, - userId: member.user._id, - }; - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace member public keys", - }); - } + const publicKeys = ( + await Membership.find({ + workspace: workspaceId, + }).populate<{ user: IUser }>("user", "publicKey") + ).map((member) => { + return { + publicKey: member.user.publicKey, + userId: member.user._id, + }; + }); return res.status(200).send({ publicKeys, @@ -58,20 +49,11 @@ export const getWorkspacePublicKeys = async (req: Request, res: Response) => { * @returns */ export const getWorkspaceMemberships = async (req: Request, res: Response) => { - let users; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - users = await Membership.find({ - workspace: workspaceId, - }).populate("user", "+publicKey"); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace members", - }); - } + const users = await Membership.find({ + workspace: workspaceId, + }).populate("user", "+publicKey"); return res.status(200).send({ users, @@ -85,20 +67,11 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => { * @returns */ export const getWorkspaces = async (req: Request, res: Response) => { - let workspaces; - try { - workspaces = ( - await Membership.find({ - user: req.user._id, - }).populate("workspace") - ).map((m) => m.workspace); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspaces", - }); - } + const workspaces = ( + await Membership.find({ + user: req.user._id, + }).populate("workspace") + ).map((m) => m.workspace); return res.status(200).send({ workspaces, @@ -112,20 +85,11 @@ export const getWorkspaces = async (req: Request, res: Response) => { * @returns */ export const getWorkspace = async (req: Request, res: Response) => { - let workspace; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - workspace = await Workspace.findOne({ - _id: workspaceId, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace", - }); - } + const workspace = await Workspace.findOne({ + _id: workspaceId, + }); return res.status(200).send({ workspace, @@ -140,43 +104,46 @@ export const getWorkspace = async (req: Request, res: Response) => { * @returns */ export const createWorkspace = async (req: Request, res: Response) => { - let workspace; - try { - const { workspaceName, organizationId } = req.body; + const { workspaceName, organizationId } = req.body; - // validate organization membership - const membershipOrg = await MembershipOrg.findOne({ - user: req.user._id, - organization: organizationId, - }); + // validate organization membership + const membershipOrg = await MembershipOrg.findOne({ + user: req.user._id, + organization: organizationId, + }); - if (!membershipOrg) { - throw new Error("Failed to validate organization membership"); - } - - if (workspaceName.length < 1) { - throw new Error("Workspace names must be at least 1-character long"); - } - - // create workspace and add user as member - workspace = await create({ - name: workspaceName, - organizationId, - }); - - await addMemberships({ - userIds: [req.user._id], - workspaceId: workspace._id.toString(), - roles: [ADMIN], - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to create workspace", - }); + if (!membershipOrg) { + throw new Error("Failed to validate organization membership"); } + const plan = await EELicenseService.getPlan(organizationId); + + if (plan.workspaceLimit !== null) { + // case: limit imposed on number of workspaces allowed + if (plan.workspacesUsed >= plan.workspaceLimit) { + // case: number of workspaces used exceeds the number of workspaces allowed + return res.status(400).send({ + message: 'Failed to create workspace due to plan limit reached. Upgrade plan to add more workspaces.' + }); + } + } + + if (workspaceName.length < 1) { + throw new Error("Workspace names must be at least 1-character long"); + } + + // create workspace and add user as member + const workspace = await create({ + name: workspaceName, + organizationId, + }); + + await addMemberships({ + userIds: [req.user._id], + workspaceId: workspace._id.toString(), + roles: [ADMIN], + }); + return res.status(200).send({ workspace, }); @@ -189,20 +156,12 @@ export const createWorkspace = async (req: Request, res: Response) => { * @returns */ export const deleteWorkspace = async (req: Request, res: Response) => { - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - // delete workspace - await deleteWork({ - id: workspaceId, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to delete workspace", - }); - } + // delete workspace + await deleteWork({ + id: workspaceId, + }); return res.status(200).send({ message: "Successfully deleted workspace", @@ -216,29 +175,20 @@ export const deleteWorkspace = async (req: Request, res: Response) => { * @returns */ export const changeWorkspaceName = async (req: Request, res: Response) => { - let workspace; - try { - const { workspaceId } = req.params; - const { name } = req.body; + const { workspaceId } = req.params; + const { name } = req.body; - workspace = await Workspace.findOneAndUpdate( - { - _id: workspaceId, - }, - { - name, - }, - { - new: true, - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to change workspace name", - }); - } + const workspace = await Workspace.findOneAndUpdate( + { + _id: workspaceId, + }, + { + name, + }, + { + new: true, + } + ); return res.status(200).send({ message: "Successfully changed workspace name", @@ -253,20 +203,11 @@ export const changeWorkspaceName = async (req: Request, res: Response) => { * @returns */ export const getWorkspaceIntegrations = async (req: Request, res: Response) => { - let integrations; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - integrations = await Integration.find({ - workspace: workspaceId, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace integrations", - }); - } + const integrations = await Integration.find({ + workspace: workspaceId, + }); return res.status(200).send({ integrations, @@ -283,20 +224,11 @@ export const getWorkspaceIntegrationAuthorizations = async ( req: Request, res: Response ) => { - let authorizations; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - authorizations = await IntegrationAuth.find({ - workspace: workspaceId, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace integration authorizations", - }); - } + const authorizations = await IntegrationAuth.find({ + workspace: workspaceId, + }); return res.status(200).send({ authorizations, @@ -313,21 +245,12 @@ export const getWorkspaceServiceTokens = async ( req: Request, res: Response ) => { - let serviceTokens; - try { - const { workspaceId } = req.params; - // ?? FIX. - serviceTokens = await ServiceToken.find({ - user: req.user._id, - workspace: workspaceId, - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get workspace service tokens", - }); - } + const { workspaceId } = req.params; + // ?? FIX. + const serviceTokens = await ServiceToken.find({ + user: req.user._id, + workspace: workspaceId, + }); return res.status(200).send({ serviceTokens, diff --git a/backend/src/controllers/v2/apiKeyDataController.ts b/backend/src/controllers/v2/apiKeyDataController.ts index fd87f7306..73fd1afbf 100644 --- a/backend/src/controllers/v2/apiKeyDataController.ts +++ b/backend/src/controllers/v2/apiKeyDataController.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Request, Response } from 'express'; import crypto from 'crypto'; import bcrypt from 'bcrypt'; @@ -14,18 +13,9 @@ import { getSaltRounds } from '../../config'; * @returns */ export const getAPIKeyData = async (req: Request, res: Response) => { - let apiKeyData; - try { - apiKeyData = await APIKeyData.find({ - user: req.user._id - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get API key data' - }); - } + const apiKeyData = await APIKeyData.find({ + user: req.user._id + }); return res.status(200).send({ apiKeyData @@ -38,38 +28,30 @@ export const getAPIKeyData = async (req: Request, res: Response) => { * @param res */ export const createAPIKeyData = async (req: Request, res: Response) => { - let apiKey, apiKeyData; - try { - const { name, expiresIn } = req.body; - - const secret = crypto.randomBytes(16).toString('hex'); - const secretHash = await bcrypt.hash(secret, getSaltRounds()); - - const expiresAt = new Date(); - expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); - - apiKeyData = await new APIKeyData({ - name, - expiresAt, - user: req.user._id, - secretHash - }).save(); - - // return api key data without sensitive data - apiKeyData = await APIKeyData.findById(apiKeyData._id); - - if (!apiKeyData) throw new Error('Failed to find API key data'); - - apiKey = `ak.${apiKeyData._id.toString()}.${secret}`; - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to API key data' - }); - } + const { name, expiresIn } = req.body; + const secret = crypto.randomBytes(16).toString('hex'); + const secretHash = await bcrypt.hash(secret, await getSaltRounds()); + + const expiresAt = new Date(); + expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); + + let apiKeyData = await new APIKeyData({ + name, + lastUsed: new Date(), + expiresAt, + user: req.user._id, + secretHash + }).save(); + + // return api key data without sensitive data + // FIX: fix this any + apiKeyData = await APIKeyData.findById(apiKeyData._id) as any + + if (!apiKeyData) throw new Error('Failed to find API key data'); + + const apiKey = `ak.${apiKeyData._id.toString()}.${secret}`; + return res.status(200).send({ apiKey, apiKeyData @@ -83,21 +65,10 @@ export const createAPIKeyData = async (req: Request, res: Response) => { * @returns */ export const deleteAPIKeyData = async (req: Request, res: Response) => { - let apiKeyData; - try { - const { apiKeyDataId } = req.params; - - apiKeyData = await APIKeyData.findByIdAndDelete(apiKeyDataId); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete API key data' - }); - } + const { apiKeyDataId } = req.params; + const apiKeyData = await APIKeyData.findByIdAndDelete(apiKeyDataId); return res.status(200).send({ apiKeyData }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/v2/authController.ts b/backend/src/controllers/v2/authController.ts index 3a36d559c..0718ec8dc 100644 --- a/backend/src/controllers/v2/authController.ts +++ b/backend/src/controllers/v2/authController.ts @@ -1,7 +1,6 @@ /* eslint-disable @typescript-eslint/no-var-requires */ import { Request, Response } from 'express'; import jwt from 'jsonwebtoken'; -import * as Sentry from '@sentry/node'; import * as bigintConversion from 'bigint-conversion'; const jsrp = require('jsrp'); import { User, LoginSRPDetail } from '../../models'; @@ -17,9 +16,9 @@ import { } from '../../variables'; import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this import { - getNodeEnv, getJwtMfaLifetime, - getJwtMfaSecret + getJwtMfaSecret, + getHttpsEnabled } from '../../config'; declare module 'jsonwebtoken' { @@ -35,47 +34,40 @@ declare module 'jsonwebtoken' { * @returns */ export const login1 = async (req: Request, res: Response) => { - try { - const { - email, - clientPublicKey - }: { email: string; clientPublicKey: string } = req.body; + const { + email, + clientPublicKey + }: { email: string; clientPublicKey: string } = req.body; - const user = await User.findOne({ - email - }).select('+salt +verifier'); + const user = await User.findOne({ + email + }).select('+salt +verifier'); - if (!user) throw new Error('Failed to find user'); + if (!user) throw new Error('Failed to find user'); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier - }, - async () => { - // generate server-side public key - const serverPublicKey = server.getPublicKey(); + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier + }, + async () => { + // generate server-side public key + const serverPublicKey = server.getPublicKey(); - await LoginSRPDetail.findOneAndReplace({ email: email }, { - email: email, - clientPublicKey: clientPublicKey, - serverBInt: bigintConversion.bigintToBuf(server.bInt), - }, { upsert: true, returnNewDocument: false }); + await LoginSRPDetail.findOneAndReplace({ email: email }, { + email: email, + clientPublicKey: clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt), + }, { upsert: true, returnNewDocument: false }); - return res.status(200).send({ - serverPublicKey, - salt: user.salt - }); - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to start authentication process' - }); - } + return res.status(200).send({ + serverPublicKey, + salt: user.salt + }); + } + ); + }; /** @@ -86,149 +78,143 @@ export const login1 = async (req: Request, res: Response) => { * @returns */ export const login2 = async (req: Request, res: Response) => { - try { + if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' }); - if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' }); + const { email, clientProof } = req.body; + const user = await User.findOne({ + email + }).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices'); - const { email, clientProof } = req.body; - const user = await User.findOne({ - email - }).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag'); + if (!user) throw new Error('Failed to find user'); - if (!user) throw new Error('Failed to find user'); + const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email }) - const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email }) + if (!loginSRPDetail) { + return BadRequestError(Error("Failed to find login details for SRP")) + } - if (!loginSRPDetail) { - return BadRequestError(Error("Failed to find login details for SRP")) - } + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: loginSRPDetail.serverBInt + }, + async () => { + server.setClientPublicKey(loginSRPDetail.clientPublicKey); - const server = new jsrp.server(); - server.init( - { - salt: user.salt, - verifier: user.verifier, - b: loginSRPDetail.serverBInt - }, - async () => { - server.setClientPublicKey(loginSRPDetail.clientPublicKey); + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + if (user.isMfaEnabled) { + // case: user has MFA enabled - // compare server and client shared keys - if (server.checkClientProof(clientProof)) { - - if (user.isMfaEnabled) { - // case: user has MFA enabled - - // generate temporary MFA token - const token = createToken({ - payload: { - userId: user._id.toString() - }, - expiresIn: getJwtMfaLifetime(), - secret: getJwtMfaSecret() - }); - - const code = await TokenService.createToken({ - type: TOKEN_EMAIL_MFA, - email - }); - - // send MFA code [code] to [email] - await sendMail({ - template: 'emailMfa.handlebars', - subjectLine: 'Infisical MFA code', - recipients: [email], - substitutions: { - code - } - }); - - return res.status(200).send({ - mfaEnabled: true, - token - }); - } - - await checkUserDevice({ - user, - ip: req.ip, - userAgent: req.headers['user-agent'] ?? '' + // generate temporary MFA token + const token = createToken({ + payload: { + userId: user._id.toString() + }, + expiresIn: await getJwtMfaLifetime(), + secret: await getJwtMfaSecret() }); - // issue tokens - const tokens = await issueAuthTokens({ userId: user._id.toString() }); - - // store (refresh) token in httpOnly cookie - res.cookie('jid', tokens.refreshToken, { - httpOnly: true, - path: '/', - sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false + const code = await TokenService.createToken({ + type: TOKEN_EMAIL_MFA, + email }); - // case: user does not have MFA enablgged - // return (access) token in response - - interface ResponseData { - mfaEnabled: boolean; - encryptionVersion: any; - protectedKey?: string; - protectedKeyIV?: string; - protectedKeyTag?: string; - token: string; - publicKey?: string; - encryptedPrivateKey?: string; - iv?: string; - tag?: string; - } - - const response: ResponseData = { - mfaEnabled: false, - encryptionVersion: user.encryptionVersion, - token: tokens.token, - publicKey: user.publicKey, - encryptedPrivateKey: user.encryptedPrivateKey, - iv: user.iv, - tag: user.tag - } - - if ( - user?.protectedKey && - user?.protectedKeyIV && - user?.protectedKeyTag - ) { - response.protectedKey = user.protectedKey; - response.protectedKeyIV = user.protectedKeyIV - response.protectedKeyTag = user.protectedKeyTag; - } - - const loginAction = await EELogService.createAction({ - name: ACTION_LOGIN, - userId: user._id + // send MFA code [code] to [email] + await sendMail({ + template: 'emailMfa.handlebars', + subjectLine: 'Infisical MFA code', + recipients: [email], + substitutions: { + code + } }); - loginAction && await EELogService.createLog({ - userId: user._id, - actions: [loginAction], - channel: getChannelFromUserAgent(req.headers['user-agent']), - ipAddress: req.ip + return res.status(200).send({ + mfaEnabled: true, + token }); - - return res.status(200).send(response); } - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' + await checkUserDevice({ + user, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' }); + + // issue tokens + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); + + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); + + // case: user does not have MFA enabled + // return (access) token in response + + interface ResponseData { + mfaEnabled: boolean; + encryptionVersion: any; + protectedKey?: string; + protectedKeyIV?: string; + protectedKeyTag?: string; + token: string; + publicKey?: string; + encryptedPrivateKey?: string; + iv?: string; + tag?: string; + } + + const response: ResponseData = { + mfaEnabled: false, + encryptionVersion: user.encryptionVersion, + token: tokens.token, + publicKey: user.publicKey, + encryptedPrivateKey: user.encryptedPrivateKey, + iv: user.iv, + tag: user.tag + } + + if ( + user?.protectedKey && + user?.protectedKeyIV && + user?.protectedKeyTag + ) { + response.protectedKey = user.protectedKey; + response.protectedKeyIV = user.protectedKeyIV + response.protectedKeyTag = user.protectedKeyTag; + } + + const loginAction = await EELogService.createAction({ + name: ACTION_LOGIN, + userId: user._id + }); + + loginAction && await EELogService.createLog({ + userId: user._id, + actions: [loginAction], + channel: getChannelFromUserAgent(req.headers['user-agent']), + ipAddress: req.ip + }); + + return res.status(200).send(response); } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to authenticate. Try again?' - }); - } + + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } + ); }; /** @@ -237,30 +223,22 @@ export const login2 = async (req: Request, res: Response) => { * @param res */ export const sendMfaToken = async (req: Request, res: Response) => { - try { - const { email } = req.body; + const { email } = req.body; - const code = await TokenService.createToken({ - type: TOKEN_EMAIL_MFA, - email - }); + const code = await TokenService.createToken({ + type: TOKEN_EMAIL_MFA, + email + }); - // send MFA code [code] to [email] - await sendMail({ - template: 'emailMfa.handlebars', - subjectLine: 'Infisical MFA code', - recipients: [email], - substitutions: { - code - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to send MFA code' - }); - } + // send MFA code [code] to [email] + await sendMail({ + template: 'emailMfa.handlebars', + subjectLine: 'Infisical MFA code', + recipients: [email], + substitutions: { + code + } + }); return res.status(200).send({ message: 'Successfully sent new MFA code' @@ -284,25 +262,31 @@ export const verifyMfaToken = async (req: Request, res: Response) => { const user = await User.findOne({ email - }).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag'); + }).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices'); if (!user) throw new Error('Failed to find user'); + await LoginSRPDetail.deleteOne({ userId: user.id }) + await checkUserDevice({ user, - ip: req.ip, + ip: req.realIP, userAgent: req.headers['user-agent'] ?? '' }); // issue tokens - const tokens = await issueAuthTokens({ userId: user._id.toString() }); + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); // store (refresh) token in httpOnly cookie res.cookie('jid', tokens.refreshToken, { httpOnly: true, path: '/', sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false + secure: await getHttpsEnabled() }); interface VerifyMfaTokenRes { @@ -353,7 +337,7 @@ export const verifyMfaToken = async (req: Request, res: Response) => { userId: user._id, actions: [loginAction], channel: getChannelFromUserAgent(req.headers['user-agent']), - ipAddress: req.ip + ipAddress: req.realIP }); return res.status(200).send(resObj); diff --git a/backend/src/controllers/v2/environmentController.ts b/backend/src/controllers/v2/environmentController.ts index b82dca9fe..d3ff5d0ab 100644 --- a/backend/src/controllers/v2/environmentController.ts +++ b/backend/src/controllers/v2/environmentController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { Secret, ServiceToken, @@ -9,9 +8,10 @@ import { Membership, } from '../../models'; import { SecretVersion } from '../../ee/models'; +import { EELicenseService } from '../../ee/services'; import { BadRequestError } from '../../utils/errors'; import _ from 'lodash'; -import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization'; +import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from '../../variables'; /** * Create new workspace environment named [environmentName] under workspace with id @@ -25,30 +25,24 @@ export const createWorkspaceEnvironment = async ( ) => { const { workspaceId } = req.params; const { environmentName, environmentSlug } = req.body; - try { - const workspace = await Workspace.findById(workspaceId).exec(); - if ( - !workspace || - workspace?.environments.find( - ({ name, slug }) => slug === environmentSlug || environmentName === name - ) - ) { - throw new Error('Failed to create workspace environment'); - } - - workspace?.environments.push({ - name: environmentName, - slug: environmentSlug.toLowerCase(), - }); - await workspace.save(); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to create new workspace environment', - }); + const workspace = await Workspace.findById(workspaceId).exec(); + if ( + !workspace || + workspace?.environments.find( + ({ name, slug }) => slug === environmentSlug || environmentName === name + ) + ) { + throw new Error('Failed to create workspace environment'); } + workspace?.environments.push({ + name: environmentName, + slug: environmentSlug.toLowerCase(), + }); + await workspace.save(); + + await EELicenseService.refreshPlan(workspace.organization.toString(), workspaceId); + return res.status(200).send({ message: 'Successfully created new environment', workspace: workspaceId, @@ -72,75 +66,67 @@ export const renameWorkspaceEnvironment = async ( ) => { const { workspaceId } = req.params; const { environmentName, environmentSlug, oldEnvironmentSlug } = req.body; - try { - // user should pass both new slug and env name - if (!environmentSlug || !environmentName) { - throw new Error('Invalid environment given.'); - } - - // atomic update the env to avoid conflict - const workspace = await Workspace.findById(workspaceId).exec(); - if (!workspace) { - throw new Error('Failed to create workspace environment'); - } - - const isEnvExist = workspace.environments.some( - ({ name, slug }) => - slug !== oldEnvironmentSlug && - (name === environmentName || slug === environmentSlug) - ); - if (isEnvExist) { - throw new Error('Invalid environment given'); - } - - const envIndex = workspace?.environments.findIndex( - ({ slug }) => slug === oldEnvironmentSlug - ); - if (envIndex === -1) { - throw new Error('Invalid environment given'); - } - - workspace.environments[envIndex].name = environmentName; - workspace.environments[envIndex].slug = environmentSlug.toLowerCase(); - - await workspace.save(); - await Secret.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await SecretVersion.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await ServiceToken.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await ServiceTokenData.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await Integration.updateMany( - { workspace: workspaceId, environment: oldEnvironmentSlug }, - { environment: environmentSlug } - ); - await Membership.updateMany( - { - workspace: workspaceId, - "deniedPermissions.environmentSlug": oldEnvironmentSlug - }, - { $set: { "deniedPermissions.$[element].environmentSlug": environmentSlug } }, - { arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] } - ) - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to update workspace environment', - }); + // user should pass both new slug and env name + if (!environmentSlug || !environmentName) { + throw new Error('Invalid environment given.'); } + // atomic update the env to avoid conflict + const workspace = await Workspace.findById(workspaceId).exec(); + if (!workspace) { + throw new Error('Failed to create workspace environment'); + } + + const isEnvExist = workspace.environments.some( + ({ name, slug }) => + slug !== oldEnvironmentSlug && + (name === environmentName || slug === environmentSlug) + ); + if (isEnvExist) { + throw new Error('Invalid environment given'); + } + + const envIndex = workspace?.environments.findIndex( + ({ slug }) => slug === oldEnvironmentSlug + ); + if (envIndex === -1) { + throw new Error('Invalid environment given'); + } + + workspace.environments[envIndex].name = environmentName; + workspace.environments[envIndex].slug = environmentSlug.toLowerCase(); + + await workspace.save(); + await Secret.updateMany( + { workspace: workspaceId, environment: oldEnvironmentSlug }, + { environment: environmentSlug } + ); + await SecretVersion.updateMany( + { workspace: workspaceId, environment: oldEnvironmentSlug }, + { environment: environmentSlug } + ); + await ServiceToken.updateMany( + { workspace: workspaceId, environment: oldEnvironmentSlug }, + { environment: environmentSlug } + ); + await ServiceTokenData.updateMany( + { workspace: workspaceId, environment: oldEnvironmentSlug }, + { environment: environmentSlug } + ); + await Integration.updateMany( + { workspace: workspaceId, environment: oldEnvironmentSlug }, + { environment: environmentSlug } + ); + await Membership.updateMany( + { + workspace: workspaceId, + "deniedPermissions.environmentSlug": oldEnvironmentSlug + }, + { $set: { "deniedPermissions.$[element].environmentSlug": environmentSlug } }, + { arrayFilters: [{ "element.environmentSlug": oldEnvironmentSlug }] } + ) + + return res.status(200).send({ message: 'Successfully update environment', workspace: workspaceId, @@ -163,57 +149,50 @@ export const deleteWorkspaceEnvironment = async ( ) => { const { workspaceId } = req.params; const { environmentSlug } = req.body; - try { - // atomic update the env to avoid conflict - const workspace = await Workspace.findById(workspaceId).exec(); - if (!workspace) { - throw new Error('Failed to create workspace environment'); - } - - const envIndex = workspace?.environments.findIndex( - ({ slug }) => slug === environmentSlug - ); - if (envIndex === -1) { - throw new Error('Invalid environment given'); - } - - workspace.environments.splice(envIndex, 1); - await workspace.save(); - - // clean up - await Secret.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await SecretVersion.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await ServiceToken.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await ServiceTokenData.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await Integration.deleteMany({ - workspace: workspaceId, - environment: environmentSlug, - }); - await Membership.updateMany( - { workspace: workspaceId }, - { $pull: { deniedPermissions: { environmentSlug: environmentSlug } } } - ) - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete workspace environment', - }); + // atomic update the env to avoid conflict + const workspace = await Workspace.findById(workspaceId).exec(); + if (!workspace) { + throw new Error('Failed to create workspace environment'); } + const envIndex = workspace?.environments.findIndex( + ({ slug }) => slug === environmentSlug + ); + if (envIndex === -1) { + throw new Error('Invalid environment given'); + } + + workspace.environments.splice(envIndex, 1); + await workspace.save(); + + // clean up + await Secret.deleteMany({ + workspace: workspaceId, + environment: environmentSlug, + }); + await SecretVersion.deleteMany({ + workspace: workspaceId, + environment: environmentSlug, + }); + await ServiceToken.deleteMany({ + workspace: workspaceId, + environment: environmentSlug, + }); + await ServiceTokenData.deleteMany({ + workspace: workspaceId, + environment: environmentSlug, + }); + await Integration.deleteMany({ + workspace: workspaceId, + environment: environmentSlug, + }); + await Membership.updateMany( + { workspace: workspaceId }, + { $pull: { deniedPermissions: { environmentSlug: environmentSlug } } } + ); + + await EELicenseService.refreshPlan(workspace.organization.toString(), workspaceId); + return res.status(200).send({ message: 'Successfully deleted environment', workspace: workspaceId, @@ -244,8 +223,8 @@ export const getAllAccessibleEnvironmentsOfWorkspace = async ( throw BadRequestError() } relatedWorkspace.environments.forEach(environment => { - const isReadBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: ABILITY_READ }) - const isWriteBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: ABILITY_WRITE }) + const isReadBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: PERMISSION_READ_SECRETS }) + const isWriteBlocked = _.some(deniedPermission, { environmentSlug: environment.slug, ability: PERMISSION_WRITE_SECRETS }) if (isReadBlocked && isWriteBlocked) { return } else { diff --git a/backend/src/controllers/v2/index.ts b/backend/src/controllers/v2/index.ts index d266ace3f..db78fa503 100644 --- a/backend/src/controllers/v2/index.ts +++ b/backend/src/controllers/v2/index.ts @@ -7,6 +7,7 @@ import * as serviceTokenDataController from './serviceTokenDataController'; import * as apiKeyDataController from './apiKeyDataController'; import * as secretController from './secretController'; import * as secretsController from './secretsController'; +import * as serviceAccountsController from './serviceAccountsController'; import * as environmentController from './environmentController'; import * as tagController from './tagController'; @@ -20,6 +21,7 @@ export { apiKeyDataController, secretController, secretsController, + serviceAccountsController, environmentController, tagController } diff --git a/backend/src/controllers/v2/organizationsController.ts b/backend/src/controllers/v2/organizationsController.ts index d167e5129..3bfd9085e 100644 --- a/backend/src/controllers/v2/organizationsController.ts +++ b/backend/src/controllers/v2/organizationsController.ts @@ -1,9 +1,10 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { MembershipOrg, Membership, - Workspace + Workspace, + ServiceAccount } from '../../models'; import { deleteMembershipOrg } from '../../helpers/membershipOrg'; import { updateSubscriptionOrgQuantity } from '../../helpers/organization'; @@ -47,20 +48,11 @@ export const getOrganizationMemberships = async (req: Request, res: Response) => } } */ - let memberships; - try { - const { organizationId } = req.params; + const { organizationId } = req.params; - memberships = await MembershipOrg.find({ + const memberships = await MembershipOrg.find({ organization: organizationId }).populate('user', '+publicKey'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organization memberships' - }); - } return res.status(200).send({ memberships @@ -126,26 +118,17 @@ export const updateOrganizationMembership = async (req: Request, res: Response) } } */ - let membership; - try { - const { membershipId } = req.params; - const { role } = req.body; - - membership = await MembershipOrg.findByIdAndUpdate( - membershipId, - { - role - }, { - new: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to update organization membership' - }); - } + const { membershipId } = req.params; + const { role } = req.body; + + const membership = await MembershipOrg.findByIdAndUpdate( + membershipId, + { + role + }, { + new: true + } + ); return res.status(200).send({ membership @@ -195,25 +178,16 @@ export const deleteOrganizationMembership = async (req: Request, res: Response) } } */ - let membership; - try { - const { membershipId } = req.params; - - // delete organization membership - membership = await deleteMembershipOrg({ - membershipOrgId: membershipId - }); + const { membershipId } = req.params; + + // delete organization membership + const membership = await deleteMembershipOrg({ + membershipOrgId: membershipId + }); - await updateSubscriptionOrgQuantity({ + await updateSubscriptionOrgQuantity({ organizationId: membership.organization.toString() }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete organization membership' - }); - } return res.status(200).send({ membership @@ -260,37 +234,45 @@ export const getOrganizationWorkspaces = async (req: Request, res: Response) => } } */ - let workspaces; - try { - const { organizationId } = req.params; + const { organizationId } = req.params; - const workspacesSet = new Set( - ( - await Workspace.find( - { - organization: organizationId - }, - '_id' - ) - ).map((w) => w._id.toString()) - ); + const workspacesSet = new Set( + ( + await Workspace.find( + { + organization: organizationId + }, + '_id' + ) + ).map((w) => w._id.toString()) + ); - workspaces = ( - await Membership.find({ - user: req.user._id - }).populate('workspace') - ) - .filter((m) => workspacesSet.has(m.workspace._id.toString())) - .map((m) => m.workspace); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get organization workspaces' - }); - } - - return res.status(200).send({ + const workspaces = ( + await Membership.find({ + user: req.user._id + }).populate('workspace') + ) + .filter((m) => workspacesSet.has(m.workspace._id.toString())) + .map((m) => m.workspace); + +return res.status(200).send({ workspaces }); -} \ No newline at end of file +} + +/** + * Return service accounts for organization with id [organizationId] + * @param req + * @param res + */ +export const getOrganizationServiceAccounts = async (req: Request, res: Response) => { + const { organizationId } = req.params; + + const serviceAccounts = await ServiceAccount.find({ + organization: new Types.ObjectId(organizationId) + }); + + return res.status(200).send({ + serviceAccounts + }); +} diff --git a/backend/src/controllers/v2/secretController.ts b/backend/src/controllers/v2/secretController.ts index cd91dca67..fecba43d6 100644 --- a/backend/src/controllers/v2/secretController.ts +++ b/backend/src/controllers/v2/secretController.ts @@ -6,8 +6,10 @@ import { CreateSecretRequestBody, ModifySecretRequestBody, SanitizedSecretForCre const { ValidationError } = mongoose.Error; import { BadRequestError, InternalServerError, UnauthorizedRequestError, ValidationError as RouteValidationError } from '../../utils/errors'; import { AnyBulkWriteOperation } from 'mongodb'; -import { SECRET_PERSONAL, SECRET_SHARED } from "../../variables"; -import { getPostHogClient } from '../../services'; +import { ALGORITHM_AES_256_GCM, ENCODING_SCHEME_UTF8, SECRET_PERSONAL, SECRET_SHARED } from "../../variables"; +import { TelemetryService } from '../../services'; +import { User } from "../../models"; +import { AccountNotFoundError } from '../../utils/errors'; /** * Create secret for workspace with id [workspaceId] and environment [environment] @@ -15,7 +17,7 @@ import { getPostHogClient } from '../../services'; * @param res */ export const createSecret = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const secretToCreate: CreateSecretRequestBody = req.body.secret; const { workspaceId, environment } = req.params const sanitizedSecret: SanitizedSecretForCreate = { @@ -34,7 +36,9 @@ export const createSecret = async (req: Request, res: Response) => { workspace: new Types.ObjectId(workspaceId), environment, type: secretToCreate.type, - user: new Types.ObjectId(req.user._id) + user: new Types.ObjectId(req.user._id), + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 } @@ -68,7 +72,7 @@ export const createSecret = async (req: Request, res: Response) => { * @param res */ export const createSecrets = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const secretsToCreate: CreateSecretRequestBody[] = req.body.secrets; const { workspaceId, environment } = req.params const sanitizedSecretesToCreate: SanitizedSecretForCreate[] = [] @@ -90,7 +94,9 @@ export const createSecrets = async (req: Request, res: Response) => { workspace: new Types.ObjectId(workspaceId), environment, type: rawSecret.type, - user: new Types.ObjectId(req.user._id) + user: new Types.ObjectId(req.user._id), + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 } sanitizedSecretesToCreate.push(safeUpdateFields) @@ -130,7 +136,7 @@ export const createSecrets = async (req: Request, res: Response) => { * @param res */ export const deleteSecrets = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const { workspaceId, environmentName } = req.params const secretIdsToDelete: string[] = req.body.secretIds @@ -184,7 +190,7 @@ export const deleteSecrets = async (req: Request, res: Response) => { * @param res */ export const deleteSecret = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); await Secret.findByIdAndDelete(req._secret._id) if (postHogClient) { @@ -213,7 +219,7 @@ export const deleteSecret = async (req: Request, res: Response) => { * @returns */ export const updateSecrets = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const { workspaceId, environmentName } = req.params const secretsModificationsRequested: ModifySecretRequestBody[] = req.body.secrets; const [secretIdsUserCanModifyError, secretIdsUserCanModify] = await to(Secret.find({ workspace: workspaceId, environment: environmentName }, { _id: 1 }).then()) @@ -281,7 +287,7 @@ export const updateSecrets = async (req: Request, res: Response) => { * @returns */ export const updateSecret = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const { workspaceId, environmentName } = req.params const secretModificationsRequested: ModifySecretRequestBody = req.body.secret; @@ -335,20 +341,23 @@ export const updateSecret = async (req: Request, res: Response) => { * @returns */ export const getSecrets = async (req: Request, res: Response) => { - const postHogClient = getPostHogClient(); + const postHogClient = await TelemetryService.getPostHogClient(); const { environment } = req.query; const { workspaceId } = req.params; let userId: Types.ObjectId | undefined = undefined // used for getting personal secrets for user - let userEmail: Types.ObjectId | undefined = undefined // used for posthog + let userEmail: string | undefined = undefined // used for posthog if (req.user) { userId = req.user._id; userEmail = req.user.email; } if (req.serviceTokenData) { - userId = req.serviceTokenData.user._id - userEmail = req.serviceTokenData.user.email; + userId = req.serviceTokenData.user; + + const user = await User.findById(req.serviceTokenData.user, 'email'); + if (!user) throw AccountNotFoundError(); + userEmail = user.email; } const [err, secrets] = await to(Secret.find( diff --git a/backend/src/controllers/v2/secretsController.ts b/backend/src/controllers/v2/secretsController.ts index 66aecd423..ae1de8cfe 100644 --- a/backend/src/controllers/v2/secretsController.ts +++ b/backend/src/controllers/v2/secretsController.ts @@ -1,282 +1,367 @@ -import to from 'await-to-js'; -import { Types } from 'mongoose'; -import { Request, Response } from 'express'; -import { ISecret, Secret } from '../../models'; -import { IAction } from '../../ee/models'; +import { Types } from "mongoose"; +import { Request, Response } from "express"; +import { ISecret, Secret, ServiceTokenData } from "../../models"; +import { IAction, SecretVersion } from "../../ee/models"; import { - SECRET_PERSONAL, - SECRET_SHARED, - ACTION_ADD_SECRETS, - ACTION_READ_SECRETS, - ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS -} from '../../variables'; -import { UnauthorizedRequestError, ValidationError } from '../../utils/errors'; -import { EventService } from '../../services'; -import { eventPushSecrets } from '../../events'; -import { EESecretService, EELogService } from '../../ee/services'; -import { getPostHogClient } from '../../services'; -import { getChannelFromUserAgent } from '../../utils/posthog'; -import { ABILITY_READ, ABILITY_WRITE } from '../../variables/organization'; -import { userHasNoAbility, userHasWorkspaceAccess, userHasWriteOnlyAbility } from '../../ee/helpers/checkMembershipPermissions'; -import Tag from '../../models/tag'; -import _ from 'lodash'; + SECRET_PERSONAL, + ACTION_ADD_SECRETS, + ACTION_READ_SECRETS, + ACTION_UPDATE_SECRETS, + ACTION_DELETE_SECRETS, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, +} from "../../variables"; +import { BadRequestError, UnauthorizedRequestError } from "../../utils/errors"; +import { EventService } from "../../services"; +import { eventPushSecrets } from "../../events"; +import { EESecretService, EELogService } from "../../ee/services"; +import { TelemetryService, SecretService } from "../../services"; +import { getChannelFromUserAgent } from "../../utils/posthog"; +import { PERMISSION_WRITE_SECRETS } from "../../variables"; import { - BatchSecretRequest, - BatchSecret -} from '../../types/secret'; + userHasNoAbility, + userHasWorkspaceAccess, + userHasWriteOnlyAbility, +} from "../../ee/helpers/checkMembershipPermissions"; +import Tag from "../../models/tag"; +import _ from "lodash"; +import { BatchSecretRequest, BatchSecret } from "../../types/secret"; +import Folder from "../../models/folder"; +import { + getFolderByPath, + getFolderIdFromServiceToken, + searchByFolderId, +} from "../../services/FolderService"; /** * Peform a batch of any specified CUD secret operations - * @param req - * @param res + * (used by dashboard) + * @param req + * @param res */ export const batchSecrets = async (req: Request, res: Response) => { - const channel = getChannelFromUserAgent(req.headers['user-agent']); - const postHogClient = getPostHogClient(); + const channel = getChannelFromUserAgent(req.headers["user-agent"]); + const postHogClient = await TelemetryService.getPostHogClient(); - const { - workspaceId, - environment, - requests - }: { - workspaceId: string; - environment: string; - requests: BatchSecretRequest[]; - } = req.body; + const { + workspaceId, + environment, + requests, + secretPath, + }: { + workspaceId: string; + environment: string; + requests: BatchSecretRequest[]; + secretPath: string; + } = req.body; + let folderId = req.body.folderId as string; - const createSecrets: BatchSecret[] = []; - const updateSecrets: BatchSecret[] = []; - const deleteSecrets: Types.ObjectId[] = []; - const actions: IAction[] = []; + const createSecrets: BatchSecret[] = []; + const updateSecrets: BatchSecret[] = []; + const deleteSecrets: Types.ObjectId[] = []; + const actions: IAction[] = []; - requests.forEach((request) => { - switch (request.method) { - case 'POST': - createSecrets.push({ - ...request.secret, - version: 1, - user: request.secret.type === SECRET_PERSONAL ? req.user : undefined, - environment, - workspace: new Types.ObjectId(workspaceId) - }); - break; - case 'PATCH': - updateSecrets.push({ - ...request.secret, - _id: new Types.ObjectId(request.secret._id) - }); - break; - case 'DELETE': - deleteSecrets.push(new Types.ObjectId(request.secret._id)); - break; - } + // get secret blind index salt + const salt = await SecretService.getSecretBlindIndexSalt({ + workspaceId: new Types.ObjectId(workspaceId), + }); + + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + if (folders && folderId !== "root") { + const folder = searchByFolderId(folders.nodes, folderId as string); + if (!folder) throw BadRequestError({ message: "Folder not found" }); + } + + if (req.authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = req.authData.authPayload; + // in service token when not giving secretpath folderid must be root + // this is to avoid giving folderid when service tokens are used + if ( + (!secretPath && folderId !== "root") || + (secretPath && secretPath !== serviceTkScopedSecretPath) + ) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + if (secretPath) { + folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + } + + for await (const request of requests) { + // do a validation + + let secretBlindIndex = ""; + switch (request.method) { + case "POST": + secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt( + { + secretName: request.secret.secretName, + salt, + } + ); + + createSecrets.push({ + ...request.secret, + version: 1, + user: request.secret.type === SECRET_PERSONAL ? req.user : undefined, + environment, + workspace: new Types.ObjectId(workspaceId), + folder: folderId, + secretBlindIndex, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + break; + case "PATCH": + secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt( + { + secretName: request.secret.secretName, + salt, + } + ); + + updateSecrets.push({ + ...request.secret, + _id: new Types.ObjectId(request.secret._id), + secretBlindIndex, + folder: folderId, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + break; + case "DELETE": + deleteSecrets.push(new Types.ObjectId(request.secret._id)); + break; + } + } + + // handle create secrets + let createdSecrets: ISecret[] = []; + if (createSecrets.length > 0) { + createdSecrets = await Secret.insertMany(createSecrets); + // (EE) add secret versions for new secrets + await EESecretService.addSecretVersions({ + secretVersions: createdSecrets.map((n: any) => { + return { + ...n._doc, + _id: new Types.ObjectId(), + secret: n._id, + isDeleted: false, + }; + }), }); - // handle create secrets - let createdSecrets: ISecret[] = []; - if (createSecrets.length > 0) { - createdSecrets = await Secret.insertMany(createSecrets); - // (EE) add secret versions for new secrets - await EESecretService.addSecretVersions({ - secretVersions: createdSecrets.map((n: any) => { - return ({ - ...n._doc, - _id: new Types.ObjectId(), - secret: n._id, - isDeleted: false - }); - }) - }); + const addAction = (await EELogService.createAction({ + name: ACTION_ADD_SECRETS, + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId), + secretIds: createdSecrets.map((n) => n._id), + })) as IAction; + actions.push(addAction); - const addAction = await EELogService.createAction({ - name: ACTION_ADD_SECRETS, - userId: req.user._id, - workspaceId: new Types.ObjectId(workspaceId), - secretIds: createdSecrets.map((n) => n._id) - }) as IAction; - actions.push(addAction); - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets added', - distinctId: req.user.email, - properties: { - numberOfSecrets: createdSecrets.length, - environment, - workspaceId, - channel, - userAgent: req.headers?.['user-agent'] - } - }); - } + if (postHogClient) { + postHogClient.capture({ + event: "secrets added", + distinctId: req.user.email, + properties: { + numberOfSecrets: createdSecrets.length, + environment, + workspaceId, + folderId, + channel, + userAgent: req.headers?.["user-agent"], + }, + }); } + } - // handle update secrets - let updatedSecrets: ISecret[] = []; - if (updateSecrets.length > 0 && req.secrets) { - // construct object containing all secrets - let listedSecretsObj: { - [key: string]: { - version: number; - type: string; - } - } = {}; + // handle update secrets + let updatedSecrets: ISecret[] = []; + if (updateSecrets.length > 0 && req.secrets) { + // construct object containing all secrets + let listedSecretsObj: { + [key: string]: { + version: number; + type: string; + }; + } = {}; - listedSecretsObj = req.secrets.reduce((obj: any, secret: ISecret) => ({ - ...obj, - [secret._id.toString()]: secret - }), {}); + listedSecretsObj = req.secrets.reduce( + (obj: any, secret: ISecret) => ({ + ...obj, + [secret._id.toString()]: secret, + }), + {} + ); - const updateOperations = updateSecrets.map((u) => ({ - updateOne: { - filter: { _id: new Types.ObjectId(u._id) }, - update: { - $inc: { - version: 1 - }, - ...u, - _id: new Types.ObjectId(u._id) - } - } - })); + const updateOperations = updateSecrets.map((u) => ({ + updateOne: { + filter: { + _id: new Types.ObjectId(u._id), + workspace: new Types.ObjectId(workspaceId), + }, + update: { + $inc: { + version: 1, + }, + ...u, + _id: new Types.ObjectId(u._id), + }, + }, + })); - await Secret.bulkWrite(updateOperations); + await Secret.bulkWrite(updateOperations); - const secretVersions = updateSecrets.map((u) => ({ - secret: new Types.ObjectId(u._id), - version: listedSecretsObj[u._id.toString()].version, - workspace: new Types.ObjectId(workspaceId), - type: listedSecretsObj[u._id.toString()].type, - environment, - isDeleted: false, - secretKeyCiphertext: u.secretKeyCiphertext, - secretKeyIV: u.secretKeyIV, - secretKeyTag: u.secretKeyTag, - secretValueCiphertext: u.secretValueCiphertext, - secretValueIV: u.secretValueIV, - secretValueTag: u.secretValueTag, - secretCommentCiphertext: u.secretCommentCiphertext, - secretCommentIV: u.secretCommentIV, - secretCommentTag: u.secretCommentTag, - tags: u.tags - })); - - await EESecretService.addSecretVersions({ - secretVersions - }); - - updatedSecrets = await Secret.find({ - _id: { - $in: updateSecrets.map((u) => new Types.ObjectId(u._id)) - } - }); - - const updateAction = await EELogService.createAction({ - name: ACTION_UPDATE_SECRETS, - userId: req.user._id, - workspaceId: new Types.ObjectId(workspaceId), - secretIds: updatedSecrets.map((u) => u._id) - }) as IAction; - actions.push(updateAction); - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets modified', - distinctId: req.user.email, - properties: { - numberOfSecrets: updateSecrets.length, - environment, - workspaceId, - channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - } - - // handle delete secrets - if (deleteSecrets.length > 0) { - await Secret.deleteMany({ - _id: { - $in: deleteSecrets - } - }); - - await EESecretService.markDeletedSecretVersions({ - secretIds: deleteSecrets - }); - - const deleteAction = await EELogService.createAction({ - name: ACTION_DELETE_SECRETS, - userId: req.user._id, - workspaceId: new Types.ObjectId(workspaceId), - secretIds: deleteSecrets - }) as IAction; - actions.push(deleteAction); - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets deleted', - distinctId: req.user.email, - properties: { - numberOfSecrets: deleteSecrets.length, - environment, - workspaceId, - channel: channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - } - - if (actions.length > 0) { - // (EE) create (audit) log - await EELogService.createLog({ - userId: req.user._id.toString(), - workspaceId: new Types.ObjectId(workspaceId), - actions, - channel, - ipAddress: req.ip - }); - } - - // // trigger event - push secrets - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId + const secretVersions = updateSecrets.map( + (u) => + new SecretVersion({ + secret: new Types.ObjectId(u._id), + version: listedSecretsObj[u._id.toString()].version, + workspace: new Types.ObjectId(workspaceId), + type: listedSecretsObj[u._id.toString()].type, + environment, + isDeleted: false, + secretBlindIndex: u.secretBlindIndex, + secretKeyCiphertext: u.secretKeyCiphertext, + secretKeyIV: u.secretKeyIV, + secretKeyTag: u.secretKeyTag, + secretValueCiphertext: u.secretValueCiphertext, + secretValueIV: u.secretValueIV, + secretValueTag: u.secretValueTag, + secretCommentCiphertext: u.secretCommentCiphertext, + secretCommentIV: u.secretCommentIV, + secretCommentTag: u.secretCommentTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + tags: u.tags, + folder: u.folder, }) + ); + + await EESecretService.addSecretVersions({ + secretVersions, }); - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId + updatedSecrets = await Secret.find({ + _id: { + $in: updateSecrets.map((u) => new Types.ObjectId(u._id)), + }, }); - const resObj: { [key: string]: ISecret[] | string[] } = {} + const updateAction = (await EELogService.createAction({ + name: ACTION_UPDATE_SECRETS, + userId: req.user._id, + workspaceId: new Types.ObjectId(workspaceId), + secretIds: updatedSecrets.map((u) => u._id), + })) as IAction; + actions.push(updateAction); - if (createSecrets.length > 0) { - resObj['createdSecrets'] = createdSecrets; + if (postHogClient) { + postHogClient.capture({ + event: "secrets modified", + distinctId: req.user.email, + properties: { + numberOfSecrets: updateSecrets.length, + environment, + workspaceId, + folderId, + channel, + userAgent: req.headers?.["user-agent"], + }, + }); } + } - if (updateSecrets.length > 0) { - resObj['updatedSecrets'] = updatedSecrets; + // handle delete secrets + if (deleteSecrets.length > 0) { + await Secret.deleteMany({ + _id: { + $in: deleteSecrets, + }, + }); + + await EESecretService.markDeletedSecretVersions({ + secretIds: deleteSecrets, + }); + + const deleteAction = (await EELogService.createAction({ + name: ACTION_DELETE_SECRETS, + userId: req.user._id, + workspaceId: new Types.ObjectId(workspaceId), + secretIds: deleteSecrets, + })) as IAction; + actions.push(deleteAction); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets deleted", + distinctId: req.user.email, + properties: { + numberOfSecrets: deleteSecrets.length, + environment, + workspaceId, + channel: channel, + userAgent: req.headers?.["user-agent"], + }, + }); } + } - if (deleteSecrets.length > 0) { - resObj['deletedSecrets'] = deleteSecrets.map((d) => d.toString()); - } + if (actions.length > 0) { + // (EE) create (audit) log + await EELogService.createLog({ + userId: req.user._id.toString(), + workspaceId: new Types.ObjectId(workspaceId), + actions, + channel, + ipAddress: req.realIP, + }); + } - return res.status(200).send(resObj); -} + // // trigger event - push secrets + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + }), + }); + + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + folderId, + }); + + const resObj: { [key: string]: ISecret[] | string[] } = {}; + + if (createSecrets.length > 0) { + resObj["createdSecrets"] = createdSecrets; + } + + if (updateSecrets.length > 0) { + resObj["updatedSecrets"] = updatedSecrets; + } + + if (deleteSecrets.length > 0) { + resObj["deletedSecrets"] = deleteSecrets.map((d) => d.toString()); + } + + return res.status(200).send(resObj); +}; /** * Create secret(s) for workspace with id [workspaceId] and environment [environment] - * @param req - * @param res + * @param req + * @param res */ export const createSecrets = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Create new secret(s)' #swagger.description = 'Create one or many secrets for a given project and environment.' @@ -328,41 +413,86 @@ export const createSecrets = async (req: Request, res: Response) => { } } */ - const postHogClient = getPostHogClient(); - const channel = getChannelFromUserAgent(req.headers['user-agent']) - const { workspaceId, environment }: { workspaceId: string, environment: string } = req.body; + const channel = getChannelFromUserAgent(req.headers["user-agent"]); + const { + workspaceId, + environment, + secretPath, + }: { + workspaceId: string; + environment: string; + secretPath?: string; + } = req.body; + let folderId = req.body.folderId; - const hasAccess = await userHasWorkspaceAccess(req.user, workspaceId, environment, ABILITY_WRITE) + if (req.user) { + const hasAccess = await userHasWorkspaceAccess( + req.user, + new Types.ObjectId(workspaceId), + environment, + PERMISSION_WRITE_SECRETS + ); if (!hasAccess) { - throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" }) + throw UnauthorizedRequestError({ + message: + "You do not have the necessary permission(s) perform this action", + }); } + } - let listOfSecretsToCreate; - if (Array.isArray(req.body.secrets)) { - // case: create multiple secrets - listOfSecretsToCreate = req.body.secrets; - } else if (typeof req.body.secrets === 'object') { - // case: create 1 secret - listOfSecretsToCreate = [req.body.secrets]; + let listOfSecretsToCreate; + if (Array.isArray(req.body.secrets)) { + // case: create multiple secrets + listOfSecretsToCreate = req.body.secrets; + } else if (typeof req.body.secrets === "object") { + // case: create 1 secret + listOfSecretsToCreate = [req.body.secrets]; + } + if (req.authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = req.authData.authPayload; + // in service token when not giving secretpath folderid must be root + // this is to avoid giving folderid when service tokens are used + if ( + (!secretPath && folderId !== "root") || + (secretPath && secretPath !== serviceTkScopedSecretPath) + ) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); } + } + if (secretPath) { + folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + } - type secretsToCreateType = { - type: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[] - } + // get secret blind index salt + const salt = await SecretService.getSecretBlindIndexSalt({ + workspaceId: new Types.ObjectId(workspaceId), + }); - const secretsToInsert: ISecret[] = listOfSecretsToCreate.map(({ + type secretsToCreateType = { + type: string; + secretName?: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretCommentCiphertext: string; + secretCommentIV: string; + secretCommentTag: string; + tags: string[]; + }; + + const secretsToInsert: ISecret[] = await Promise.all( + listOfSecretsToCreate.map( + async ({ type, + secretName, secretKeyCiphertext, secretKeyIV, secretKeyTag, @@ -372,128 +502,155 @@ export const createSecrets = async (req: Request, res: Response) => { secretCommentCiphertext, secretCommentIV, secretCommentTag, - tags - }: secretsToCreateType) => { - return ({ - version: 1, - workspace: new Types.ObjectId(workspaceId), - type, - user: type === SECRET_PERSONAL ? req.user : undefined, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - }); - }) + tags, + }: secretsToCreateType) => { + let secretBlindIndex; + if (secretName) { + secretBlindIndex = + await SecretService.generateSecretBlindIndexWithSalt({ + secretName, + salt, + }); + } - const newlyCreatedSecrets: ISecret[] = (await Secret.insertMany(secretsToInsert)).map((insertedSecret) => insertedSecret.toObject()); + return { + version: 1, + workspace: new Types.ObjectId(workspaceId), + type, + folderId, + ...(secretBlindIndex ? { secretBlindIndex } : {}), + user: req.user && type === SECRET_PERSONAL ? req.user : undefined, + environment, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + tags, + }; + } + ) + ); - setTimeout(async () => { - // trigger event - push secrets - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId - }) - }); - }, 5000); + const newlyCreatedSecrets: ISecret[] = ( + await Secret.insertMany(secretsToInsert) + ).map((insertedSecret) => insertedSecret.toObject()); - // (EE) add secret versions for new secrets - await EESecretService.addSecretVersions({ - secretVersions: newlyCreatedSecrets.map(({ - _id, - version, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - }) => ({ - _id: new Types.ObjectId(), - secret: _id, - version, - workspace, - type, - user, - environment, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - })) - }); - - const addAction = await EELogService.createAction({ - name: ACTION_ADD_SECRETS, - userId: req.user._id, + setTimeout(async () => { + // trigger event - push secrets + await EventService.handleEvent({ + event: eventPushSecrets({ workspaceId: new Types.ObjectId(workspaceId), - secretIds: newlyCreatedSecrets.map((n) => n._id) + }), }); + }, 5000); - // (EE) create (audit) log - addAction && await EELogService.createLog({ - userId: req.user._id.toString(), - workspaceId: new Types.ObjectId(workspaceId), - actions: [addAction], - channel, - ipAddress: req.ip + // (EE) add secret versions for new secrets + await EESecretService.addSecretVersions({ + secretVersions: newlyCreatedSecrets.map( + ({ + _id, + version, + workspace, + type, + user, + environment, + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + }) => + new SecretVersion({ + secret: _id, + version, + workspace, + type, + user, + environment, + secretBlindIndex, + isDeleted: false, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + folder: folderId, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }) + ), + }); + + const addAction = await EELogService.createAction({ + name: ACTION_ADD_SECRETS, + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId), + secretIds: newlyCreatedSecrets.map((n) => n._id), + }); + + // (EE) create (audit) log + addAction && + (await EELogService.createLog({ + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId), + actions: [addAction], + channel, + ipAddress: req.realIP, + })); + + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + folderId, + }); + + const postHogClient = await TelemetryService.getPostHogClient(); + if (postHogClient) { + postHogClient.capture({ + event: "secrets added", + distinctId: await TelemetryService.getDistinctId({ + authData: req.authData, + }), + properties: { + numberOfSecrets: listOfSecretsToCreate.length, + environment, + workspaceId, + channel: channel, + folderId, + userAgent: req.headers?.["user-agent"], + }, }); + } - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId - }); - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets added', - distinctId: req.user.email, - properties: { - numberOfSecrets: listOfSecretsToCreate.length, - environment, - workspaceId, - channel: channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - - return res.status(200).send({ - secrets: newlyCreatedSecrets - }); -} + return res.status(200).send({ + secrets: newlyCreatedSecrets, + }); +}; /** * Return secret(s) for workspace with id [workspaceId], environment [environment] and user * with id [req.user._id] - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const getSecrets = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Read secrets' #swagger.description = 'Read secrets from a project and environment' @@ -533,166 +690,193 @@ export const getSecrets = async (req: Request, res: Response) => { } */ - const postHogClient = getPostHogClient(); + const { tagSlugs, secretPath } = req.query; + let { folderId } = req.query; + const workspaceId = req.query.workspaceId as string; + const environment = req.query.environment as string; - const { workspaceId, environment, tagSlugs } = req.query; - const tagNamesList = typeof tagSlugs === 'string' && tagSlugs !== '' ? tagSlugs.split(',') : []; - let userId = "" // used for getting personal secrets for user - let userEmail = "" // used for posthog - if (req.user) { - userId = req.user._id; - userEmail = req.user.email; + const folders = await Folder.findOne({ workspace: workspaceId, environment }); + if ( + (!folders && folderId && folderId !== "root") || + (!folders && secretPath) + ) { + throw BadRequestError({ message: "Folder not found" }); + } + if (folders && folderId !== "root") { + const folder = searchByFolderId(folders.nodes, folderId as string); + if (!folder) throw BadRequestError({ message: "Folder not found" }); + } + + if (req.authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = req.authData.authPayload; + // in service token when not giving secretpath folderid must be root + // this is to avoid giving folderid when service tokens are used + if ( + (!secretPath && folderId !== "root") || + (secretPath && secretPath !== serviceTkScopedSecretPath) + ) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + + if (folders && secretPath) { + if (!folders) throw BadRequestError({ message: "Folder not found" }); + const folder = getFolderByPath(folders.nodes, secretPath as string); + if (!folder) { + throw BadRequestError({ message: "Secret path not found" }); + } + folderId = folder.id; + } + + // secrets to return + let secrets: ISecret[] = []; + + // query tags table to get all tags ids for the tag names for the given workspace + let tagIds = []; + const tagNamesList = + typeof tagSlugs === "string" && tagSlugs !== "" ? tagSlugs.split(",") : []; + if (tagNamesList != undefined && tagNamesList.length != 0) { + const workspaceFromDB = await Tag.find({ workspace: workspaceId }); + tagIds = _.map(tagNamesList, (tagName: string) => { + const tag = _.find(workspaceFromDB, { slug: tagName }); + return tag ? tag.id : null; + }); + } + + if (req.user) { + // case: client authorization is via JWT + const hasWriteOnlyAccess = await userHasWriteOnlyAbility( + req.user._id, + new Types.ObjectId(workspaceId), + environment + ); + const hasNoAccess = await userHasNoAbility( + req.user._id, + new Types.ObjectId(workspaceId), + environment + ); + if (hasNoAccess) { + throw UnauthorizedRequestError({ + message: + "You do not have the necessary permission(s) perform this action", + }); } - if (req.serviceTokenData) { - userId = req.serviceTokenData.user._id - userEmail = req.serviceTokenData.user.email; - } + const secretQuery: any = { + workspace: workspaceId, + environment, + folder: folderId, + $or: [ + { user: req.user._id }, // personal secrets for this user + { user: { $exists: false } }, // shared secrets from workspace + ], + }; - // none service token case as service tokens are already scoped to env and project - let hasWriteOnlyAccess - if (!req.serviceTokenData) { - hasWriteOnlyAccess = await userHasWriteOnlyAbility(userId, workspaceId, environment) - const hasNoAccess = await userHasNoAbility(userId, workspaceId, environment) - if (hasNoAccess) { - throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" }) - } - } - let secrets: any - let secretQuery: any - - if (tagNamesList != undefined && tagNamesList.length != 0) { - const workspaceFromDB = await Tag.find({ workspace: workspaceId }) - - const tagIds = _.map(tagNamesList, (tagName) => { - const tag = _.find(workspaceFromDB, { slug: tagName }); - return tag ? tag.id : null; - }); - - secretQuery = { - workspace: workspaceId, - environment, - $or: [ - { user: userId }, - { user: { $exists: false } } - ], - tags: { $in: tagIds }, - type: { $in: [SECRET_SHARED, SECRET_PERSONAL] } - } - } else { - secretQuery = { - workspace: workspaceId, - environment, - $or: [ - { user: userId }, - { user: { $exists: false } } - ], - type: { $in: [SECRET_SHARED, SECRET_PERSONAL] } - } + if (tagIds.length > 0) { + secretQuery.tags = { $in: tagIds }; } if (hasWriteOnlyAccess) { - secrets = await Secret.find(secretQuery).select("secretKeyCiphertext secretKeyIV secretKeyTag") + // only return the secret keys and not the values since user does not have right to see values + secrets = await Secret.find(secretQuery) + .select("secretKeyCiphertext secretKeyIV secretKeyTag") + .populate("tags"); } else { - secrets = await Secret.find(secretQuery).populate("tags") + secrets = await Secret.find(secretQuery).populate("tags"); + } + } + + // case: client authorization is via service token + if (req.serviceTokenData) { + const userId = req.serviceTokenData.user; + + const secretQuery: any = { + workspace: workspaceId, + folder: folderId, + environment, + $or: [ + { user: userId }, // personal secrets for this user + { user: { $exists: false } }, // shared secrets from workspace + ], + }; + + if (tagIds.length > 0) { + secretQuery.tags = { $in: tagIds }; } - const channel = getChannelFromUserAgent(req.headers['user-agent']) + // TODO check if service token has write only permission - const readAction = await EELogService.createAction({ - name: ACTION_READ_SECRETS, - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId as string), - secretIds: secrets.map((n: any) => n._id) - }); + secrets = await Secret.find(secretQuery).populate("tags"); + } - readAction && await EELogService.createLog({ - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId as string), - actions: [readAction], + // case: client authorization is via service account + if (req.serviceAccount) { + const secretQuery: any = { + workspace: workspaceId, + environment, + folder: folderId, + user: { $exists: false }, // shared secrets only from workspace + }; + + if (tagIds.length > 0) { + secretQuery.tags = { $in: tagIds }; + } + + secrets = await Secret.find(secretQuery).populate("tags"); + } + + const channel = getChannelFromUserAgent(req.headers["user-agent"]); + + const readAction = await EELogService.createAction({ + name: ACTION_READ_SECRETS, + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId as string), + secretIds: secrets.map((n: any) => n._id), + }); + + readAction && + (await EELogService.createLog({ + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(workspaceId as string), + actions: [readAction], + channel, + ipAddress: req.realIP, + })); + + const postHogClient = await TelemetryService.getPostHogClient(); + if (postHogClient) { + postHogClient.capture({ + event: "secrets pulled", + distinctId: await TelemetryService.getDistinctId({ + authData: req.authData, + }), + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, channel, - ipAddress: req.ip + folderId, + userAgent: req.headers?.["user-agent"], + }, }); + } - if (postHogClient) { - postHogClient.capture({ - event: 'secrets pulled', - distinctId: userEmail, - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - - return res.status(200).send({ - secrets - }); -} - - -export const getOnlySecretKeys = async (req: Request, res: Response) => { - const { workspaceId, environment } = req.query; - - let userId = "" // used for getting personal secrets for user - let userEmail = "" // used for posthog - if (req.user) { - userId = req.user._id; - userEmail = req.user.email; - } - - if (req.serviceTokenData) { - userId = req.serviceTokenData.user._id - userEmail = req.serviceTokenData.user.email; - } - - // none service token case as service tokens are already scoped - if (!req.serviceTokenData) { - const hasAccess = await userHasWorkspaceAccess(userId, workspaceId, environment, ABILITY_READ) - if (!hasAccess) { - throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" }) - } - } - - const [err, secretKeys] = await to(Secret.find( - { - workspace: workspaceId, - environment, - $or: [ - { user: userId }, - { user: { $exists: false } } - ], - type: { $in: [SECRET_SHARED, SECRET_PERSONAL] } - } - ) - .select("secretKeyIV secretKeyTag secretKeyCiphertext") - .then()) - - if (err) throw ValidationError({ message: 'Failed to get secrets', stack: err.stack }); - - // readAction && await EELogService.createLog({ - // userId: new Types.ObjectId(userId), - // workspaceId: new Types.ObjectId(workspaceId as string), - // actions: [readAction], - // channel, - // ipAddress: req.ip - // }); - - return res.status(200).send({ - secretKeys - }); -} + return res.status(200).send({ + secrets, + }); +}; /** * Update secret(s) - * @param req - * @param res + * @param req + * @param res */ export const updateSecrets = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Update secret(s)' #swagger.description = 'Update secret(s)' @@ -736,185 +920,211 @@ export const updateSecrets = async (req: Request, res: Response) => { } } */ - const postHogClient = getPostHogClient(); - const channel = req.headers?.['user-agent']?.toLowerCase().includes('mozilla') ? 'web' : 'cli'; + const channel = req.headers?.["user-agent"]?.toLowerCase().includes("mozilla") + ? "web" + : "cli"; - // TODO: move type - interface PatchSecret { - id: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[] - } + interface PatchSecret { + id: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretCommentCiphertext: string; + secretCommentIV: string; + secretCommentTag: string; + tags: string[]; + } - const updateOperationsToPerform = req.body.secrets.map((secret: PatchSecret) => { - const { + const updateOperationsToPerform = req.body.secrets.map( + (secret: PatchSecret) => { + const { + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + tags, + } = secret; + + return { + updateOne: { + filter: { _id: new Types.ObjectId(secret.id) }, + update: { + $inc: { + version: 1, + }, secretKeyCiphertext, secretKeyIV, secretKeyTag, secretValueCiphertext, secretValueIV, secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - } = secret; - - return ({ - updateOne: { - filter: { _id: new Types.ObjectId(secret.id) }, - update: { - $inc: { - version: 1 - }, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - tags, - ...(( - secretCommentCiphertext !== undefined && - secretCommentIV && - secretCommentTag - ) ? { - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - } : {}), + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + tags, + ...(secretCommentCiphertext !== undefined && + secretCommentIV && + secretCommentTag + ? { + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, } - } - }); - }); - - await Secret.bulkWrite(updateOperationsToPerform); - - const secretModificationsBySecretId: { [key: string]: PatchSecret } = {}; - req.body.secrets.forEach((secret: PatchSecret) => { - secretModificationsBySecretId[secret.id] = secret; - }); - - const ListOfSecretsBeforeModifications = req.secrets - const secretVersions = { - secretVersions: ListOfSecretsBeforeModifications.map((secret: ISecret) => { - const { - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - tags - } = secretModificationsBySecretId[secret._id.toString()] - - return ({ - secret: secret._id, - version: secret.version + 1, - workspace: secret.workspace, - type: secret.type, - environment: secret.environment, - secretKeyCiphertext: secretKeyCiphertext ? secretKeyCiphertext : secret.secretKeyCiphertext, - secretKeyIV: secretKeyIV ? secretKeyIV : secret.secretKeyIV, - secretKeyTag: secretKeyTag ? secretKeyTag : secret.secretKeyTag, - secretValueCiphertext: secretValueCiphertext ? secretValueCiphertext : secret.secretValueCiphertext, - secretValueIV: secretValueIV ? secretValueIV : secret.secretValueIV, - secretValueTag: secretValueTag ? secretValueTag : secret.secretValueTag, - secretCommentCiphertext: secretCommentCiphertext ? secretCommentCiphertext : secret.secretCommentCiphertext, - secretCommentIV: secretCommentIV ? secretCommentIV : secret.secretCommentIV, - secretCommentTag: secretCommentTag ? secretCommentTag : secret.secretCommentTag, - tags: tags ? tags : secret.tags - }); - }) + : {}), + }, + }, + }; } + ); - await EESecretService.addSecretVersions(secretVersions); + await Secret.bulkWrite(updateOperationsToPerform); + const secretModificationsBySecretId: { [key: string]: PatchSecret } = {}; + req.body.secrets.forEach((secret: PatchSecret) => { + secretModificationsBySecretId[secret.id] = secret; + }); - // group secrets into workspaces so updated secrets can - // be logged and snapshotted separately for each workspace - const workspaceSecretObj: any = {}; - req.secrets.forEach((s: any) => { - if (s.workspace.toString() in workspaceSecretObj) { - workspaceSecretObj[s.workspace.toString()].push(s); - } else { - workspaceSecretObj[s.workspace.toString()] = [s] - } + const ListOfSecretsBeforeModifications = req.secrets; + const secretVersions = { + secretVersions: ListOfSecretsBeforeModifications.map((secret: ISecret) => { + const { + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + tags, + } = secretModificationsBySecretId[secret._id.toString()]; + + return { + secret: secret._id, + version: secret.version + 1, + workspace: secret.workspace, + type: secret.type, + environment: secret.environment, + secretKeyCiphertext: secretKeyCiphertext + ? secretKeyCiphertext + : secret.secretKeyCiphertext, + secretKeyIV: secretKeyIV ? secretKeyIV : secret.secretKeyIV, + secretKeyTag: secretKeyTag ? secretKeyTag : secret.secretKeyTag, + secretValueCiphertext: secretValueCiphertext + ? secretValueCiphertext + : secret.secretValueCiphertext, + secretValueIV: secretValueIV ? secretValueIV : secret.secretValueIV, + secretValueTag: secretValueTag ? secretValueTag : secret.secretValueTag, + secretCommentCiphertext: secretCommentCiphertext + ? secretCommentCiphertext + : secret.secretCommentCiphertext, + secretCommentIV: secretCommentIV + ? secretCommentIV + : secret.secretCommentIV, + secretCommentTag: secretCommentTag + ? secretCommentTag + : secret.secretCommentTag, + tags: tags ? tags : secret.tags, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }; + }), + }; + + await EESecretService.addSecretVersions(secretVersions); + + // group secrets into workspaces so updated secrets can + // be logged and snapshotted separately for each workspace + const workspaceSecretObj: any = {}; + req.secrets.forEach((s: any) => { + if (s.workspace.toString() in workspaceSecretObj) { + workspaceSecretObj[s.workspace.toString()].push(s); + } else { + workspaceSecretObj[s.workspace.toString()] = [s]; + } + }); + + Object.keys(workspaceSecretObj).forEach(async (key) => { + // trigger event - push secrets + setTimeout(async () => { + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(key), + }), + }); + }, 10000); + + const updateAction = await EELogService.createAction({ + name: ACTION_UPDATE_SECRETS, + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(key), + secretIds: workspaceSecretObj[key].map((secret: ISecret) => secret._id), }); - Object.keys(workspaceSecretObj).forEach(async (key) => { - // trigger event - push secrets - setTimeout(async () => { - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: key - }) - }); - }, 10000); + // (EE) create (audit) log + updateAction && + (await EELogService.createLog({ + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(key), + actions: [updateAction], + channel, + ipAddress: req.realIP, + })); - const updateAction = await EELogService.createAction({ - name: ACTION_UPDATE_SECRETS, - userId: req.user._id, - workspaceId: new Types.ObjectId(key), - secretIds: workspaceSecretObj[key].map((secret: ISecret) => secret._id) - }); + // (EE) take a secret snapshot + // IMP(akhilmhdh): commented out due to unknown where the environment is + // await EESecretService.takeSecretSnapshot({ + // workspaceId: new Types.ObjectId(key), + // environment, + // folderId, + // }); - // (EE) create (audit) log - updateAction && await EELogService.createLog({ - userId: req.user._id.toString(), - workspaceId: new Types.ObjectId(key), - actions: [updateAction], - channel, - ipAddress: req.ip - }); + const postHogClient = await TelemetryService.getPostHogClient(); + if (postHogClient) { + postHogClient.capture({ + event: "secrets modified", + distinctId: await TelemetryService.getDistinctId({ + authData: req.authData, + }), + properties: { + numberOfSecrets: workspaceSecretObj[key].length, + environment: workspaceSecretObj[key][0].environment, + workspaceId: key, + channel: channel, + userAgent: req.headers?.["user-agent"], + }, + }); + } + }); - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: key - }) - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets modified', - distinctId: req.user.email, - properties: { - numberOfSecrets: workspaceSecretObj[key].length, - environment: workspaceSecretObj[key][0].environment, - workspaceId: key, - channel: channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - }); - - return res.status(200).send({ - secrets: await Secret.find({ - _id: { - $in: req.secrets.map((secret: ISecret) => secret._id) - } - }) - }); -} + return res.status(200).send({ + secrets: await Secret.find({ + _id: { + $in: req.secrets.map((secret: ISecret) => secret._id), + }, + }), + }); +}; /** - * Delete secret(s) with id [workspaceId] and environment [environment] - * @param req - * @param res + * Delete secret(s) + * @param req + * @param res */ export const deleteSecrets = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Delete secret(s)' #swagger.description = 'Delete one or many secrets by their ID(s)' @@ -958,75 +1168,84 @@ export const deleteSecrets = async (req: Request, res: Response) => { } } */ - const postHogClient = getPostHogClient(); - const channel = getChannelFromUserAgent(req.headers['user-agent']) - const toDelete = req.secrets.map((s: any) => s._id); - await Secret.deleteMany({ - _id: { - $in: toDelete - } + const channel = getChannelFromUserAgent(req.headers["user-agent"]); + const toDelete = req.secrets.map((s: any) => s._id); + + await Secret.deleteMany({ + _id: { + $in: toDelete, + }, + }); + + await EESecretService.markDeletedSecretVersions({ + secretIds: toDelete, + }); + + // group secrets into workspaces so deleted secrets can + // be logged and snapshotted separately for each workspace + const workspaceSecretObj: any = {}; + req.secrets.forEach((s: any) => { + if (s.workspace.toString() in workspaceSecretObj) { + workspaceSecretObj[s.workspace.toString()].push(s); + } else { + workspaceSecretObj[s.workspace.toString()] = [s]; + } + }); + + Object.keys(workspaceSecretObj).forEach(async (key) => { + // trigger event - push secrets + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(key), + }), + }); + const deleteAction = await EELogService.createAction({ + name: ACTION_DELETE_SECRETS, + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(key), + secretIds: workspaceSecretObj[key].map((secret: ISecret) => secret._id), }); - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete - }); + // (EE) create (audit) log + deleteAction && + (await EELogService.createLog({ + userId: req.user?._id, + serviceAccountId: req.serviceAccount?._id, + serviceTokenDataId: req.serviceTokenData?._id, + workspaceId: new Types.ObjectId(key), + actions: [deleteAction], + channel, + ipAddress: req.realIP, + })); - // group secrets into workspaces so deleted secrets can - // be logged and snapshotted separately for each workspace - const workspaceSecretObj: any = {}; - req.secrets.forEach((s: any) => { - if (s.workspace.toString() in workspaceSecretObj) { - workspaceSecretObj[s.workspace.toString()].push(s); - } else { - workspaceSecretObj[s.workspace.toString()] = [s] - } - }); + // (EE) take a secret snapshot + // IMP(akhilmhdh): Not sure how to take secretSnapshot + // await EESecretService.takeSecretSnapshot({ + // workspaceId: new Types.ObjectId(key), + // }); - Object.keys(workspaceSecretObj).forEach(async (key) => { - // trigger event - push secrets - await EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId: key - }) - }); - const deleteAction = await EELogService.createAction({ - name: ACTION_DELETE_SECRETS, - userId: req.user._id, - workspaceId: new Types.ObjectId(key), - secretIds: workspaceSecretObj[key].map((secret: ISecret) => secret._id) - }); + const postHogClient = await TelemetryService.getPostHogClient(); + if (postHogClient) { + postHogClient.capture({ + event: "secrets deleted", + distinctId: await TelemetryService.getDistinctId({ + authData: req.authData, + }), + properties: { + numberOfSecrets: workspaceSecretObj[key].length, + environment: workspaceSecretObj[key][0].environment, + workspaceId: key, + channel: channel, + userAgent: req.headers?.["user-agent"], + }, + }); + } + }); - // (EE) create (audit) log - deleteAction && await EELogService.createLog({ - userId: req.user._id.toString(), - workspaceId: new Types.ObjectId(key), - actions: [deleteAction], - channel, - ipAddress: req.ip - }); - - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: key - }) - - if (postHogClient) { - postHogClient.capture({ - event: 'secrets deleted', - distinctId: req.user.email, - properties: { - numberOfSecrets: workspaceSecretObj[key].length, - environment: workspaceSecretObj[key][0].environment, - workspaceId: key, - channel: channel, - userAgent: req.headers?.['user-agent'] - } - }); - } - }); - - return res.status(200).send({ - secrets: req.secrets - }); -} \ No newline at end of file + return res.status(200).send({ + secrets: req.secrets, + }); +}; diff --git a/backend/src/controllers/v2/serviceAccountsController.ts b/backend/src/controllers/v2/serviceAccountsController.ts new file mode 100644 index 000000000..d0ec62e1b --- /dev/null +++ b/backend/src/controllers/v2/serviceAccountsController.ts @@ -0,0 +1,306 @@ +import { Request, Response } from 'express'; +import { Types } from 'mongoose'; +import crypto from 'crypto'; +import bcrypt from 'bcrypt'; +import { + ServiceAccount, + ServiceAccountKey, + ServiceAccountOrganizationPermission, + ServiceAccountWorkspacePermission +} from '../../models'; +import { + CreateServiceAccountDto +} from '../../interfaces/serviceAccounts/dto'; +import { BadRequestError, ServiceAccountNotFoundError } from '../../utils/errors'; +import { getSaltRounds } from '../../config'; + +/** + * Return service account tied to the request (service account) client + * @param req + * @param res + */ +export const getCurrentServiceAccount = async (req: Request, res: Response) => { + const serviceAccount = await ServiceAccount.findById(req.serviceAccount._id); + + if (!serviceAccount) { + throw ServiceAccountNotFoundError({ message: 'Failed to find service account' }); + } + + return res.status(200).send({ + serviceAccount + }); +} + +/** + * Return service account with id [serviceAccountId] + * @param req + * @param res + */ +export const getServiceAccountById = async (req: Request, res: Response) => { + const { serviceAccountId } = req.params; + + const serviceAccount = await ServiceAccount.findById(serviceAccountId); + + if (!serviceAccount) { + throw ServiceAccountNotFoundError({ message: 'Failed to find service account' }); + } + + return res.status(200).send({ + serviceAccount + }); +} + +/** + * Create a new service account under organization with id [organizationId] + * that has access to workspaces [workspaces] + * @param req + * @param res + * @returns + */ +export const createServiceAccount = async (req: Request, res: Response) => { + const { + name, + organizationId, + publicKey, + expiresIn, + }: CreateServiceAccountDto = req.body; + + let expiresAt; + if (expiresIn) { + expiresAt = new Date(); + expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); + } + + const secret = crypto.randomBytes(16).toString('base64'); + const secretHash = await bcrypt.hash(secret, await getSaltRounds()); + + // create service account + const serviceAccount = await new ServiceAccount({ + name, + organization: new Types.ObjectId(organizationId), + user: req.user, + publicKey, + lastUsed: new Date(), + expiresAt, + secretHash + }).save(); + + const serviceAccountObj = serviceAccount.toObject(); + + delete serviceAccountObj.secretHash; + + // provision default org-level permission for service account + await new ServiceAccountOrganizationPermission({ + serviceAccount: serviceAccount._id + }).save(); + + const secretId = Buffer.from(serviceAccount._id.toString(), 'hex').toString('base64'); + + return res.status(200).send({ + serviceAccountAccessKey: `sa.${secretId}.${secret}`, + serviceAccount: serviceAccountObj + }); +} + +/** + * Change name of service account with id [serviceAccountId] to [name] + * @param req + * @param res + * @returns + */ +export const changeServiceAccountName = async (req: Request, res: Response) => { + const { serviceAccountId } = req.params; + const { name } = req.body; + + const serviceAccount = await ServiceAccount.findOneAndUpdate( + { + _id: new Types.ObjectId(serviceAccountId) + }, + { + name + }, + { + new: true + } + ); + + return res.status(200).send({ + serviceAccount + }); +} + +/** + * Add a service account key to service account with id [serviceAccountId] + * for workspace with id [workspaceId] + * @param req + * @param res + * @returns + */ +export const addServiceAccountKey = async (req: Request, res: Response) => { + const { + workspaceId, + encryptedKey, + nonce + } = req.body; + + const serviceAccountKey = await new ServiceAccountKey({ + encryptedKey, + nonce, + sender: req.user._id, + serviceAccount: req.serviceAccount._d, + workspace: new Types.ObjectId(workspaceId) + }).save(); + + return serviceAccountKey; +} + +/** + * Return workspace-level permission for service account with id [serviceAccountId] + * @param req + * @param res + */ +export const getServiceAccountWorkspacePermissions = async (req: Request, res: Response) => { + const serviceAccountWorkspacePermissions = await ServiceAccountWorkspacePermission.find({ + serviceAccount: req.serviceAccount._id + }).populate('workspace'); + + return res.status(200).send({ + serviceAccountWorkspacePermissions + }); +} + +/** + * Add a workspace permission to service account with id [serviceAccountId] + * @param req + * @param res + */ +export const addServiceAccountWorkspacePermission = async (req: Request, res: Response) => { + const { serviceAccountId } = req.params; + const { + environment, + workspaceId, + read = false, + write = false, + encryptedKey, + nonce + } = req.body; + + if (!req.membership.workspace.environments.some((e: { name: string; slug: string }) => e.slug === environment)) { + return res.status(400).send({ + message: 'Failed to validate workspace environment' + }); + } + + const existingPermission = await ServiceAccountWorkspacePermission.findOne({ + serviceAccount: new Types.ObjectId(serviceAccountId), + workspace: new Types.ObjectId(workspaceId), + environment + }); + + if (existingPermission) throw BadRequestError({ message: 'Failed to add workspace permission to service account due to already-existing ' }); + + const serviceAccountWorkspacePermission = await new ServiceAccountWorkspacePermission({ + serviceAccount: new Types.ObjectId(serviceAccountId), + workspace: new Types.ObjectId(workspaceId), + environment, + read, + write + }).save(); + + const existingServiceAccountKey = await ServiceAccountKey.findOne({ + serviceAccount: new Types.ObjectId(serviceAccountId), + workspace: new Types.ObjectId(workspaceId) + }); + + if (!existingServiceAccountKey) { + await new ServiceAccountKey({ + encryptedKey, + nonce, + sender: req.user._id, + serviceAccount: new Types.ObjectId(serviceAccountId), + workspace: new Types.ObjectId(workspaceId) + }).save(); + } + + return res.status(200).send({ + serviceAccountWorkspacePermission + }); +} + +/** + * Delete workspace permission from service account with id [serviceAccountId] + * @param req + * @param res + */ +export const deleteServiceAccountWorkspacePermission = async (req: Request, res: Response) => { + const { serviceAccountWorkspacePermissionId } = req.params; + const serviceAccountWorkspacePermission = await ServiceAccountWorkspacePermission.findByIdAndDelete(serviceAccountWorkspacePermissionId); + + if (serviceAccountWorkspacePermission) { + const { serviceAccount, workspace } = serviceAccountWorkspacePermission; + const count = await ServiceAccountWorkspacePermission.countDocuments({ + serviceAccount, + workspace + }); + + if (count === 0) { + await ServiceAccountKey.findOneAndDelete({ + serviceAccount, + workspace + }); + } + } + + return res.status(200).send({ + serviceAccountWorkspacePermission + }); +} + +/** + * Delete service account with id [serviceAccountId] + * @param req + * @param res + * @returns + */ +export const deleteServiceAccount = async (req: Request, res: Response) => { + const { serviceAccountId } = req.params; + + const serviceAccount = await ServiceAccount.findByIdAndDelete(serviceAccountId); + + if (serviceAccount) { + await ServiceAccountKey.deleteMany({ + serviceAccount: serviceAccount._id + }); + + await ServiceAccountOrganizationPermission.deleteMany({ + serviceAccount: new Types.ObjectId(serviceAccountId) + }); + + await ServiceAccountWorkspacePermission.deleteMany({ + serviceAccount: new Types.ObjectId(serviceAccountId) + }); + } + + return res.status(200).send({ + serviceAccount + }); +} + +/** + * Return service account keys for service account with id [serviceAccountId] + * @param req + * @param res + * @returns + */ +export const getServiceAccountKeys = async (req: Request, res: Response) => { + const workspaceId = req.query.workspaceId as string; + + const serviceAccountKeys = await ServiceAccountKey.find({ + serviceAccount: req.serviceAccount._id, + ...(workspaceId ? { workspace: new Types.ObjectId(workspaceId) } : {}) + }); + + return res.status(200).send({ + serviceAccountKeys + }); +} \ No newline at end of file diff --git a/backend/src/controllers/v2/serviceTokenDataController.ts b/backend/src/controllers/v2/serviceTokenDataController.ts index a4e06f8e4..21cc29b04 100644 --- a/backend/src/controllers/v2/serviceTokenDataController.ts +++ b/backend/src/controllers/v2/serviceTokenDataController.ts @@ -1,22 +1,27 @@ -import * as Sentry from '@sentry/node'; -import { Request, Response } from 'express'; -import crypto from 'crypto'; -import bcrypt from 'bcrypt'; +import { Request, Response } from "express"; +import crypto from "crypto"; +import bcrypt from "bcrypt"; +import { User, ServiceAccount, ServiceTokenData } from "../../models"; +import { userHasWorkspaceAccess } from "../../ee/helpers/checkMembershipPermissions"; import { - ServiceTokenData -} from '../../models'; -import { userHasWorkspaceAccess } from '../../ee/helpers/checkMembershipPermissions'; -import { ABILITY_READ } from '../../variables/organization'; -import { getSaltRounds } from '../../config'; + PERMISSION_READ_SECRETS, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, +} 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 - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const getServiceTokenData = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Return Infisical Token data' #swagger.description = 'Return Infisical Token data' @@ -29,115 +34,135 @@ export const getServiceTokenData = async (req: Request, res: Response) => { "application/json": { "schema": { "type": "object", - "properties": { + "properties": { "serviceTokenData": { "type": "object", $ref: "#/components/schemas/ServiceTokenData", "description": "Details of service token" } - } + } } } } } */ - return res.status(200).json(req.serviceTokenData); -} + if (!(req.authData.authPayload instanceof ServiceTokenData)) + throw BadRequestError({ + message: "Failed accepted client validation for service token data", + }); + + const serviceTokenData = await ServiceTokenData.findById( + req.authData.authPayload._id + ) + .select("+encryptedKey +iv +tag") + .populate("user"); + + return res.status(200).json(serviceTokenData); +}; /** * Create new service token data for workspace with id [workspaceId] and * environment [environment]. - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const createServiceTokenData = async (req: Request, res: Response) => { - let serviceToken, serviceTokenData; + let serviceTokenData; - try { - const { - name, - workspaceId, - environment, - encryptedKey, - iv, - tag, - expiresIn, - permissions - } = req.body; + const { + name, + workspaceId, + environment, + encryptedKey, + iv, + tag, + expiresIn, + secretPath, + permissions, + } = req.body; - const hasAccess = await userHasWorkspaceAccess(req.user, workspaceId, environment, ABILITY_READ) - if (!hasAccess) { - throw UnauthorizedRequestError({ message: "You do not have the necessary permission(s) perform this action" }) - } + const folders = await Folder.findOne({ + workspace: workspaceId, + environment, + }); - const secret = crypto.randomBytes(16).toString('hex'); - const secretHash = await bcrypt.hash(secret, getSaltRounds()); - - const expiresAt = new Date(); - expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); - - serviceTokenData = await new ServiceTokenData({ - name, - workspace: workspaceId, - environment, - user: req.user._id, - expiresAt, - secretHash, - encryptedKey, - iv, - tag, - permissions - }).save(); - - // return service token data without sensitive data - serviceTokenData = await ServiceTokenData.findById(serviceTokenData._id); - - if (!serviceTokenData) throw new Error('Failed to find service token data'); - - serviceToken = `st.${serviceTokenData._id.toString()}.${secret}`; - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to create service token data' - }); + if (folders) { + const folder = getFolderByPath(folders.nodes, secretPath); + if (folder == undefined) { + throw BadRequestError({ message: "Path for service token does not exist" }) } + } - return res.status(200).send({ - serviceToken, - serviceTokenData - }); -} + const secret = crypto.randomBytes(16).toString("hex"); + const secretHash = await bcrypt.hash(secret, await getSaltRounds()); + + let expiresAt; + if (expiresIn) { + expiresAt = new Date(); + expiresAt.setSeconds(expiresAt.getSeconds() + expiresIn); + } + + let user, serviceAccount; + + if ( + req.authData.authMode === AUTH_MODE_JWT && + req.authData.authPayload instanceof User + ) { + user = req.authData.authPayload._id; + } + + if ( + req.authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && + req.authData.authPayload instanceof ServiceAccount + ) { + serviceAccount = req.authData.authPayload._id; + } + + serviceTokenData = await new ServiceTokenData({ + name, + workspace: workspaceId, + environment, + user, + serviceAccount, + lastUsed: new Date(), + expiresAt, + secretHash, + encryptedKey, + iv, + tag, + secretPath, + permissions, + }).save(); + + // return service token data without sensitive data + serviceTokenData = await ServiceTokenData.findById(serviceTokenData._id); + + if (!serviceTokenData) throw new Error("Failed to find service token data"); + + const serviceToken = `st.${serviceTokenData._id.toString()}.${secret}`; + + return res.status(200).send({ + serviceToken, + serviceTokenData, + }); +}; /** * Delete service token data with id [serviceTokenDataId]. - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const deleteServiceTokenData = async (req: Request, res: Response) => { - let serviceTokenData; - try { - const { serviceTokenDataId } = req.params; + const { serviceTokenDataId } = req.params; - serviceTokenData = await ServiceTokenData.findByIdAndDelete(serviceTokenDataId); + const serviceTokenData = await ServiceTokenData.findByIdAndDelete( + serviceTokenDataId + ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete service token data' - }); - } - - return res.status(200).send({ - serviceTokenData - }); -} - -function UnauthorizedRequestError(arg0: { message: string; }) { - throw new Error('Function not implemented.'); -} \ No newline at end of file + return res.status(200).send({ + serviceTokenData, + }); +}; diff --git a/backend/src/controllers/v2/signupController.ts b/backend/src/controllers/v2/signupController.ts index aaf055b78..ada119ee9 100644 --- a/backend/src/controllers/v2/signupController.ts +++ b/backend/src/controllers/v2/signupController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { User, MembershipOrg } from '../../models'; import { completeAccount } from '../../helpers/user'; import { @@ -7,8 +6,9 @@ import { } from '../../helpers/signup'; import { issueAuthTokens } from '../../helpers/auth'; import { INVITED, ACCEPTED } from '../../variables'; -import request from '../../config/request'; -import { getNodeEnv, getLoopsApiKey } from '../../config'; +import { standardRequest } from '../../config/request'; +import { getLoopsApiKey, getHttpsEnabled } from '../../config'; +import { updateSubscriptionOrgQuantity } from '../../helpers/organization'; /** * Complete setting up user by adding their personal and auth information as part of the @@ -19,123 +19,130 @@ import { getNodeEnv, getLoopsApiKey } from '../../config'; */ export const completeAccountSignup = async (req: Request, res: Response) => { let user, token, refreshToken; - try { - const { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier, - organizationName - }: { - email: string; - firstName: string; - lastName: string; - protectedKey: string; - protectedKeyIV: string; - protectedKeyTag: string; - publicKey: string; - encryptedPrivateKey: string; - encryptedPrivateKeyIV: string; - encryptedPrivateKeyTag: string; - salt: string; - verifier: string; - organizationName: string; - } = req.body; + const { + email, + firstName, + lastName, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier, + organizationName + }: { + email: string; + firstName: string; + lastName: string; + protectedKey: string; + protectedKeyIV: string; + protectedKeyTag: string; + publicKey: string; + encryptedPrivateKey: string; + encryptedPrivateKeyIV: string; + encryptedPrivateKeyTag: string; + salt: string; + verifier: string; + organizationName: string; + } = req.body; - // get user - user = await User.findOne({ email }); - - if (!user || (user && user?.publicKey)) { - // case 1: user doesn't exist. - // case 2: user has already completed account - return res.status(403).send({ - error: 'Failed to complete account for complete user' - }); - } + // get user + user = await User.findOne({ email }); - // complete setting up user's account - user = await completeAccount({ - userId: user._id.toString(), - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }); + if (!user || (user && user?.publicKey)) { + // case 1: user doesn't exist. + // case 2: user has already completed account + return res.status(403).send({ + error: 'Failed to complete account for complete user' + }); + } - if (!user) - throw new Error('Failed to complete account for non-existent user'); // ensure user is non-null + // complete setting up user's account + user = await completeAccount({ + userId: user._id.toString(), + firstName, + lastName, + encryptionVersion: 2, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier + }); - // initialize default organization and workspace - await initializeDefaultOrg({ - organizationName, - user - }); + if (!user) + throw new Error('Failed to complete account for non-existent user'); // ensure user is non-null - // update organization membership statuses that are - // invited to completed with user attached - await MembershipOrg.updateMany( - { - inviteEmail: email, - status: INVITED - }, - { - user, - status: ACCEPTED - } - ); + // initialize default organization and workspace + await initializeDefaultOrg({ + organizationName, + user + }); - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id.toString() - }); + // update organization membership statuses that are + // invited to completed with user attached + const membershipsToUpdate = await MembershipOrg.find({ + inviteEmail: email, + status: INVITED + }); + + membershipsToUpdate.forEach(async (membership) => { + await updateSubscriptionOrgQuantity({ + organizationId: membership.organization.toString() + }); + }); - token = tokens.token; + // update organization membership statuses that are + // invited to completed with user attached + await MembershipOrg.updateMany( + { + inviteEmail: email, + status: INVITED + }, + { + user, + status: ACCEPTED + } + ); - // sending a welcome email to new users - if (getLoopsApiKey()) { - await request.post("https://app.loops.so/api/v1/events/send", { - "email": email, - "eventName": "Sign Up", - "firstName": firstName, - "lastName": lastName - }, { - headers: { - "Accept": "application/json", - "Authorization": "Bearer " + getLoopsApiKey() - }, - }); - } + // issue tokens + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); - // store (refresh) token in httpOnly cookie - res.cookie('jid', tokens.refreshToken, { - httpOnly: true, - path: '/', - sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to complete account setup' - }); - } + token = tokens.token; + + // sending a welcome email to new users + if (await getLoopsApiKey()) { + await standardRequest.post("https://app.loops.so/api/v1/events/send", { + "email": email, + "eventName": "Sign Up", + "firstName": firstName, + "lastName": lastName + }, { + headers: { + "Accept": "application/json", + "Authorization": "Bearer " + (await getLoopsApiKey()) + }, + }); + } + + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); return res.status(200).send({ message: 'Successfully set up account', @@ -153,98 +160,103 @@ export const completeAccountSignup = async (req: Request, res: Response) => { */ export const completeAccountInvite = async (req: Request, res: Response) => { let user, token, refreshToken; - try { - const { - email, - firstName, - lastName, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - } = req.body; + const { + email, + firstName, + lastName, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier + } = req.body; - // get user - user = await User.findOne({ email }); + // get user + user = await User.findOne({ email }); - if (!user || (user && user?.publicKey)) { - // case 1: user doesn't exist. - // case 2: user has already completed account - return res.status(403).send({ - error: 'Failed to complete account for complete user' - }); - } + if (!user || (user && user?.publicKey)) { + // case 1: user doesn't exist. + // case 2: user has already completed account + return res.status(403).send({ + error: 'Failed to complete account for complete user' + }); + } - const membershipOrg = await MembershipOrg.findOne({ - inviteEmail: email, - status: INVITED - }); + const membershipOrg = await MembershipOrg.findOne({ + inviteEmail: email, + status: INVITED + }); - if (!membershipOrg) throw new Error('Failed to find invitations for email'); + if (!membershipOrg) throw new Error('Failed to find invitations for email'); - // complete setting up user's account - user = await completeAccount({ - userId: user._id.toString(), - firstName, - lastName, - encryptionVersion: 2, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - encryptedPrivateKeyIV, - encryptedPrivateKeyTag, - salt, - verifier - }); + // complete setting up user's account + user = await completeAccount({ + userId: user._id.toString(), + firstName, + lastName, + encryptionVersion: 2, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier + }); - if (!user) - throw new Error('Failed to complete account for non-existent user'); + if (!user) + throw new Error('Failed to complete account for non-existent user'); + + // update organization membership statuses that are + // invited to completed with user attached + const membershipsToUpdate = await MembershipOrg.find({ + inviteEmail: email, + status: INVITED + }); + + membershipsToUpdate.forEach(async (membership) => { + await updateSubscriptionOrgQuantity({ + organizationId: membership.organization.toString() + }); + }); - // update organization membership statuses that are - // invited to completed with user attached - await MembershipOrg.updateMany( - { - inviteEmail: email, - status: INVITED - }, - { - user, - status: ACCEPTED - } - ); + await MembershipOrg.updateMany( + { + inviteEmail: email, + status: INVITED + }, + { + user, + status: ACCEPTED + } + ); - // issue tokens - const tokens = await issueAuthTokens({ - userId: user._id.toString() - }); + // issue tokens + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); - token = tokens.token; + token = tokens.token; + + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); - // store (refresh) token in httpOnly cookie - res.cookie('jid', tokens.refreshToken, { - httpOnly: true, - path: '/', - sameSite: 'strict', - secure: getNodeEnv() === 'production' ? true : false - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to complete account setup' - }); - } - return res.status(200).send({ message: 'Successfully set up account', user, token }); -}; \ No newline at end of file +}; diff --git a/backend/src/controllers/v2/tagController.ts b/backend/src/controllers/v2/tagController.ts index 199f2401e..0175b359a 100644 --- a/backend/src/controllers/v2/tagController.ts +++ b/backend/src/controllers/v2/tagController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { Types } from 'mongoose'; import { Membership, Secret, @@ -69,4 +68,4 @@ export const getWorkspaceTags = async (req: Request, res: Response) => { return res.json({ workspaceTags }) -} \ No newline at end of file +} diff --git a/backend/src/controllers/v2/usersController.ts b/backend/src/controllers/v2/usersController.ts index 9940ddc56..2d5cdc51a 100644 --- a/backend/src/controllers/v2/usersController.ts +++ b/backend/src/controllers/v2/usersController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { User, MembershipOrg @@ -37,18 +36,9 @@ export const getMe = async (req: Request, res: Response) => { } } */ - let user; - try { - user = await User - .findById(req.user._id) - .select('+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get current user' - }); - } + const user = await User + .findById(req.user._id) + .select('+salt +publicKey +encryptedPrivateKey +iv +tag +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag'); return res.status(200).send({ user @@ -64,29 +54,20 @@ export const getMe = async (req: Request, res: Response) => { * @returns */ export const updateMyMfaEnabled = async (req: Request, res: Response) => { - let user; - try { - const { isMfaEnabled }: { isMfaEnabled: boolean } = req.body; - req.user.isMfaEnabled = isMfaEnabled; - - if (isMfaEnabled) { - // TODO: adapt this route/controller - // to work for different forms of MFA - req.user.mfaMethods = ['email']; - } else { - req.user.mfaMethods = []; - } - - await req.user.save(); - - user = req.user; - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to update current user's MFA status" - }); + const { isMfaEnabled }: { isMfaEnabled: boolean } = req.body; + req.user.isMfaEnabled = isMfaEnabled; + + if (isMfaEnabled) { + // TODO: adapt this route/controller + // to work for different forms of MFA + req.user.mfaMethods = ['email']; + } else { + req.user.mfaMethods = []; } + + await req.user.save(); + + const user = req.user; return res.status(200).send({ user @@ -126,22 +107,13 @@ export const getMyOrganizations = async (req: Request, res: Response) => { } } */ - let organizations; - try { - organizations = ( - await MembershipOrg.find({ - user: req.user._id - }).populate('organization') - ).map((m) => m.organization); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: "Failed to get current user's organizations" - }); - } + const organizations = ( + await MembershipOrg.find({ + user: req.user._id + }).populate('organization') + ).map((m) => m.organization); return res.status(200).send({ organizations }); -} \ No newline at end of file +} diff --git a/backend/src/controllers/v2/workspaceController.ts b/backend/src/controllers/v2/workspaceController.ts index 650c70610..20778491d 100644 --- a/backend/src/controllers/v2/workspaceController.ts +++ b/backend/src/controllers/v2/workspaceController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { Types } from 'mongoose'; import { Workspace, @@ -19,7 +18,7 @@ import { reformatPullSecrets } from '../../helpers/secret'; import { pushKeys } from '../../helpers/key'; -import { getPostHogClient, EventService } from '../../services'; +import { TelemetryService, EventService } from '../../services'; import { eventPushSecrets } from '../../events'; interface V2PushSecret { @@ -47,65 +46,57 @@ interface V2PushSecret { */ export const pushWorkspaceSecrets = async (req: Request, res: Response) => { // upload (encrypted) secrets to workspace with id [workspaceId] - try { - const postHogClient = getPostHogClient(); - let { secrets }: { secrets: V2PushSecret[] } = req.body; - const { keys, environment, channel } = req.body; - const { workspaceId } = req.params; + const postHogClient = await TelemetryService.getPostHogClient(); + let { secrets }: { secrets: V2PushSecret[] } = req.body; + const { keys, environment, channel } = req.body; + const { workspaceId } = req.params; - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error('Failed to validate environment'); - } + // validate environment + const workspaceEnvs = req.membership.workspace.environments; + if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { + throw new Error('Failed to validate environment'); + } - // sanitize secrets - secrets = secrets.filter( - (s: V2PushSecret) => s.secretKeyCiphertext !== '' && s.secretValueCiphertext !== '' - ); + // sanitize secrets + secrets = secrets.filter( + (s: V2PushSecret) => s.secretKeyCiphertext !== '' && s.secretValueCiphertext !== '' + ); - await push({ - userId: req.user._id, - workspaceId, - environment, - secrets, - channel: channel ? channel : 'cli', - ipAddress: req.ip - }); + await push({ + userId: req.user._id, + workspaceId, + environment, + secrets, + channel: channel ? channel : 'cli', + ipAddress: req.realIP + }); - await pushKeys({ - userId: req.user._id, - workspaceId, - keys - }); + await pushKeys({ + userId: req.user._id, + workspaceId, + keys + }); - if (postHogClient) { - postHogClient.capture({ - event: 'secrets pushed', - distinctId: req.user.email, - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : 'cli' - } - }); - } + if (postHogClient) { + postHogClient.capture({ + event: 'secrets pushed', + distinctId: req.user.email, + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + channel: channel ? channel : 'cli' + } + }); + } - // trigger event - push secrets - EventService.handleEvent({ - event: eventPushSecrets({ - workspaceId - }) - }); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to upload workspace secrets' - }); - } + // trigger event - push secrets + EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment + }) + }); return res.status(200).send({ message: 'Successfully uploaded workspace secrets' @@ -121,56 +112,48 @@ export const pushWorkspaceSecrets = async (req: Request, res: Response) => { */ export const pullSecrets = async (req: Request, res: Response) => { let secrets; - try { - const postHogClient = getPostHogClient(); - const environment: string = req.query.environment as string; - const channel: string = req.query.channel as string; - const { workspaceId } = req.params; + const postHogClient = await TelemetryService.getPostHogClient(); + const environment: string = req.query.environment as string; + const channel: string = req.query.channel as string; + const { workspaceId } = req.params; - let userId; - if (req.user) { - userId = req.user._id.toString(); - } else if (req.serviceTokenData) { - userId = req.serviceTokenData.user._id - } - // validate environment - const workspaceEnvs = req.membership.workspace.environments; - if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { - throw new Error('Failed to validate environment'); - } + let userId; + if (req.user) { + userId = req.user._id.toString(); + } else if (req.serviceTokenData) { + userId = req.serviceTokenData.user.toString(); + } + // validate environment + const workspaceEnvs = req.membership.workspace.environments; + if (!workspaceEnvs.find(({ slug }: { slug: string }) => slug === environment)) { + throw new Error('Failed to validate environment'); + } - secrets = await pull({ - userId, - workspaceId, - environment, - channel: channel ? channel : 'cli', - ipAddress: req.ip - }); + secrets = await pull({ + userId, + workspaceId, + environment, + channel: channel ? channel : 'cli', + ipAddress: req.realIP + }); - if (channel !== 'cli') { - secrets = reformatPullSecrets({ secrets }); - } + if (channel !== 'cli') { + secrets = reformatPullSecrets({ secrets }); + } - if (postHogClient) { - // capture secrets pushed event in production - postHogClient.capture({ - distinctId: req.user.email, - event: 'secrets pulled', - properties: { - numberOfSecrets: secrets.length, - environment, - workspaceId, - channel: channel ? channel : 'cli' - } - }); - } - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to pull workspace secrets' - }); - } + if (postHogClient) { + // capture secrets pushed event in production + postHogClient.capture({ + distinctId: req.user.email, + event: 'secrets pulled', + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + channel: channel ? channel : 'cli' + } + }); + } return res.status(200).send({ secrets @@ -207,22 +190,14 @@ export const getWorkspaceKey = async (req: Request, res: Response) => { } */ let key; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - key = await Key.findOne({ - workspace: workspaceId, - receiver: req.user._id - }).populate('sender', '+publicKey'); + key = await Key.findOne({ + workspace: workspaceId, + receiver: req.user._id + }).populate('sender', '+publicKey'); - if (!key) throw new Error('Failed to find workspace key'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get workspace key' - }); - } + if (!key) throw new Error('Failed to find workspace key'); return res.status(200).json(key); } @@ -230,23 +205,13 @@ export const getWorkspaceServiceTokenData = async ( req: Request, res: Response ) => { - let serviceTokenData; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - serviceTokenData = await ServiceTokenData - .find({ - workspace: workspaceId - }) - .select('+encryptedKey +iv +tag'); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get workspace service token data' - }); - } + const serviceTokenData = await ServiceTokenData + .find({ + workspace: workspaceId + }) + .select('+encryptedKey +iv +tag'); return res.status(200).send({ serviceTokenData @@ -293,20 +258,11 @@ export const getWorkspaceMemberships = async (req: Request, res: Response) => { } } */ - let memberships; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - memberships = await Membership.find({ - workspace: workspaceId - }).populate('user', '+publicKey'); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get workspace memberships' - }); - } + const memberships = await Membership.find({ + workspace: workspaceId + }).populate('user', '+publicKey'); return res.status(200).send({ memberships @@ -373,29 +329,20 @@ export const updateWorkspaceMembership = async (req: Request, res: Response) => } } */ - let membership; - try { - const { - membershipId - } = req.params; - const { role } = req.body; - - membership = await Membership.findByIdAndUpdate( - membershipId, - { - role - }, { - new: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to update workspace membership' - }); - } - + const { + membershipId + } = req.params; + const { role } = req.body; + + const membership = await Membership.findByIdAndUpdate( + membershipId, + { + role + }, { + new: true + } + ); + return res.status(200).send({ membership }); @@ -444,27 +391,18 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) => } } */ - let membership; - try { - const { - membershipId - } = req.params; - - membership = await Membership.findByIdAndDelete(membershipId); - - if (!membership) throw new Error('Failed to delete workspace membership'); - - await Key.deleteMany({ - receiver: membership.user, - workspace: membership.workspace - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to delete workspace membership' - }); - } + const { + membershipId + } = req.params; + + const membership = await Membership.findByIdAndDelete(membershipId); + + if (!membership) throw new Error('Failed to delete workspace membership'); + + await Key.deleteMany({ + receiver: membership.user, + workspace: membership.workspace + }); return res.status(200).send({ membership @@ -478,33 +416,23 @@ export const deleteWorkspaceMembership = async (req: Request, res: Response) => * @returns */ export const toggleAutoCapitalization = async (req: Request, res: Response) => { - let workspace; - try { - const { workspaceId } = req.params; - const { autoCapitalization } = req.body; + const { workspaceId } = req.params; + const { autoCapitalization } = req.body; - workspace = await Workspace.findOneAndUpdate( - { - _id: workspaceId - }, - { - autoCapitalization - }, - { - new: true - } - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to change autoCapitalization setting' - }); - } + const workspace = await Workspace.findOneAndUpdate( + { + _id: workspaceId + }, + { + autoCapitalization + }, + { + new: true + } + ); return res.status(200).send({ message: 'Successfully changed autoCapitalization setting', workspace }); }; - diff --git a/backend/src/controllers/v3/authController.ts b/backend/src/controllers/v3/authController.ts new file mode 100644 index 000000000..afb670269 --- /dev/null +++ b/backend/src/controllers/v3/authController.ts @@ -0,0 +1,264 @@ +/* eslint-disable @typescript-eslint/no-var-requires */ +import { Request, Response } from 'express'; +import jwt from 'jsonwebtoken'; +import * as Sentry from '@sentry/node'; +import * as bigintConversion from 'bigint-conversion'; +const jsrp = require('jsrp'); +import { User, LoginSRPDetail } from '../../models'; +import { issueAuthTokens, createToken, validateProviderAuthToken } from '../../helpers/auth'; +import { checkUserDevice } from '../../helpers/user'; +import { sendMail } from '../../helpers/nodemailer'; +import { TokenService } from '../../services'; +import { EELogService } from '../../ee/services'; +import { BadRequestError, InternalServerError } from '../../utils/errors'; +import { + TOKEN_EMAIL_MFA, + ACTION_LOGIN +} from '../../variables'; +import { getChannelFromUserAgent } from '../../utils/posthog'; // TODO: move this +import { + getJwtMfaLifetime, + getJwtMfaSecret, + getHttpsEnabled, +} from '../../config'; +import { AuthProvider } from '../../models/user'; + +declare module 'jsonwebtoken' { + export interface ProviderAuthJwtPayload extends jwt.JwtPayload { + userId: string; + email: string; + authProvider: AuthProvider; + isUserCompleted: boolean, + } +} + +/** + * Log in user step 1: Return [salt] and [serverPublicKey] as part of step 1 of SRP protocol + * @param req + * @param res + * @returns + */ +export const login1 = async (req: Request, res: Response) => { + try { + const { + email, + providerAuthToken, + clientPublicKey + }: { + email: string; + clientPublicKey: string, + providerAuthToken?: string; + } = req.body; + + const user = await User.findOne({ + email, + }).select('+salt +verifier'); + + if (!user) throw new Error('Failed to find user'); + + if (user.authProvider) { + await validateProviderAuthToken({ + email, + user, + providerAuthToken, + }) + } + + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier + }, + async () => { + // generate server-side public key + const serverPublicKey = server.getPublicKey(); + await LoginSRPDetail.findOneAndReplace({ + email: email + }, { + email, + userId: user.id, + clientPublicKey: clientPublicKey, + serverBInt: bigintConversion.bigintToBuf(server.bInt), + }, { upsert: true, returnNewDocument: false }); + + return res.status(200).send({ + serverPublicKey, + salt: user.salt + }); + } + ); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to start authentication process' + }); + } +}; + +/** + * Log in user step 2: complete step 2 of SRP protocol and return token and their (encrypted) + * private key + * @param req + * @param res + * @returns + */ +export const login2 = async (req: Request, res: Response) => { + try { + + if (!req.headers['user-agent']) throw InternalServerError({ message: 'User-Agent header is required' }); + + const { email, clientProof, providerAuthToken } = req.body; + + const user = await User.findOne({ + email, + }).select('+salt +verifier +encryptionVersion +protectedKey +protectedKeyIV +protectedKeyTag +publicKey +encryptedPrivateKey +iv +tag +devices'); + + if (!user) throw new Error('Failed to find user'); + + if (user.authProvider) { + await validateProviderAuthToken({ + email, + user, + providerAuthToken, + }) + } + + const loginSRPDetail = await LoginSRPDetail.findOneAndDelete({ email: email }) + + if (!loginSRPDetail) { + return BadRequestError(Error("Failed to find login details for SRP")) + } + + const server = new jsrp.server(); + server.init( + { + salt: user.salt, + verifier: user.verifier, + b: loginSRPDetail.serverBInt + }, + async () => { + server.setClientPublicKey(loginSRPDetail.clientPublicKey); + + // compare server and client shared keys + if (server.checkClientProof(clientProof)) { + + if (user.isMfaEnabled) { + // case: user has MFA enabled + + // generate temporary MFA token + const token = createToken({ + payload: { + userId: user._id.toString() + }, + expiresIn: await getJwtMfaLifetime(), + secret: await getJwtMfaSecret() + }); + + const code = await TokenService.createToken({ + type: TOKEN_EMAIL_MFA, + email + }); + + // send MFA code [code] to [email] + await sendMail({ + template: 'emailMfa.handlebars', + subjectLine: 'Infisical MFA code', + recipients: [user.email], + substitutions: { + code + } + }); + + return res.status(200).send({ + mfaEnabled: true, + token + }); + } + + await checkUserDevice({ + user, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); + + // issue tokens + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); + + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); + + // case: user does not have MFA enablgged + // return (access) token in response + + interface ResponseData { + mfaEnabled: boolean; + encryptionVersion: any; + protectedKey?: string; + protectedKeyIV?: string; + protectedKeyTag?: string; + token: string; + publicKey?: string; + encryptedPrivateKey?: string; + iv?: string; + tag?: string; + } + + const response: ResponseData = { + mfaEnabled: false, + encryptionVersion: user.encryptionVersion, + token: tokens.token, + publicKey: user.publicKey, + encryptedPrivateKey: user.encryptedPrivateKey, + iv: user.iv, + tag: user.tag + } + + if ( + user?.protectedKey && + user?.protectedKeyIV && + user?.protectedKeyTag + ) { + response.protectedKey = user.protectedKey; + response.protectedKeyIV = user.protectedKeyIV + response.protectedKeyTag = user.protectedKeyTag; + } + + const loginAction = await EELogService.createAction({ + name: ACTION_LOGIN, + userId: user._id + }); + + loginAction && await EELogService.createLog({ + userId: user._id, + actions: [loginAction], + channel: getChannelFromUserAgent(req.headers['user-agent']), + ipAddress: req.realIP + }); + + return res.status(200).send(response); + } + + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } + ); + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to authenticate. Try again?' + }); + } +}; diff --git a/backend/src/controllers/v3/index.ts b/backend/src/controllers/v3/index.ts new file mode 100644 index 000000000..9d3f118d3 --- /dev/null +++ b/backend/src/controllers/v3/index.ts @@ -0,0 +1,11 @@ +import * as secretsController from './secretsController'; +import * as workspacesController from './workspacesController'; +import * as authController from './authController'; +import * as signupController from './signupController'; + +export { + authController, + secretsController, + signupController, + workspacesController, +} diff --git a/backend/src/controllers/v3/secretsController.ts b/backend/src/controllers/v3/secretsController.ts new file mode 100644 index 000000000..8a9350a36 --- /dev/null +++ b/backend/src/controllers/v3/secretsController.ts @@ -0,0 +1,420 @@ +import { Request, Response } from "express"; +import { Types } from "mongoose"; +import { SecretService, EventService } from "../../services"; +import { eventPushSecrets } from "../../events"; +import { BotService } from "../../services"; +import { repackageSecretToRaw } from "../../helpers/secrets"; +import { encryptSymmetric128BitHexKeyUTF8 } from "../../utils/crypto"; + +/** + * Return secrets for workspace with id [workspaceId] and environment + * [environment] in plaintext + * @param req + * @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; + + const secrets = await SecretService.getSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + secretPath, + authData: req.authData, + }); + + const key = await BotService.getWorkspaceKeyWithBot({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + return res.status(200).send({ + secrets: secrets.map((secret) => { + const rep = repackageSecretToRaw({ + secret, + key + }); + + return rep; + }) + }); +}; + +/** + * Return secret with name [secretName] in plaintext + * @param req + * @param res + */ +export const getSecretByNameRaw = async (req: Request, res: Response) => { + const { secretName } = req.params; + const workspaceId = req.query.workspaceId as string; + const environment = req.query.environment as string; + const secretPath = req.query.secretPath as string; + const type = req.query.type as "shared" | "personal" | undefined; + + const secret = await SecretService.getSecret({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + secretPath, + authData: req.authData, + }); + + const key = await BotService.getWorkspaceKeyWithBot({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + return res.status(200).send({ + secret: repackageSecretToRaw({ + secret, + key + }) + }); +}; + +/** + * Create secret with name [secretName] in plaintext + * @param req + * @param res + */ +export const createSecretRaw = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretValue, + secretComment, + secretPath = "/" + } = req.body; + + const key = await BotService.getWorkspaceKeyWithBot({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + const secretKeyEncrypted = encryptSymmetric128BitHexKeyUTF8({ + plaintext: secretName, + key + }); + + const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8({ + plaintext: secretValue, + key + }); + + const secretCommentEncrypted = encryptSymmetric128BitHexKeyUTF8({ + plaintext: secretComment, + key + }); + + const secret = await SecretService.createSecret({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + authData: req.authData, + secretKeyCiphertext: secretKeyEncrypted.ciphertext, + secretKeyIV: secretKeyEncrypted.iv, + secretKeyTag: secretKeyEncrypted.tag, + secretValueCiphertext: secretValueEncrypted.ciphertext, + secretValueIV: secretValueEncrypted.iv, + secretValueTag: secretValueEncrypted.tag, + secretPath, + secretCommentCiphertext: secretCommentEncrypted.ciphertext, + secretCommentIV: secretCommentEncrypted.iv, + secretCommentTag: secretCommentEncrypted.tag + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + const secretWithoutBlindIndex = secret.toObject(); + delete secretWithoutBlindIndex.secretBlindIndex; + + return res.status(200).send({ + secret: repackageSecretToRaw({ + secret: secretWithoutBlindIndex, + key + }) + }); +} + +/** + * Update secret with name [secretName] + * @param req + * @param res + */ +export const updateSecretByNameRaw = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretValue, + secretPath = "/", + } = req.body; + + const key = await BotService.getWorkspaceKeyWithBot({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + const secretValueEncrypted = encryptSymmetric128BitHexKeyUTF8({ + plaintext: secretValue, + key + }); + + const secret = await SecretService.updateSecret({ + secretName, + workspaceId, + environment, + type, + authData: req.authData, + secretValueCiphertext: secretValueEncrypted.ciphertext, + secretValueIV: secretValueEncrypted.iv, + secretValueTag: secretValueEncrypted.tag, + secretPath, + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + return res.status(200).send({ + secret: repackageSecretToRaw({ + secret, + key + }) + }); +}; + +/** + * Delete secret with name [secretName] + * @param req + * @param res + */ +export const deleteSecretByNameRaw = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretPath = "/" + } = req.body; + + const { secret } = await SecretService.deleteSecret({ + secretName, + workspaceId, + environment, + type, + authData: req.authData, + secretPath, + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + const key = await BotService.getWorkspaceKeyWithBot({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + return res.status(200).send({ + secret: repackageSecretToRaw({ + secret, + key + }) + }); +}; + +/** + * Get secrets for workspace with id [workspaceId] and environment + * [environment] + * @param req + * @param res + */ +export const getSecrets = 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; + + const secrets = await SecretService.getSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + secretPath, + authData: req.authData, + }); + + return res.status(200).send({ + secrets, + }); +}; + +/** + * Return secret with name [secretName] + * @param req + * @param res + */ +export const getSecretByName = async (req: Request, res: Response) => { + const { secretName } = req.params; + const workspaceId = req.query.workspaceId as string; + const environment = req.query.environment as string; + const secretPath = req.query.secretPath as string; + const type = req.query.type as "shared" | "personal" | undefined; + + const secret = await SecretService.getSecret({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + secretPath, + authData: req.authData, + }); + + return res.status(200).send({ + secret, + }); +}; + +/** + * Create secret with name [secretName] + * @param req + * @param res + */ +export const createSecret = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + secretPath = "/", + } = req.body; + + const secret = await SecretService.createSecret({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + authData: req.authData, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretPath, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + const secretWithoutBlindIndex = secret.toObject(); + delete secretWithoutBlindIndex.secretBlindIndex; + + return res.status(200).send({ + secret: secretWithoutBlindIndex, + }); +}; + + +/** + * Update secret with name [secretName] + * @param req + * @param res + */ +export const updateSecretByName = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretPath = "/", + } = req.body; + + const secret = await SecretService.updateSecret({ + secretName, + workspaceId, + environment, + type, + authData: req.authData, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretPath, + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + return res.status(200).send({ + secret, + }); +}; + +/** + * Delete secret with name [secretName] + * @param req + * @param res + */ +export const deleteSecretByName = async (req: Request, res: Response) => { + const { secretName } = req.params; + const { + workspaceId, + environment, + type, + secretPath = "/" + } = req.body; + + const { secret } = await SecretService.deleteSecret({ + secretName, + workspaceId, + environment, + type, + authData: req.authData, + secretPath, + }); + + await EventService.handleEvent({ + event: eventPushSecrets({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }), + }); + + return res.status(200).send({ + secret, + }); +}; diff --git a/backend/src/controllers/v3/signupController.ts b/backend/src/controllers/v3/signupController.ts new file mode 100644 index 000000000..5944e289a --- /dev/null +++ b/backend/src/controllers/v3/signupController.ts @@ -0,0 +1,194 @@ +import jwt from 'jsonwebtoken'; +import { Request, Response } from 'express'; +import * as Sentry from '@sentry/node'; +import { User, MembershipOrg } from '../../models'; +import { completeAccount } from '../../helpers/user'; +import { + initializeDefaultOrg +} from '../../helpers/signup'; +import { issueAuthTokens, validateProviderAuthToken } from '../../helpers/auth'; +import { INVITED, ACCEPTED } from '../../variables'; +import { standardRequest } from '../../config/request'; +import { getLoopsApiKey, getHttpsEnabled, getJwtSignupSecret } from '../../config'; +import { BadRequestError } from '../../utils/errors'; +import { TelemetryService } from '../../services'; + +/** + * Complete setting up user by adding their personal and auth information as part of the + * signup flow + * @param req + * @param res + * @returns + */ +export const completeAccountSignup = async (req: Request, res: Response) => { + let user, token, refreshToken; + try { + const { + email, + firstName, + lastName, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier, + organizationName, + providerAuthToken, + attributionSource, + }: { + email: string; + firstName: string; + lastName: string; + protectedKey: string; + protectedKeyIV: string; + protectedKeyTag: string; + publicKey: string; + encryptedPrivateKey: string; + encryptedPrivateKeyIV: string; + encryptedPrivateKeyTag: string; + salt: string; + verifier: string; + organizationName: string; + providerAuthToken?: string; + attributionSource?: string; + } = req.body; + + user = await User.findOne({ email }); + + if (!user || (user && user?.publicKey)) { + // case 1: user doesn't exist. + // case 2: user has already completed account + return res.status(403).send({ + error: 'Failed to complete account for complete user' + }); + } + + if (providerAuthToken) { + await validateProviderAuthToken({ + email, + providerAuthToken, + user, + }); + } else { + const [AUTH_TOKEN_TYPE, AUTH_TOKEN_VALUE] = <[string, string]>req.headers['authorization']?.split(' ', 2) ?? [null, null] + if (AUTH_TOKEN_TYPE === null) { + throw BadRequestError({ message: `Missing Authorization Header in the request header.` }); + } + if (AUTH_TOKEN_TYPE.toLowerCase() !== 'bearer') { + throw BadRequestError({ message: `The provided authentication type '${AUTH_TOKEN_TYPE}' is not supported.` }) + } + if (AUTH_TOKEN_VALUE === null) { + throw BadRequestError({ + message: 'Missing Authorization Body in the request header', + }) + } + + const decodedToken = ( + jwt.verify(AUTH_TOKEN_VALUE, await getJwtSignupSecret()) + ); + + if (decodedToken.userId !== user.id) { + throw BadRequestError(); + } + } + + // complete setting up user's account + user = await completeAccount({ + userId: user._id.toString(), + firstName, + lastName, + encryptionVersion: 2, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + encryptedPrivateKeyIV, + encryptedPrivateKeyTag, + salt, + verifier + }); + + 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 + }); + + // update organization membership statuses that are + // invited to completed with user attached + await MembershipOrg.updateMany( + { + inviteEmail: email, + status: INVITED + }, + { + user, + status: ACCEPTED + } + ); + + // issue tokens + const tokens = await issueAuthTokens({ + userId: user._id, + ip: req.realIP, + userAgent: req.headers['user-agent'] ?? '' + }); + + token = tokens.token; + + // sending a welcome email to new users + if (await getLoopsApiKey()) { + await standardRequest.post("https://app.loops.so/api/v1/events/send", { + "email": email, + "eventName": "Sign Up", + "firstName": firstName, + "lastName": lastName + }, { + headers: { + "Accept": "application/json", + "Authorization": "Bearer " + (await getLoopsApiKey()) + }, + }); + } + + // store (refresh) token in httpOnly cookie + res.cookie('jid', tokens.refreshToken, { + httpOnly: true, + path: '/', + sameSite: 'strict', + secure: await getHttpsEnabled() + }); + + const postHogClient = await TelemetryService.getPostHogClient(); + if (postHogClient) { + postHogClient.capture({ + event: 'User Signed Up', + distinctId: email, + properties: { + email, + attributionSource + } + }); + } + } catch (err) { + Sentry.setUser(null); + Sentry.captureException(err); + return res.status(400).send({ + message: 'Failed to complete account setup' + }); + } + + return res.status(200).send({ + message: 'Successfully set up account', + user, + token + }); +}; diff --git a/backend/src/controllers/v3/workspacesController.ts b/backend/src/controllers/v3/workspacesController.ts new file mode 100644 index 000000000..aac6682d7 --- /dev/null +++ b/backend/src/controllers/v3/workspacesController.ts @@ -0,0 +1,90 @@ +import { Request, Response } from 'express'; +import { Types } from 'mongoose'; +import { Secret } from '../../models'; +import { SecretService } from'../../services'; + +/** + * Return whether or not all secrets in workspace with id [workspaceId] + * are blind-indexed + * @param req + * @param res + * @returns + */ +export const getWorkspaceBlindIndexStatus = async (req: Request, res: Response) => { + const { workspaceId } = req.params; + + const secretsWithoutBlindIndex = await Secret.countDocuments({ + workspace: new Types.ObjectId(workspaceId), + secretBlindIndex: { + $exists: false + } + }); + + return res.status(200).send(secretsWithoutBlindIndex === 0); +} + +/** + * Get all secrets for workspace with id [workspaceId] + */ +export const getWorkspaceSecrets = async (req: Request, res: Response) => { + const { workspaceId } = req.params; + + const secrets = await Secret.find({ + workspace: new Types.ObjectId (workspaceId) + }); + + return res.status(200).send({ + secrets + }); +} + +/** + * Update blind indices for secrets in workspace with id [workspaceId] + * @param req + * @param res + */ +export const nameWorkspaceSecrets = async (req: Request, res: Response) => { + interface SecretToUpdate { + secretName: string; + _id: string; + } + + const { workspaceId } = req.params; + const { + secretsToUpdate + }: { + secretsToUpdate: SecretToUpdate[]; + } = req.body; + + // get secret blind index salt + const salt = await SecretService.getSecretBlindIndexSalt({ + workspaceId: new Types.ObjectId(workspaceId) + }); + + // update secret blind indices + const operations = await Promise.all( + secretsToUpdate.map(async (secretToUpdate: SecretToUpdate) => { + const secretBlindIndex = await SecretService.generateSecretBlindIndexWithSalt({ + secretName: secretToUpdate.secretName, + salt + }); + + return ({ + updateOne: { + filter: { + _id: new Types.ObjectId(secretToUpdate._id) + }, + update: { + secretBlindIndex + } + } + }); + }) + ); + + await Secret.bulkWrite(operations); + + return res.status(200).send({ + message: 'Successfully named workspace secrets' + }); +} \ No newline at end of file diff --git a/backend/src/data/common_passwords.txt b/backend/src/data/common_passwords.txt new file mode 100644 index 000000000..01a442b17 --- /dev/null +++ b/backend/src/data/common_passwords.txt @@ -0,0 +1,1497 @@ +123456 +123456789 +111111 +password +qwerty +abc123 +12345678 +password1 +1234567 +123123 +1234567890 +000000 +12345 +iloveyou +1q2w3e4r5t +1234 +123456a +qwertyuiop +monkey +123321 +dragon +654321 +666666 +123 +myspace1 +a123456 +121212 +1qaz2wsx +123qwe +123abc +tinkle +target123 +gwerty +1g2w3e4r +gwerty123 +zag12wsx +7777777 +qwerty1 +1q2w3e4r +987654321 +222222 +qwe123 +qwerty123 +zxcvbnm +555555 +112233 +fuckyou +asdfghjkl +12345a +123123123 +1q2w3e +qazwsx +computer +aaaaaa +159753 +iloveyou1 +fuckyou1 +princess +789456123 +11111111 +123654 +princess1 +888888 +linkedin +michael +sunshine +football +11111 +777777 +1234qwer +999999 +j38ifUbn +monkey1 +football1 +daniel +azerty +a12345 +123456789a +789456 +asdfgh +love123 +abcd1234 +jordan23 +88888888 +5201314 +12qwaszx +FQRG7CS493 +ashley +asdf +asd123 +superman +jessica +love +samsung +shadow +blink182 +333333 +michael1 +babygirl1 +jesus1 +qwert +k.: +baseball +charlie +0 +hello1 +soccer +killer +131313 +master +1111111 +gfhjkm +0123456789 +987654 +iloveyou2 +angel1 +jordan +147258369 +bitch1 +michelle +q1w2e3r4 +jessica1 +qwer1234 +159357 +soccer1 +liverpool +101010 +zxcvbn +thomas +asdasd +fuckyou2 +justin +nicole +1111111111 +1 +1111 +qazwsxedc +baseball1 +andrew +hello +apple +0987654321 +anthony1 +102030 +money1 +parola +abc +147258 +anthony +111222 +jennifer +number1 +naruto +123456q +696969 +00000000 +joshua +golfer +29rsavoy +myspace +andrea +basketball +qwerty12 +charlie1 +passw0rd +asshole1 +hunter +marina +welcome +010203 +superman1 +password12 +xbox360 +sunshine1 +ashley1 +lovely +babygirl +! +trustno1 +666 +asdf1234 +chocolate +buster +summer +tigger +purple +freedom +loveme +matthew +50cent +password2 +maggie +george +chelsea +12341234 +amanda +hannah +q1w2e3 +friends +shadow1 +william +abcdefg +samantha +12344321 +nicole1 +q1w2e3r4t5y6 +robert +mother +jordan1 +secret +letmein +qweasdzxc +212121 +pokemon +$HEX +internet +batman +love12 +a123456789 +VQsaBLPzLa +qweqwe +hello123 +232323 +butterfly +martin +flower +forever +mustang +1qazxsw2 +iloveu +cjmasterinf +orange +harley +user +brandon1 +london +1234567891 +pepper +chris1 +lol123 +abcdef +whatever +1342 +alexander +loveyou +290966 +wall.e +junior +12413 +qweasd +PE#5GZ29PTZMSE +tudelft +dpbk1234 +DIOSESFIEL +U38fa39 +147852 +cookie +family +jasmine +dragon1 +12345q +nikita +pakistan +123654789 +123789 +amanda1 +joseph +happy1 +ginger +: +matthew1 +snoopy +justin1 +lastfm +3rJs1la7qE +пїЅпїЅпїЅпїЅпїЅпїЅ +antonio +barcelona +matrix +computer1 +hottie1 +sophie +sandra +michelle1 +12345678910 +qqqqqq +arsenal +444444 +brandon +daniel1 +jonathan +killer1 +liverpool1 +mickey +ghbdtn +purple1 +mercedes +patrick +11223344 +diamond +456789 +victoria +asshole +taylor +qwertyu +andrew1 +red123 +lucky1 +eminem +12345qwert +111222tianya +yellow +william1 +bailey +angel +chicken1 +richard +0000 +banana +0000000000 +jasmine1 +benjamin +welcome1 +starwars +hunter1 +cheese +melissa +angela +christian +1234554321 +oliver +chocolate1 +butterfly1 +peanut +55555 +hockey +mylove +natasha +NULL +mommy1 +1234561 +q1w2e3r4t5 +america +252525 +monster +school +456123 +james1 +slipknot +hannah1 +zaq12wsx +chicken +147852369 +gabriel +elizabeth +cookie1 +Status +87654321 +robert1 +ferrari +nathan +1password +buddy1 +1314520 +america1 +metallica +chelsea1 +zzzzzz +prince +adidas +jackson +morgan +rainbow +silver +1234567a +angels +iw14Fi9j +loveme1 +juventus +jennifer1 +!~!1 +bubbles +samuel +fuckoff +lovers +cheese1 +0123456 +123asd +999999999 +madison +elizabeth1 +music +buster1 +lauren +david1 +tigger1 +123qweasd +taylor1 +carlos +tinkerbell +samantha1 +Sojdlg123aljg +joshua1 +poop +stella +myspace123 +asdasd5 +freedom1 +whatever1 +xxxxxx +00000 +valentina +a1b2c3 +741852963 +austin +monica +qaz123 +lovely1 +music1 +harley1 +family1 +spongebob1 +steven +nirvana +1234abcd +hellokitty +thomas1 +7654321 +madison1 +daddy1 +summer1 +cocacola +nicholas +zxc123 +123456m +qwertyui +spiderman +vanessa +diamond1 +142536 +danielle +badoo +7758521 +bandit +pokemon1 +mustang1 +1qaz2wsx3edc +alexis +loulou +justinbieb +yamaha +qwert1 +scooter +rachel +tennis +ronaldo +i +mexico1 +friends1 +victor +maggie1 +asdfasdf +qwerty12345 +lover1 +jesus +123hfjdk147 +nicolas +batman1 +weed420 +password123 +loser1 +123456j +iloveyou! +pepper1 +fuckoff1 +555666 +iloveu2 +sabrina +pussy1 +bubbles1 +098765 +master1 +smokey +a1b2c3d4 +123456789q +qwaszx +heather +jasper +booboo +heather1 +4815162342 +peanut1 +chester +123456s +123456b +google +edward +yankees1 +canada +Exigent +destiny +success +nigger1 +135790 +asdfghjkl1 +124578 +casper +lalala +mother1 +sexy123 +qazxsw +naruto1 +1q2w3e4r5t6y +david +money +yellow1 +patrick1 +flower1 +12121212 +alexander1 +raiders1 +Password1 +sebastian +134679 +zxcvbnm1 +dennis +852456 +hahaha +daniela +ginger1 +olivia +melissa1 +010101 +slipknot1 +spiderman1 +cowboys1 +0000000 +rebecca +741852 +jeremy +a1234567 +dakota +123456d +1a2b3c +apple1 +november +alexandra +159951 +iloveu1 +veronica +fuckme1 +baby123 +yankees +stupid1 +cristina +newyork1 +jackson1 +playboy +friend +iloveyou12 +sammy1 +pimpin1 +phoenix +PolniyPizdec0211 +rocky1 +password! +joseph1 +753951 +p +a838hfiD +richard1 +beautiful1 +mickey1 +carolina +j123456 +202020 +newyork +patricia +charles +stephanie +orange1 +m123456 +421uiopy258 +myspace2 +cameron +spider +barbie +woaini +vincent +mexico +scorpion +monster1 +aaaaa +elephant +asdf123 +963852741 +zk.: +guitar +fucker1 +destiny1 +hotmail +johnny +doudou +q123456 +bailey1 +asdfgh1 +fucker +louise +sparky +sweety +123456abc +shorty1 +booboo1 +december +9876543210 +manchester +midnight +246810 +jessie +dallas +austin1 +s123456 +pass +12345678a +claudia +пїЅпїЅпїЅпїЅпїЅпїЅпїЅ +kristina +lakers +lovelove +crazy1 +tiger1 +thunder +dolphin +a +gangsta1 +jackie +151515 +charlotte +scooter1 +caroline +fuck +merlin +junior1 +super123 +scooby +marseille +aaaa +metallica1 +kitty1 +chris +beautiful +black1 +danielle1 +blessed1 +skater1 +1029384756 +qazwsx123 +456456 +b123456 +genius +guitar1 +tyler1 +peaches +california +sakura +tigers +soleil +lauren1 +green1 +smokey1 +cooper +520520 +muffin +christian1 +love13 +fucku2 +arsenal1 +lucky7 +diablo +apples +george1 +babyboy1 +crystal +1122334455 +player1 +aa123456 +vfhbyf +forever1 +Password +winston +chivas1 +sexy +hockey1 +1a2b3c4d +pussy +playboy1 +stalker +cherry +tweety +toyota +creative +gemini +pretty1 +пїЅпїЅпїЅпїЅпїЅпїЅпїЅпїЅ +maverick +brittany1 +nathan1 +letmein1 +cameron1 +secret1 +google1 +heaven +martina +murphy +spongebob +uQA9Ebw445 +fernando +pretty +startfinding +softball +dolphin1 +fuckme +test123 +qwerty1234 +kobe24 +alejandro +adrian +september +aaaaaa1 +bubba1 +isabella +abc123456 +password3 +jason1 +abcdefg123 +loveyou1 +shannon +100200 +manuel +leonardo +molly1 +flowers +123456z +007007 +password. +321321 +miguel +samsung1 +sergey +sweet1 +abc1234 +windows +qwert123 +vfrcbv +poohbear +d123456 +school1 +badboy +951753 +123456c +111 +steven1 +snoopy1 +garfield +YAgjecc826 +compaq +candy1 +sarah1 +qwerty123456 +123456l +eminem1 +141414 +789789 +maria +steelers +iloveme1 +morgan1 +winner +boomer +lolita +nastya +alexis1 +carmen +angelo +nicholas1 +portugal +precious +jackass1 +jonathan1 +yfnfif +bitch +tiffany +rabbit +rainbow1 +angel123 +popcorn +barbara +brandy +fuckyou! +starwars1 +barney +natalia +hiphop +tiffany1 +shorty +poohbear1 +simone +albert +marlboro +hardcore +cowboys +sydney +alex +scorpio +1234512345 +q12345 +qq123456 +onelove +bond007 +abcdefg1 +eagles +crystal1 +azertyuiop +winter +sexy12 +angelina +james +svetlana +fatima +123456k +icecream +popcorn1 +121314 +john316 +qazwsx1 +victoria1 +twilight +iloveme +9379992 +pass123 +dancer +brittany +beauty +bonjour +maxwell +coffee +dexter +454545 +qazqaz +snickers +love11 +samson +aaaaaaaa +swordfish +fyfcnfcbz +abcd123 +aaa111 +natalie +hottie +passion +alyssa +rockstar1 +lovers1 +florida +alicia +happy +blue123 +123456t +ranger +yourmom1 +pumpkin +denise +edward1 +tweety1 +christine +august +54321 +bella1 +marie1 +seven7 +steelers1 +aaaaa1 +shannon1 +amber1 +cutie1 +peaches1 +florida1 +bonnie +stephanie1 +lollipop +cassie +k. +rachel1 +greenday1 +krishna +teresa +october +iverson3 +motorola +rockstar +hahaha1 +police +lakers24 +fylhtq +andrey +loveme2 +turtle +southside1 +baby +bismillah +pa55word +blessed +emmanuel +666999 +012345 +fluffy +5555555555 +stupid +karina +fishing +musica +password11 +love4ever +melanie +greenday +isabelle +nothing +abcd +chicago +cowboy +mnbvcxz +andrea1 +242424 +babygurl1 +santiago +ssssss +kevin1 +lakers1 +chester1 +321654 +kimberly +carlos1 +z123456 +daisy1 +jackass +m +5555555 +zoosk +boston +happy123 +55555555 +satan666 +111111a +pamela +090909 +francesco +horses +456852 +qwer +vanessa1 +redsox +pookie +a12345678 +110110 +tucker +marley +corvette +778899 +realmadrid +raiders +rangers +people +1123581321 +soccer12 +sayang +shelby +christ +12345t +fktrcfylh +kitten +player +c123456 +qwert12345 +baby12 +trinity +1v7Upjw3nT +p@ssw0rd +thunder1 +zxcvbnm123 +midnight1 +lebron23 +golden +strawberry +orlando +love1234 +lucky13 +asdfg1 +marine +soccer10123456 +password +12345678 +1234 +pussy +12345 +dragon +qwerty +696969 +mustang +letmein +baseball +master +michael +football +shadow +monkey +abc123 +pass +fuckme +6969 +jordan +harley +ranger +iwantu +jennifer +hunter +fuck +2000 +test +batman +trustno1 +thomas +tigger +robert +access +love +buster +1234567 +soccer +hockey +killer +george +sexy +andrew +charlie +superman +asshole +fuckyou +dallas +jessica +panties +pepper +1111 +austin +william +daniel +golfer +summer +heather +hammer +yankees +joshua +maggie +biteme +enter +ashley +thunder +cowboy +silver +richard +fucker +orange +merlin +michelle +corvette +bigdog +cheese +matthew +121212 +patrick +martin +freedom +ginger +blowjob +nicole +sparky +yellow +camaro +secret +dick +falcon +taylor +111111 +131313 +123123 +bitch +hello +scooter +please +porsche +guitar +chelsea +black +diamond +nascar +jackson +cameron +654321 +computer +amanda +wizard +xxxxxxxx +money +phoenix +mickey +bailey +knight +iceman +tigers +purple +andrea +horny +dakota +aaaaaa +player +sunshine +morgan +starwars +boomer +cowboys +edward +charles +girls +booboo +coffee +xxxxxx +bulldog +ncc1701 +rabbit +peanut +john +johnny +gandalf +spanky +winter +brandy +compaq +carlos +tennis +james +mike +brandon +fender +anthony +blowme +ferrari +cookie +chicken +maverick +chicago +joseph +diablo +sexsex +hardcore +666666 +willie +welcome +chris +panther +yamaha +justin +banana +driver +marine +angels +fishing +david +maddog +hooters +wilson +butthead +dennis +fucking +captain +bigdick +chester +smokey +xavier +steven +viking +snoopy +blue +eagles +winner +samantha +house +miller +flower +jack +firebird +butter +united +turtle +steelers +tiffany +zxcvbn +tomcat +golf +bond007 +bear +tiger +doctor +gateway +gators +angel +junior +thx1138 +porno +badboy +debbie +spider +melissa +booger +1212 +flyers +fish +porn +matrix +teens +scooby +jason +walter +cumshot +boston +braves +yankee +lover +barney +victor +tucker +princess +mercedes +5150 +doggie +zzzzzz +gunner +horney +bubba +2112 +fred +johnson +xxxxx +tits +member +boobs +donald +bigdaddy +bronco +penis +voyager +rangers +birdie +trouble +white +topgun +bigtits +bitches +green +super +qazwsx +magic +lakers +rachel +slayer +scott +2222 +asdf +video +london +7777 +marlboro +srinivas +internet +action +carter +jasper +monster +teresa +jeremy +11111111 +bill +crystal +peter +pussies +cock +beer +rocket +theman +oliver +prince +beach +amateur +7777777 +muffin +redsox +star +testing +shannon +murphy +frank +hannah +dave +eagle1 +11111 +mother +nathan +raiders +steve +forever +angela +viper +ou812 +jake +lovers +suckit +gregory +buddy +whatever +young +nicholas +lucky +helpme +jackie +monica +midnight +college +baby +cunt +brian +mark +startrek +sierra +leather +232323 +4444 +beavis +bigcock +happy +sophie +ladies +naughty +giants +booty +blonde +fucked +golden +0 +fire +sandra +pookie +packers +einstein +dolphins +chevy +winston +warrior +sammy +slut +8675309 +zxcvbnm +nipples +power +victoria +asdfgh +vagina +toyota +travis +hotdog +paris +rock +xxxx +extreme +redskins +erotic +dirty +ford +freddy +arsenal +access14 +wolf +nipple +iloveyou +alex +florida +eric +legend +movie +success +rosebud +jaguar +great +cool +cooper +1313 +scorpio +mountain +madison +987654 +brazil +lauren +japan +naked +squirt +stars +apple +alexis +aaaa +bonnie +peaches +jasmine +kevin +matt +qwertyui +danielle +beaver +4321 +4128 +runner +swimming +dolphin +gordon +casper +stupid +shit +saturn +gemini +apples +august +3333 +canada +blazer +cumming +hunting +kitty +rainbow +112233 +arthur +cream +calvin +shaved +surfer +samson +kelly +paul +mine +king +racing +5555 +eagle +hentai +newyork +little +redwings +smith +sticky +cocacola +animal +broncos +private +skippy +marvin +blondes +enjoy +girl +apollo +parker +qwert +time +sydney +women +voodoo +magnum +juice +abgrtyu +777777 +dreams +maxwell +music +rush2112 +russia +scorpion +rebecca +tester +mistress +phantom +billy +6666 +albert \ No newline at end of file diff --git a/backend/src/data/disposable_emails.txt b/backend/src/data/disposable_emails.txt new file mode 100644 index 000000000..70e24a460 --- /dev/null +++ b/backend/src/data/disposable_emails.txt @@ -0,0 +1,3519 @@ +0-mail.com +027168.com +0815.ru +0815.ry +0815.su +0845.ru +0box.eu +0clickemail.com +0n0ff.net +0nelce.com +0v.ro +0w.ro +0wnd.net +0wnd.org +0x207.info +1-8.biz +1-tm.com +10-minute-mail.com +1000rebates.stream +100likers.com +105kg.ru +10dk.email +10mail.com +10mail.org +10minut.com.pl +10minut.xyz +10minutemail.be +10minutemail.cf +10minutemail.co.uk +10minutemail.co.za +10minutemail.com +10minutemail.de +10minutemail.ga +10minutemail.gq +10minutemail.ml +10minutemail.net +10minutemail.nl +10minutemail.pro +10minutemail.us +10minutemailbox.com +10minutemails.in +10minutenemail.de +10minutesmail.com +10minutesmail.fr +10minutmail.pl +10x9.com +11163.com +123-m.com +12hosting.net +12houremail.com +12minutemail.com +12minutemail.net +12storage.com +140unichars.com +147.cl +14n.co.uk +15qm.com +1blackmoon.com +1ce.us +1chuan.com +1clck2.com +1fsdfdsfsdf.tk +1mail.ml +1pad.de +1s.fr +1secmail.com +1secmail.net +1secmail.org +1st-forms.com +1to1mail.org +1usemail.com +1webmail.info +1zhuan.com +2012-2016.ru +20email.eu +20email.it +20mail.eu +20mail.in +20mail.it +20minutemail.com +20minutemail.it +20mm.eu +2120001.net +21cn.com +247web.net +24hinbox.com +24hourmail.com +24hourmail.net +2anom.com +2chmail.net +2ether.net +2fdgdfgdfgdf.tk +2odem.com +2prong.com +2wc.info +300book.info +30mail.ir +30minutemail.com +30wave.com +3202.com +36ru.com +3d-painting.com +3l6.com +3mail.ga +3trtretgfrfe.tk +4-n.us +4057.com +418.dk +42o.org +4gfdsgfdgfd.tk +4k5.net +4mail.cf +4mail.ga +4nextmail.com +4nmv.ru +4tb.host +4warding.com +4warding.net +4warding.org +50set.ru +55hosting.net +5ghgfhfghfgh.tk +5gramos.com +5july.org +5mail.cf +5mail.ga +5minutemail.net +5oz.ru +5tb.in +5x25.com +5ymail.com +60minutemail.com +672643.net +675hosting.com +675hosting.net +675hosting.org +6hjgjhgkilkj.tk +6ip.us +6mail.cf +6mail.ga +6mail.ml +6paq.com +6somok.ru +6url.com +75hosting.com +75hosting.net +75hosting.org +7days-printing.com +7mail.ga +7mail.ml +7tags.com +80665.com +8127ep.com +8mail.cf +8mail.ga +8mail.ml +99.com +99cows.com +99experts.com +9mail.cf +9me.site +9mot.ru +9ox.net +9q.ro +a-bc.net +a45.in +a7996.com +aa5zy64.com +abacuswe.us +abakiss.com +abcmail.email +abilitywe.us +abovewe.us +absolutewe.us +abundantwe.us +abusemail.de +abuser.eu +abyssmail.com +ac20mail.in +academiccommunity.com +academywe.us +acceleratewe.us +accentwe.us +acceptwe.us +acclaimwe.us +accordwe.us +accreditedwe.us +acentri.com +achievementwe.us +achievewe.us +acornwe.us +acrossgracealley.com +acrylicwe.us +activatewe.us +activitywe.us +acucre.com +acuitywe.us +acumenwe.us +adaptivewe.us +adaptwe.us +add3000.pp.ua +addictingtrailers.com +adeptwe.us +adfskj.com +adios.email +adiq.eu +aditus.info +admiralwe.us +ado888.biz +adobeccepdm.com +adoniswe.us +adpugh.org +adroh.com +adsd.org +adubiz.info +advantagewe.us +advantimo.com +adventurewe.us +adventwe.us +advisorwe.us +advocatewe.us +adwaterandstir.com +aegde.com +aegia.net +aegiscorp.net +aegiswe.us +aelo.es +aeonpsi.com +afarek.com +affiliate-nebenjob.info +affiliatedwe.us +affilikingz.de +affinitywe.us +affluentwe.us +affordablewe.us +afia.pro +afrobacon.com +afterhourswe.us +agedmail.com +agendawe.us +agger.ro +agilewe.us +agorawe.us +agtx.net +aheadwe.us +ahem.email +ahk.jp +ahmedkhlef.com +air2token.com +airmailbox.website +airsi.de +ajaxapp.net +akapost.com +akerd.com +akgq701.com +akmail.in +al-qaeda.us +albionwe.us +alchemywe.us +alfaceti.com +aliaswe.us +alienware13.com +aligamel.com +alisongamel.com +alivance.com +alivewe.us +all-cats.ru +allaccesswe.us +allamericanwe.us +allaroundwe.us +alldirectbuy.com +allegiancewe.us +allegrowe.us +allemojikeyboard.com +allgoodwe.us +alliancewe.us +allinonewe.us +allofthem.net +alloutwe.us +allowed.org +alloywe.us +allprowe.us +allseasonswe.us +allstarwe.us +allthegoodnamesaretaken.org +allurewe.us +almondwe.us +alph.wtf +alpha-web.net +alphaomegawe.us +alpinewe.us +altairwe.us +altitudewe.us +altuswe.us +ama-trade.de +ama-trans.de +amadeuswe.us +amail.club +amail.com +amail1.com +amail4.me +amazon-aws.org +amberwe.us +ambiancewe.us +ambitiouswe.us +amelabs.com +americanawe.us +americasbestwe.us +americaswe.us +amicuswe.us +amilegit.com +amiri.net +amiriindustries.com +amplewe.us +amplifiedwe.us +amplifywe.us +ampsylike.com +analogwe.us +analysiswe.us +analyticalwe.us +analyticswe.us +analyticwe.us +anappfor.com +anappthat.com +andreihusanu.ro +andthen.us +animesos.com +anit.ro +ano-mail.net +anon-mail.de +anonbox.net +anonmail.top +anonmails.de +anonymail.dk +anonymbox.com +anonymized.org +anonymousness.com +anotherdomaincyka.tk +ansibleemail.com +anthony-junkmail.com +antireg.com +antireg.ru +antispam.de +antispam24.de +antispammail.de +anyalias.com +aoeuhtns.com +apfelkorps.de +aphlog.com +apkmd.com +appc.se +appinventor.nl +appixie.com +apps.dj +appzily.com +arduino.hk +ariaz.jetzt +armyspy.com +aron.us +arroisijewellery.com +art-en-ligne.pro +artman-conception.com +arur01.tk +arurgitu.gq +arvato-community.de +aschenbrandt.net +asdasd.nl +asdasd.ru +ashleyandrew.com +ask-mail.com +asorent.com +ass.pp.ua +astonut.tk +astroempires.info +asu.mx +asu.su +at.hm +at0mik.org +atnextmail.com +attnetwork.com +augmentationtechnology.com +ausgefallen.info +auti.st +autorobotica.com +autosouvenir39.ru +autotwollow.com +autowb.com +aver.com +averdov.com +avia-tonic.fr +avls.pt +awatum.de +awdrt.org +awiki.org +awsoo.com +axiz.org +axon7zte.com +axsup.net +ayakamail.cf +azazazatashkent.tk +azcomputerworks.com +azmeil.tk +b1of96u.com +b2bx.net +b2cmail.de +badgerland.eu +badoop.com +badpotato.tk +balaket.com +banit.club +banit.me +bank-opros1.ru +bareed.ws +barryogorman.com +bartdevos.be +basscode.org +bauwerke-online.com +bazaaboom.com +bbbbyyzz.info +bbhost.us +bbitf.com +bbitj.com +bbitq.com +bcaoo.com +bcast.ws +bcb.ro +bccto.me +bdmuzic.pw +beaconmessenger.com +bearsarefuzzy.com +beddly.com +beefmilk.com +belamail.org +belljonestax.com +beluckygame.com +benipaula.org +bepureme.com +beribase.ru +beribaza.ru +berirabotay.ru +best-john-boats.com +bestchoiceusedcar.com +bestlistbase.com +bestoption25.club +bestparadize.com +bestsoundeffects.com +besttempmail.com +betr.co +bgtmail.com +bgx.ro +bheps.com +bidourlnks.com +big1.us +bigprofessor.so +bigstring.com +bigwhoop.co.za +bij.pl +binka.me +binkmail.com +binnary.com +bio-muesli.info +bio-muesli.net +bione.co +bitwhites.top +bitymails.us +blackgoldagency.ru +blackmarket.to +bladesmail.net +blip.ch +blnkt.net +block521.com +blogmyway.org +blogos.net +blogspam.ro +blondemorkin.com +bluedumpling.info +bluewerks.com +bnote.com +boatmail.us +bobmail.info +bobmurchison.com +bofthew.com +bonobo.email +boofx.com +bookthemmore.com +bootybay.de +borged.com +borged.net +borged.org +bot.nu +boun.cr +bouncr.com +boxformail.in +boximail.com +boxmail.lol +boxomail.live +boxtemp.com.br +bptfp.net +brand-app.biz +brandallday.net +brasx.org +breakthru.com +brefmail.com +brennendesreich.de +briggsmarcus.com +broadbandninja.com +bsnow.net +bspamfree.org +bspooky.com +bst-72.com +btb-notes.com +btc.email +btcmail.pw +btcmod.com +btizet.pl +buccalmassage.ru +budaya-tionghoa.com +budayationghoa.com +buffemail.com +bugfoo.com +bugmenever.com +bugmenot.com +bukhariansiddur.com +bulrushpress.com +bum.net +bumpymail.com +bunchofidiots.com +bund.us +bundes-li.ga +bunsenhoneydew.com +burnthespam.info +burstmail.info +businessbackend.com +businesssuccessislifesuccess.com +buspad.org +bussitussi.com +buymoreplays.com +buyordie.info +buyusdomain.com +buyusedlibrarybooks.org +buzzcluby.com +byebyemail.com +byespm.com +byom.de +c51vsgq.com +cachedot.net +californiafitnessdeals.com +cam4you.cc +camping-grill.info +candymail.de +cane.pw +capitalistdilemma.com +car101.pro +carbtc.net +cars2.club +carsencyclopedia.com +cartelera.org +caseedu.tk +cashflow35.com +casualdx.com +cavi.mx +cbair.com +cbes.net +cc.liamria +ccmail.uk +cdfaq.com +cdpa.cc +ceed.se +cek.pm +cellurl.com +centermail.com +centermail.net +cetpass.com +cfo2go.ro +chacuo.net +chaichuang.com +chalupaurybnicku.cz +chammy.info +chasefreedomactivate.com +chatich.com +cheaphub.net +cheatmail.de +chenbot.email +chibakenma.ml +chickenkiller.com +chielo.com +childsavetrust.org +chilkat.com +chinamkm.com +chithinh.com +chitthi.in +choco.la +chogmail.com +choicemail1.com +chong-mail.com +chong-mail.net +chong-mail.org +chumpstakingdumps.com +cigar-auctions.com +civikli.com +civx.org +ckaazaza.tk +ckiso.com +cl-cl.org +cl0ne.net +claimab.com +clandest.in +classesmail.com +clearwatermail.info +click-email.com +clickdeal.co +clipmail.eu +clixser.com +clonemoi.tk +cloud-mail.top +cloudns.cx +clout.wiki +clrmail.com +cmail.club +cmail.com +cmail.net +cmail.org +cnamed.com +cndps.com +cnew.ir +cnmsg.net +cnsds.de +co.cc +cobarekyo1.ml +cocoro.uk +cocovpn.com +codeandscotch.com +codivide.com +coffeetimer24.com +coieo.com +coin-host.net +coinlink.club +coldemail.info +compareshippingrates.org +completegolfswing.com +comwest.de +conf.work +consumerriot.com +contbay.com +cooh-2.site +coolandwacky.us +coolimpool.org +coreclip.com +cosmorph.com +courrieltemporaire.com +coza.ro +crankhole.com +crapmail.org +crastination.de +crazespaces.pw +crazymailing.com +cream.pink +crepeau12.com +cringemonster.com +cross-law.ga +cross-law.gq +crossmailjet.com +crossroadsmail.com +crunchcompass.com +crusthost.com +cs.email +csh.ro +cszbl.com +ctmailing.us +ctos.ch +cu.cc +cubiclink.com +cuendita.com +cuirushi.org +cuoly.com +cupbest.com +curlhph.tk +curryworld.de +cust.in +cutout.club +cutradition.com +cuvox.de +cyber-innovation.club +cyber-phone.eu +cylab.org +d1yun.com +d3p.dk +daabox.com +dab.ro +dacoolest.com +daemsteam.com +daibond.info +daily-email.com +daintly.com +damai.webcam +dammexe.net +damnthespam.com +dandikmail.com +darkharvestfilms.com +daryxfox.net +dasdasdascyka.tk +dash-pads.com +dataarca.com +datarca.com +datazo.ca +datenschutz.ru +datum2.com +davidkoh.net +davidlcreative.com +dawin.com +daymail.life +daymailonline.com +dayrep.com +dbunker.com +dcctb.com +dcemail.com +ddcrew.com +de-a.org +dea-21olympic.com +deadaddress.com +deadchildren.org +deadfake.cf +deadfake.ga +deadfake.ml +deadfake.tk +deadspam.com +deagot.com +dealja.com +dealrek.com +deekayen.us +defomail.com +degradedfun.net +deinbox.com +delayload.com +delayload.net +delikkt.de +delivrmail.com +demen.ml +dengekibunko.ga +dengekibunko.gq +dengekibunko.ml +der-kombi.de +derkombi.de +derluxuswagen.de +desoz.com +despam.it +despammed.com +dev-null.cf +dev-null.ga +dev-null.gq +dev-null.ml +developermail.com +devnullmail.com +deyom.com +dharmatel.net +dhm.ro +dhy.cc +dialogus.com +diapaulpainting.com +dicopto.com +digdig.org +digital-message.com +digitalesbusiness.info +digitalmail.info +digitalmariachis.com +digitalsanctuary.com +dildosfromspace.com +dim-coin.com +dingbone.com +diolang.com +directmail24.net +disaq.com +disbox.net +disbox.org +discard.cf +discard.email +discard.ga +discard.gq +discard.ml +discard.tk +discardmail.com +discardmail.de +discos4.com +disign-concept.eu +disign-revelation.com +dispo.in +dispomail.eu +disposable-e.ml +disposable-email.ml +disposable.cf +disposable.ga +disposable.ml +disposable.site +disposableaddress.com +disposableemailaddresses.com +disposableinbox.com +disposablemails.com +dispose.it +disposeamail.com +disposemail.com +disposemymail.com +dispostable.com +divad.ga +divermail.com +divismail.ru +diwaq.com +dlemail.ru +dmarc.ro +dndent.com +dnses.ro +doanart.com +dob.jp +dodgeit.com +dodgemail.de +dodgit.com +dodgit.org +dodsi.com +doiea.com +dolphinnet.net +domforfb1.tk +domforfb18.tk +domforfb19.tk +domforfb2.tk +domforfb23.tk +domforfb27.tk +domforfb29.tk +domforfb3.tk +domforfb4.tk +domforfb5.tk +domforfb6.tk +domforfb7.tk +domforfb8.tk +domforfb9.tk +domozmail.com +donemail.ru +dongqing365.com +dontreg.com +dontsendmespam.de +doojazz.com +doquier.tk +dotman.de +dotmsg.com +dotslashrage.com +doublemail.de +douchelounge.com +dozvon-spb.ru +dp76.com +dr69.site +drdrb.com +drdrb.net +dred.ru +drevo.si +drivetagdev.com +drmail.in +droolingfanboy.de +dropcake.de +dropjar.com +droplar.com +dropmail.me +dropsin.net +dsgvo.ru +dsiay.com +dspwebservices.com +duam.net +duck2.club +dudmail.com +duk33.com +dukedish.com +dump-email.info +dumpandjunk.com +dumpmail.de +dumpyemail.com +durandinterstellar.com +duskmail.com +dwse.edu.pl +dyceroprojects.com +dz17.net +e-mail.com +e-mail.org +e-marketstore.ru +e-tomarigi.com +e3z.de +e4ward.com +eanok.com +easy-trash-mail.com +easynetwork.info +easytrashmail.com +eatmea2z.club +eay.jp +ebbob.com +ebeschlussbuch.de +ecallheandi.com +ecolo-online.fr +edgex.ru +edinburgh-airporthotels.com +edv.to +ee1.pl +ee2.pl +eeedv.de +eelmail.com +efxs.ca +egzones.com +einmalmail.de +einrot.com +einrot.de +eintagsmail.de +elearningjournal.org +electro.mn +elitevipatlantamodels.com +elki-mkzn.ru +email-fake.cf +email-fake.com +email-fake.ga +email-fake.gq +email-fake.ml +email-fake.tk +email-jetable.fr +email-lab.com +email-temp.com +email.edu.pl +email.net +email1.pro +email60.com +emailage.cf +emailage.ga +emailage.gq +emailage.ml +emailage.tk +emailate.com +emailcu.icu +emaildienst.de +emaildrop.io +emailfake.com +emailfake.ml +emailfreedom.ml +emailgenerator.de +emailgo.de +emailias.com +emailigo.de +emailinfive.com +emailisvalid.com +emaillime.com +emailmiser.com +emailna.co +emailnax.com +emailo.pro +emailondeck.com +emailportal.info +emailproxsy.com +emailresort.com +emails.ga +emailsecurer.com +emailsensei.com +emailsingularity.net +emailspam.cf +emailspam.ga +emailspam.gq +emailspam.ml +emailspam.tk +emailsy.info +emailtech.info +emailtemporanea.com +emailtemporanea.net +emailtemporar.ro +emailtemporario.com.br +emailthe.net +emailtmp.com +emailto.de +emailure.net +emailwarden.com +emailxfer.com +emailz.cf +emailz.ga +emailz.gq +emailz.ml +emeil.in +emeil.ir +emeraldwebmail.com +emil.com +emkei.cf +emkei.ga +emkei.gq +emkei.ml +emkei.tk +eml.pp.ua +emlhub.com +emlpro.com +emltmp.com +empireanime.ga +emstjzh.com +emz.net +enayu.com +enterto.com +envy17.com +eoffice.top +eoopy.com +epb.ro +ephemail.net +ephemeral.email +eposta.buzz +eposta.work +eqiluxspam.ga +ereplyzy.com +ericjohnson.ml +ero-tube.org +esadverse.com +esbano-ru.ru +esc.la +escapehatchapp.com +esemay.com +esgeneri.com +esiix.com +esprity.com +estate-invest.fr +eth2btc.info +ether123.net +ethereum1.top +ethersports.org +ethersportz.info +etotvibor.ru +etranquil.com +etranquil.net +etranquil.org +euaqa.com +evanfox.info +eveav.com +evilcomputer.com +evopo.com +evyush.com +exdonuts.com +existiert.net +exitstageleft.net +explodemail.com +express.net.ua +extracurricularsociety.com +extremail.ru +eyepaste.com +ez.lv +ezehe.com +ezfill.com +ezstest.com +f4k.es +f5.si +facebook-email.cf +facebook-email.ga +facebook-email.ml +facebookmail.gq +facebookmail.ml +fackme.gq +fadingemail.com +faecesmail.me +fag.wf +failbone.com +faithkills.com +fake-box.com +fake-email.pp.ua +fake-mail.cf +fake-mail.ga +fake-mail.ml +fakedemail.com +fakeinbox.cf +fakeinbox.com +fakeinbox.ga +fakeinbox.info +fakeinbox.ml +fakeinbox.tk +fakeinformation.com +fakemail.fr +fakemail.io +fakemailgenerator.com +fakemailz.com +fallinhay.com +fammix.com +fanclub.pm +fangoh.com +fansworldwide.de +fantasymail.de +farrse.co.uk +fast-email.info +fast-mail.fr +fastacura.com +fastchevy.com +fastchrysler.com +fasternet.biz +fastkawasaki.com +fastmazda.com +fastmitsubishi.com +fastnissan.com +fastsubaru.com +fastsuzuki.com +fasttoyota.com +fastyamaha.com +fatflap.com +fbma.tk +fddns.ml +fdfdsfds.com +femailtor.com +fer-gabon.org +fermaxxi.ru +fettometern.com +fexbox.org +fexbox.ru +fexpost.com +fextemp.com +ficken.de +fictionsite.com +fightallspam.com +figjs.com +figshot.com +figurescoin.com +fiifke.de +filbert4u.com +filberts4u.com +film-blog.biz +filzmail.com +findemail.info +findu.pl +finews.biz +fir.hk +firemailbox.club +fitnesrezink.ru +fivemail.de +fixmail.tk +fizmail.com +fleckens.hu +flemail.ru +flowu.com +flu.cc +fluidsoft.us +flurred.com +fly-ts.de +flyinggeek.net +flyspam.com +foobarbot.net +footard.com +foreastate.com +forecastertests.com +foreskin.cf +foreskin.ga +foreskin.gq +foreskin.ml +foreskin.tk +forgetmail.com +fornow.eu +forspam.net +forward.cat +fosil.pro +foxja.com +foxtrotter.info +fr.cr +fr.nf +fr33mail.info +fragolina2.tk +frapmail.com +frappina.tk +free-email.cf +free-email.ga +free-temp.net +freebabysittercam.com +freeblackbootytube.com +freecat.net +freedom4you.info +freedompop.us +freefattymovies.com +freehotmail.net +freeinbox.email +freelance-france.eu +freeletter.me +freemail.ms +freemails.cf +freemails.ga +freemails.ml +freemeil.ga +freemeil.gq +freemeil.ml +freeml.net +freeplumpervideos.com +freerubli.ru +freeschoolgirlvids.com +freesistercam.com +freeteenbums.com +freundin.ru +friendlymail.co.uk +front14.org +frwdmail.com +ftp.sh +ftpinc.ca +fuckedupload.com +fuckingduh.com +fuckme69.club +fucknloveme.top +fuckxxme.top +fudgerub.com +fuirio.com +fukaru.com +fukurou.ch +fullangle.org +fulvie.com +fun64.com +funnycodesnippets.com +funnymail.de +furzauflunge.de +futuramind.com +fuwamofu.com +fuwari.be +fux0ringduh.com +fxnxs.com +fyii.de +g14l71lb.com +g1xmail.top +g2xmail.top +g3xmail.top +g4hdrop.us +gafy.net +gage.ga +galaxy.tv +gally.jp +gamail.top +gamegregious.com +gamgling.com +garasikita.pw +garbagecollector.org +garbagemail.org +gardenscape.ca +garizo.com +garliclife.com +garrymccooey.com +gav0.com +gawab.com +gbcmail.win +gbmail.top +gcmail.top +gdmail.top +gedmail.win +geekforex.com +geew.ru +gehensiemirnichtaufdensack.de +geldwaschmaschine.de +gelitik.in +genderfuck.net +geronra.com +geschent.biz +get-mail.cf +get-mail.ga +get-mail.ml +get-mail.tk +get.pp.ua +get1mail.com +get2mail.fr +getairmail.cf +getairmail.com +getairmail.ga +getairmail.gq +getairmail.ml +getairmail.tk +geteit.com +getfun.men +getmails.eu +getnada.com +getnowtoday.cf +getonemail.com +getonemail.net +getover.de +getsimpleemail.com +gett.icu +gexik.com +ggmal.ml +ghosttexter.de +giacmosuaviet.info +giaiphapmuasam.com +giantmail.de +gifto12.com +ginzi.be +ginzi.co.uk +ginzi.es +ginzi.net +ginzy.co.uk +ginzy.eu +girlmail.win +girlsindetention.com +girlsundertheinfluence.com +gishpuppy.com +giveh2o.info +givememail.club +givmail.com +glitch.sx +globaltouron.com +glubex.com +glucosegrin.com +gmal.com +gmatch.org +gmial.com +gmx1mail.top +gmxmail.top +gmxmail.win +gnctr-calgary.com +go2usa.info +go2vpn.net +goemailgo.com +golemico.com +gomail.in +goonby.com +goplaygame.ru +gorillaswithdirtyarmpits.com +goround.info +gosuslugi-spravka.ru +gothere.biz +gotmail.com +gotmail.net +gotmail.org +gowikibooks.com +gowikicampus.com +gowikicars.com +gowikifilms.com +gowikigames.com +gowikimusic.com +gowikinetwork.com +gowikitravel.com +gowikitv.com +grandmamail.com +grandmasmail.com +great-host.in +greencafe24.com +greendike.com +greenhousemail.com +greensloth.com +greggamel.com +greggamel.net +gregorsky.zone +gregorygamel.com +gregorygamel.net +grish.de +griuc.schule +grn.cc +groupbuff.com +grr.la +grugrug.ru +gruz-m.ru +gs-arc.org +gsredcross.org +gsrv.co.uk +gsxstring.ga +gudanglowongan.com +guerillamail.biz +guerillamail.com +guerillamail.de +guerillamail.info +guerillamail.net +guerillamail.org +guerillamailblock.com +guerrillamail.biz +guerrillamail.com +guerrillamail.de +guerrillamail.info +guerrillamail.net +guerrillamail.org +guerrillamailblock.com +gufum.com +gustr.com +gxemail.men +gynzi.co.uk +gynzi.es +gynzy.at +gynzy.es +gynzy.eu +gynzy.gr +gynzy.info +gynzy.lt +gynzy.mobi +gynzy.pl +gynzy.ro +gynzy.sk +gzb.ro +h8s.org +habitue.net +hacccc.com +hackersquad.tk +hackthatbit.ch +hahawrong.com +haida-edu.cn +hairs24.ru +haltospam.com +hamham.uk +hangxomcuatoilatotoro.ml +happydomik.ru +harakirimail.com +haribu.com +hartbot.de +hasanmail.ml +hat-geld.de +hatespam.org +hawrong.com +haydoo.com +hazelnut4u.com +hazelnuts4u.com +hazmatshipping.org +hccmail.win +headstrong.de +heathenhammer.com +heathenhero.com +hecat.es +heisei.be +hellodream.mobi +helloricky.com +helpinghandtaxcenter.org +helpjobs.ru +heros3.com +herp.in +herpderp.nl +hezll.com +hi5.si +hiddentragedy.com +hidebox.org +hidebusiness.xyz +hidemail.de +hidemail.pro +hidemail.us +hidzz.com +highbros.org +hiltonvr.com +himail.online +hmail.us +hmamail.com +hmh.ro +hoanggiaanh.com +hoanglong.tech +hochsitze.com +hola.org +holl.ga +honeys.be +honor-8.com +hopemail.biz +hornyalwary.top +host1s.com +hostcalls.com +hostguru.top +hostingmail.me +hostlaba.com +hot-mail.cf +hot-mail.ga +hot-mail.gq +hot-mail.ml +hot-mail.tk +hotmai.com +hotmailproduct.com +hotmial.com +hotpop.com +hotprice.co +hotsoup.be +housat.com +hpc.tw +hs.vc +ht.cx +huangniu8.com +hukkmu.tk +hulapla.de +humaility.com +hungpackage.com +hushmail.cf +huskion.net +hvastudiesucces.nl +hwsye.net +i2pmail.org +i6.cloudns.cc +iaoss.com +ibnuh.bz +icantbelieveineedtoexplainthisshit.com +icemail.club +ichigo.me +icx.in +icx.ro +idx4.com +idxue.com +ieatspam.eu +ieatspam.info +ieh-mail.de +iencm.com +iffymedia.com +ige.es +igg.biz +ignoremail.com +ihateyoualot.info +ihazspam.ca +iheartspam.org +ikbenspamvrij.nl +illistnoise.com +ilovespam.com +imail1.net +imails.info +imailt.com +imgof.com +imgv.de +immo-gerance.info +imstations.com +imul.info +in-ulm.de +in2reach.com +inactivemachine.com +inbax.tk +inbound.plus +inbox.si +inbox2.info +inboxalias.com +inboxbear.com +inboxclean.com +inboxclean.org +inboxdesign.me +inboxed.im +inboxed.pw +inboxkitten.com +inboxproxy.com +inboxstore.me +inclusiveprogress.com +incognitomail.com +incognitomail.net +incognitomail.org +incq.com +ind.st +indieclad.com +indirect.ws +indomaed.pw +indomina.cf +indoserver.stream +indosukses.press +ineec.net +infocom.zp.ua +inggo.org +inkomail.com +inmynetwork.tk +inoutmail.de +inoutmail.eu +inoutmail.info +inoutmail.net +inpwa.com +insanumingeniumhomebrew.com +insorg-mail.info +instaddr.ch +instance-email.com +instant-mail.de +instantblingmail.info +instantemailaddress.com +instantmail.fr +internet-v-stavropole.ru +internetoftags.com +interstats.org +intersteller.com +intopwa.com +intopwa.net +intopwa.org +investore.co +iozak.com +ip4.pp.ua +ip6.li +ip6.pp.ua +ipoo.org +ippandansei.tk +ipsur.org +irabops.com +irc.so +irish2me.com +irishspringrealty.com +iroid.com +ironiebehindert.de +irssi.tv +is.af +isdaq.com +ishop2k.com +isosq.com +istii.ro +isukrainestillacountry.com +it7.ovh +italy-mail.com +itcompu.com +itfast.net +itunesgiftcodegenerator.com +iubridge.com +iuemail.men +iwi.net +ixaks.com +ixx.io +j-p.us +jafps.com +jajxz.com +janproz.com +jaqis.com +jdmadventures.com +jdz.ro +je-recycle.info +jellow.ml +jellyrolls.com +jeoce.com +jet-renovation.fr +jetable.com +jetable.net +jetable.org +jetable.pp.ua +jiooq.com +jmail.ovh +jmail.ro +jnxjn.com +jobbikszimpatizans.hu +jobbrett.com +jobposts.net +jobs-to-be-done.net +joelpet.com +joetestalot.com +jopho.com +joseihorumon.info +josse.ltd +jourrapide.com +jpco.org +jsrsolutions.com +jumonji.tk +jungkamushukum.com +junk.to +junk1e.com +junkmail.ga +junkmail.gq +just-email.com +justemail.ml +juyouxi.com +jwork.ru +kademen.com +kadokawa.cf +kadokawa.ga +kadokawa.gq +kadokawa.ml +kadokawa.tk +kaengu.ru +kagi.be +kakadua.net +kalapi.org +kamen-market.ru +kamsg.com +kaovo.com +kappala.info +kara-turk.net +karatraman.ml +kariplan.com +karta-kykyruza.ru +kartvelo.com +kasmail.com +kaspop.com +katztube.com +kazelink.ml +kbox.li +kcrw.de +keepmymail.com +keinhirn.de +keipino.de +kekita.com +kellychibale-researchgroup-uct.com +kemptvillebaseball.com +kennedy808.com +kiani.com +killmail.com +killmail.net +kimsdisk.com +kingsq.ga +kino-100.ru +kiois.com +kismail.ru +kisstwink.com +kitnastar.com +kjkszpjcompany.com +kkmail.be +kksm.be +klassmaster.com +klassmaster.net +klick-tipp.us +klipschx12.com +kloap.com +kludgemush.com +klzlk.com +kmail.li +kmhow.com +knol-power.nl +kobrandly.com +kommunity.biz +kon42.com +konultant-jurist.ru +kook.ml +kopagas.com +kopaka.net +korona-nedvizhimosti.ru +koshu.ru +kosmetik-obatkuat.com +kostenlosemailadresse.de +koszmail.pl +kpay.be +kpooa.com +kpost.be +krd.ag +krsw.tk +kruay.com +krypton.tk +ksmtrck.tk +kuhrap.com +kulmeo.com +kulturbetrieb.info +kurzepost.de +kutakbisajauhjauh.gq +kvhrr.com +kvhrs.com +kvhrw.com +kwift.net +kwilco.net +kyal.pl +kyois.com +kzccv.com +l-c-a.us +l33r.eu +l6factors.com +labetteraverouge.at +labworld.org +lacedmail.com +lackmail.net +lackmail.ru +lacto.info +lags.us +lain.ch +lak.pp.ua +lakelivingstonrealestate.com +lakqs.com +lamasticots.com +landmail.co +laoeq.com +larisia.com +larland.com +last-chance.pro +lastmail.co +lastmail.com +lawlita.com +lazyinbox.com +lazyinbox.us +ldaho.biz +ldop.com +ldtp.com +le-tim.ru +lee.mx +leeching.net +leetmail.co +legalrc.loan +lellno.gq +lenovog4.com +lerbhe.com +letmeinonthis.com +letthemeatspam.com +lez.se +lgxscreen.com +lhsdv.com +liamcyrus.com +lifebyfood.com +lifetimefriends.info +lifetotech.com +ligsb.com +lillemap.net +lilo.me +lindenbaumjapan.com +link2mail.net +linkedintuts2016.pw +linshiyouxiang.net +linuxmail.so +litedrop.com +liveradio.tk +lkgn.se +llogin.ru +loadby.us +loan101.pro +loaoa.com +loapq.com +locanto1.club +locantofuck.top +locantowsite.club +locomodev.net +login-email.cf +login-email.ga +login-email.ml +login-email.tk +logular.com +loh.pp.ua +loin.in +lolfreak.net +lolmail.biz +lookugly.com +lordsofts.com +lortemail.dk +losemymail.com +lovemeet.faith +lovemeleaveme.com +lpfmgmtltd.com +lr7.us +lr78.com +lroid.com +lru.me +ls-server.ru +lsyx24.com +luckymail.org +lukecarriere.com +lukemail.info +lukop.dk +luv2.us +lyfestylecreditsolutions.com +lyft.live +lyricspad.net +lzoaq.com +m21.cc +m4ilweb.info +maboard.com +mac-24.com +macr2.com +macromaid.com +macromice.info +magamail.com +maggotymeat.ga +magicbox.ro +magim.be +magspam.net +maidlow.info +mail-card.net +mail-easy.fr +mail-filter.com +mail-help.net +mail-hosting.co +mail-hub.info +mail-now.top +mail-owl.com +mail-share.com +mail-temporaire.com +mail-temporaire.fr +mail-tester.com +mail.by +mail.wtf +mail0.ga +mail1.top +mail114.net +mail1a.de +mail1web.org +mail21.cc +mail22.club +mail2rss.org +mail333.com +mail4trash.com +mail666.ru +mail7.io +mail707.com +mail72.com +mailapp.top +mailback.com +mailbidon.com +mailbiz.biz +mailblocks.com +mailbox.in.ua +mailbox52.ga +mailbox80.biz +mailbox82.biz +mailbox87.de +mailbox92.biz +mailboxy.fun +mailbucket.org +mailcat.biz +mailcatch.com +mailchop.com +mailcker.com +maildax.me +mailde.de +mailde.info +maildrop.cc +maildrop.cf +maildrop.ga +maildrop.gq +maildrop.ml +maildu.de +maildx.com +maileater.com +mailed.in +mailed.ro +maileimer.de +maileme101.com +mailexpire.com +mailf5.com +mailfa.tk +mailfall.com +mailfirst.icu +mailforspam.com +mailfree.ga +mailfree.gq +mailfree.ml +mailfreeonline.com +mailfs.com +mailguard.me +mailgutter.com +mailhazard.com +mailhazard.us +mailhex.com +mailhub.pro +mailhz.me +mailimate.com +mailin8r.com +mailinatar.com +mailinater.com +mailinator.co.uk +mailinator.com +mailinator.gq +mailinator.info +mailinator.net +mailinator.org +mailinator.us +mailinator0.com +mailinator1.com +mailinator2.com +mailinator2.net +mailinator3.com +mailinator4.com +mailinator5.com +mailinator6.com +mailinator7.com +mailinator8.com +mailinator9.com +mailincubator.com +mailismagic.com +mailita.tk +mailjunk.cf +mailjunk.ga +mailjunk.gq +mailjunk.ml +mailjunk.tk +mailmate.com +mailme.gq +mailme.ir +mailme.lv +mailme24.com +mailmetrash.com +mailmoat.com +mailmoth.com +mailms.com +mailna.biz +mailna.co +mailna.in +mailna.me +mailnator.com +mailnesia.com +mailnull.com +mailonaut.com +mailorc.com +mailorg.org +mailosaur.net +mailox.fun +mailpick.biz +mailpluss.com +mailpooch.com +mailpoof.com +mailpress.gq +mailproxsy.com +mailquack.com +mailrock.biz +mailsac.com +mailscrap.com +mailseal.de +mailshell.com +mailshiv.com +mailsiphon.com +mailslapping.com +mailslite.com +mailsucker.net +mailt.net +mailt.top +mailtechx.com +mailtemp.info +mailtemporaire.com +mailtemporaire.fr +mailto.plus +mailtome.de +mailtothis.com +mailtraps.com +mailtrash.net +mailtrix.net +mailtv.net +mailtv.tv +mailuniverse.co.uk +mailzi.ru +mailzilla.com +mailzilla.org +mainerfolg.info +makemenaughty.club +makemetheking.com +malahov.de +malayalamdtp.com +mama3.org +mamulenok.ru +mandraghen.cf +manifestgenerator.com +mannawo.com +mansiondev.com +manybrain.com +mark-compressoren.ru +marketlink.info +markmurfin.com +mask03.ru +masonline.info +maswae.world +matamuasu.ga +matchpol.net +matra.site +max-mail.org +mbox.re +mbx.cc +mcache.net +mciek.com +mdhc.tk +meantinc.com +mebelnu.info +mechanicalresumes.com +medkabinet-uzi.ru +meepsheep.eu +meidecn.com +meinspamschutz.de +meltedbrownies.com +meltmail.com +memsg.site +mentonit.net +mepost.pw +merry.pink +messagebeamer.de +messwiththebestdielikethe.rest +metadownload.org +metaintern.net +metalunits.com +mezimages.net +mfsa.info +mfsa.ru +mhzayt.online +miaferrari.com +miauj.com +midcoastcustoms.com +midcoastcustoms.net +midcoastsolutions.com +midcoastsolutions.net +midiharmonica.com +midlertidig.com +midlertidig.net +midlertidig.org +mierdamail.com +migmail.net +migmail.pl +migumail.com +mihep.com +mijnhva.nl +ministry-of-silly-walks.de +minsmail.com +mintemail.com +mirai.re +misterpinball.de +miucce.com +mji.ro +mjj.edu.ge +mjukglass.nu +mkpfilm.com +ml8.ca +mm.my +mm5.se +mnode.me +moakt.cc +moakt.co +moakt.com +moakt.ws +mobileninja.co.uk +mobilevpn.top +moburl.com +mockmyid.com +moeri.org +mofu.be +mohmal.com +mohmal.im +mohmal.in +mohmal.tech +moimoi.re +molms.com +momentics.ru +monachat.tk +monadi.ml +moneypipe.net +monumentmail.com +moonwake.com +moot.es +moreawesomethanyou.com +moreorcs.com +morriesworld.ml +morsin.com +moruzza.com +motique.de +mountainregionallibrary.net +mox.pp.ua +moy-elektrik.ru +moza.pl +mozej.com +mp-j.ga +mr24.co +mrvpm.net +mrvpt.com +msgos.com +mspeciosa.com +msrc.ml +mswork.ru +msxd.com +mt2009.com +mt2014.com +mt2015.com +mtmdev.com +muathegame.com +muchomail.com +mucincanon.com +muehlacker.tk +muell.icu +muell.monster +muell.xyz +muellemail.com +muellmail.com +munoubengoshi.gq +musiccode.me +mutant.me +mvrht.com +mvrht.net +mwarner.org +mxclip.com +mxfuel.com +my-pomsies.ru +my-teddyy.ru +my10minutemail.com +mybitti.de +mycleaninbox.net +mycorneroftheinter.net +myde.ml +mydefipet.live +mydemo.equipment +myecho.es +myemailboxy.com +mygeoweb.info +myindohome.services +myinterserver.ml +mykickassideas.com +mymail-in.net +mymail90.com +mymailoasis.com +mynetstore.de +myopang.com +mypacks.net +mypartyclip.de +myphantomemail.com +mysamp.de +myspaceinc.com +myspaceinc.net +myspaceinc.org +myspacepimpedup.com +myspamless.com +mystvpn.com +mysugartime.ru +mytemp.email +mytempemail.com +mytempmail.com +mytrashmail.com +mywarnernet.net +mywrld.site +mywrld.top +myzx.com +mzico.com +n1nja.org +na-cat.com +nabuma.com +nada.email +nada.ltd +nagi.be +nakedtruth.biz +nanonym.ch +naslazhdai.ru +nationalgardeningclub.com +nawmin.info +nbzmr.com +negated.com +neko2.net +nekochan.fr +neomailbox.com +neotlozhniy-zaim.ru +nepwk.com +nervmich.net +nervtmich.net +net1mail.com +netcom.ws +netmails.com +netmails.net +netricity.nl +netris.net +netviewer-france.com +netzidiot.de +nevermail.de +newbpotato.tk +newfilm24.ru +newideasfornewpeople.info +newmail.top +next.ovh +nextmail.info +nextstopvalhalla.com +nezdiro.org +nezid.com +nezumi.be +nezzart.com +nfast.net +nguyenusedcars.com +nh3.ro +nice-4u.com +nicknassar.com +nincsmail.com +nincsmail.hu +niseko.be +niwl.net +nm7.cc +nmail.cf +nnh.com +nnot.net +nnoway.ru +no-spam.ws +no-ux.com +noblepioneer.com +nobugmail.com +nobulk.com +nobuma.com +noclickemail.com +nodezine.com +nogmailspam.info +noicd.com +nokiamail.com +nolemail.ga +nomail.cf +nomail.ga +nomail.pw +nomail2me.com +nomorespamemails.com +nonspam.eu +nonspammer.de +nonze.ro +noref.in +norseforce.com +norwegischlernen.info +nospam4.us +nospamfor.us +nospamthanks.info +nothingtoseehere.ca +notif.me +notmailinator.com +notrnailinator.com +notsharingmy.info +now.im +nowhere.org +nowmymail.com +nowmymail.net +nproxi.com +nthrl.com +ntlhelp.net +nubescontrol.com +nullbox.info +nurfuerspam.de +nut.cc +nutpa.net +nuts2trade.com +nvhrw.com +nwldx.com +nwytg.com +nwytg.net +ny7.me +nypato.com +nyrmusic.com +o2stk.org +o7i.net +oalsp.com +obfusko.com +objectmail.com +obobbo.com +oborudovanieizturcii.ru +obxpestcontrol.com +octovie.com +odaymail.com +odem.com +odnorazovoe.ru +oepia.com +oerpub.org +offshore-proxies.net +ohaaa.de +ohi.tw +oida.icu +oing.cf +okclprojects.com +okinawa.li +okrent.us +okzk.com +olimp-case.ru +olypmall.ru +omail.pro +omnievents.org +omtecha.com +one-mail.top +one-time.email +one2mail.info +onekisspresave.com +onemail.host +oneoffemail.com +oneoffmail.com +onetm.jp +onewaymail.com +onlatedotcom.info +online.ms +onlineidea.info +onqin.com +ontyne.biz +oohioo.com +oolus.com +oonies-shoprus.ru +oopi.org +oosln.com +opayq.com +openavz.com +opendns.ro +opentrash.com +opmmedia.ga +opp24.com +optimaweb.me +opwebw.com +oranek.com +ordinaryamerican.net +oreidresume.com +orgmbx.cc +oroki.de +oshietechan.link +otherinbox.com +ourklips.com +ourpreviewdomain.com +outlawspam.com +outmail.win +ovomail.co +ovpn.to +owleyes.ch +owlpic.com +ownsyou.de +oxopoha.com +ozyl.de +p-banlis.ru +p33.org +p71ce1m.com +pa9e.com +pachilly.com +packiu.com +pagamenti.tk +paharpurmim.ga +pakadebu.ga +pamaweb.com +pancakemail.com +papierkorb.me +paplease.com +para2019.ru +parlimentpetitioner.tk +pastebitch.com +patonce.com +pavilionx2.com +payperex2.com +payspun.com +pe.hu +pecinan.com +pecinan.net +pecinan.org +penisgoes.in +penoto.tk +pepbot.com +peterdethier.com +petloca.com +petrzilka.net +pewpewpewpew.pw +pfui.ru +phone-elkey.ru +photo-impact.eu +photomark.net +pi.vu +piaa.me +pig.pp.ua +pii.at +piki.si +pimpedupmyspace.com +pinehill-seattle.org +pingir.com +pipemail.space +pisls.com +pitaniezdorovie.ru +pivo-bar.ru +pixiil.com +pjjkp.com +placebomail10.com +pleasenoham.org +plexfirm.com +plexolan.de +plhk.ru +ploae.com +plw.me +poehali-otdihat.ru +pojok.ml +pokemail.net +pokiemobile.com +polarkingxx.ml +politikerclub.de +polyfaust.net +pooae.com +poofy.org +pookmail.com +poopiebutt.club +popcornfarm7.com +popcornfly.com +popesodomy.com +popgx.com +porjoton.com +porsh.net +posdz.com +posta.store +postacin.com +postonline.me +poutineyourface.com +powered.name +powerencry.com +powlearn.com +pp7rvv.com +ppetw.com +pptrvv.com +pqoia.com +pratikmail.com +pratikmail.net +pratikmail.org +prazdnik-37.ru +predatorrat.cf +predatorrat.ga +predatorrat.gq +predatorrat.ml +predatorrat.tk +premium-mail.fr +primabananen.net +prin.be +privacy.net +privatdemail.net +privy-mail.com +privy-mail.de +privymail.de +pro-tag.org +pro5g.com +procrackers.com +profast.top +projectcl.com +promailt.com +proprietativalcea.ro +propscore.com +protempmail.com +proxymail.eu +proxyparking.com +prtnx.com +prtshr.com +prtz.eu +psh.me +psles.com +psnator.com +psoxs.com +puglieisi.com +puji.pro +punkass.com +puppetmail.de +purcell.email +purelogistics.org +put2.net +puttanamaiala.tk +putthisinyourspamdatabase.com +pwrby.com +qasti.com +qbfree.us +qc.to +qibl.at +qiott.com +qipmail.net +qiq.us +qisdo.com +qisoa.com +qmrbe.com +qoika.com +qopow.com +qq.my +qsl.ro +qtum-ico.com +quadrafit.com +quick-mail.cc +quickemail.info +quickinbox.com +quickmail.nl +quicksend.ch +ququb.com +qvy.me +qwickmail.com +r4nd0m.de +ra3.us +rabin.ca +rabiot.reisen +rackabzar.com +raetp9.com +rainbowly.ml +raketenmann.de +rancidhome.net +randomail.io +randomail.net +rapt.be +raqid.com +rax.la +raxtest.com +razemail.com +razuz.com +rbb.org +rcasd.com +rcpt.at +rdklcrv.xyz +re-gister.com +reality-concept.club +reallymymail.com +realtyalerts.ca +rebates.stream +receiveee.com +recipeforfailure.com +recode.me +reconmail.com +recyclemail.dk +redfeathercrow.com +reftoken.net +regbypass.com +regspaces.tk +reimondo.com +rejectmail.com +rejo.technology +reliable-mail.com +remail.cf +remail.ga +remarkable.rocks +remote.li +reptilegenetics.com +resgedvgfed.tk +revolvingdoorhoax.org +rfc822.org +rhyta.com +richfinances.pw +riddermark.de +rifkian.ga +rippb.com +risingsuntouch.com +riski.cf +rklips.com +rkomo.com +rm2rf.com +rma.ec +rmqkr.net +rnailinator.com +ro.lt +robertspcrepair.com +robot-mail.com +rollindo.agency +ronnierage.net +rootfest.net +rosebearmylove.ru +rotaniliam.com +rover.info +rowe-solutions.com +royal.net +royaldoodles.org +royalmarket.life +royandk.com +rppkn.com +rsvhr.com +rtrtr.com +rtskiya.xyz +rudymail.ml +rumgel.com +runi.ca +rupayamail.com +ruru.be +rustydoor.com +rvb.ro +ryteto.me +s0ny.net +s33db0x.com +sabrestlouis.com +sackboii.com +saeoil.com +safaat.cf +safermail.info +safersignup.de +safetymail.info +safetypost.de +saharanightstempe.com +salmeow.tk +samsclass.info +sandcars.net +sandelf.de +sandwhichvideo.com +sanfinder.com +sanim.net +sanstr.com +sast.ro +satisfyme.club +satukosong.com +sausen.com +saynotospams.com +scatmail.com +scay.net +schachrol.com +schafmail.de +schmeissweg.tk +schrott-email.de +scrsot.com +sd3.in +sdvft.com +sdvgeft.com +sdvrecft.com +secmail.pw +secretemail.de +secure-mail.biz +secure-mail.cc +secured-link.net +securehost.com.es +seekapps.com +seekjobs4u.com +sejaa.lv +selfdestructingmail.com +selfdestructingmail.org +send22u.info +sendfree.org +sendingspecialflyers.com +sendnow.win +sendspamhere.com +senseless-entertainment.com +server.ms +services391.com +sexforswingers.com +sexical.com +sexyalwasmi.top +shadap.org +shalar.net +sharedmailbox.org +sharklasers.com +sheryli.com +shhmail.com +shhuut.org +shieldedmail.com +shieldemail.com +shiftmail.com +shipfromto.com +shiphazmat.org +shipping-regulations.com +shippingterms.org +shitaway.tk +shitmail.de +shitmail.me +shitmail.org +shmeriously.com +shopxda.com +shortmail.net +shotmail.ru +showslow.de +shrib.com +shut.name +shut.ws +siberpay.com +sidelka-mytischi.ru +siftportal.ru +sify.com +sika3.com +sikux.com +siliwangi.ga +silvercoin.life +sim-simka.ru +simaenaga.com +simpleitsecurity.info +sin.cl +sinaite.net +sinema.ml +sinfiltro.cl +singlespride.com +sinnlos-mail.de +sino.tw +siteposter.net +sizzlemctwizzle.com +sjuaq.com +skeefmail.com +skrx.tk +sky-inbox.com +sky-ts.de +skyrt.de +slapsfromlastnight.com +slaskpost.se +slave-auctions.net +slippery.email +slipry.net +slopsbox.com +slothmail.net +slushmail.com +sluteen.com +sly.io +smallker.tk +smapfree24.com +smapfree24.de +smapfree24.eu +smapfree24.info +smapfree24.org +smartnator.com +smarttalent.pw +smashmail.de +smellfear.com +smellrear.com +smellypotato.tk +smtp99.com +smwg.info +snakemail.com +snapwet.com +sneakmail.de +snece.com +social-mailer.tk +socialfurry.org +sofia.re +sofimail.com +sofort-mail.de +sofortmail.de +sofrge.com +softkey-office.ru +softpls.asia +sogetthis.com +sohai.ml +sohus.cn +soioa.com +soisz.com +solar-impact.pro +solvemail.info +solventtrap.wiki +songsign.com +sonshi.cf +soodmail.com +soodomail.com +soodonims.com +soombo.com +soon.it +spacebazzar.ru +spam-be-gone.com +spam.care +spam.la +spam.org.es +spam.su +spam4.me +spamail.de +spamarrest.com +spamavert.com +spambob.com +spambob.net +spambob.org +spambog.com +spambog.de +spambog.net +spambog.ru +spambooger.com +spambox.info +spambox.me +spambox.org +spambox.us +spamcero.com +spamcon.org +spamcorptastic.com +spamcowboy.com +spamcowboy.net +spamcowboy.org +spamday.com +spamdecoy.net +spamex.com +spamfighter.cf +spamfighter.ga +spamfighter.gq +spamfighter.ml +spamfighter.tk +spamfree.eu +spamfree24.com +spamfree24.de +spamfree24.eu +spamfree24.info +spamfree24.net +spamfree24.org +spamgoes.in +spamherelots.com +spamhereplease.com +spamhole.com +spamify.com +spaminator.de +spamkill.info +spaml.com +spaml.de +spamlot.net +spammer.fail +spammotel.com +spammy.host +spamobox.com +spamoff.de +spamsalad.in +spamslicer.com +spamsphere.com +spamspot.com +spamstack.net +spamthis.co.uk +spamthis.network +spamthisplease.com +spamtrail.com +spamtrap.ro +spamtroll.net +spamwc.cf +spamwc.ga +spamwc.gq +spamwc.ml +speedgaus.net +sperma.cf +spikio.com +spindl-e.com +spoofmail.de +spr.io +spritzzone.de +spruzme.com +spybox.de +spymail.com +squizzy.de +squizzy.net +sroff.com +sry.li +ssoia.com +stanfordujjain.com +starlight-breaker.net +starpower.space +startfu.com +startkeys.com +statdvr.com +stathost.net +statiix.com +stayhome.li +steam-area.ru +steambot.net +stexsy.com +stinkefinger.net +stop-my-spam.cf +stop-my-spam.com +stop-my-spam.ga +stop-my-spam.ml +stop-my-spam.pp.ua +stop-my-spam.tk +stopspam.app +storiqax.top +storj99.com +storj99.top +streetwisemail.com +stromox.com +stuckmail.com +stuffmail.de +stumpfwerk.com +stylist-volos.ru +submic.com +suburbanthug.com +suckmyd.com +sueshaw.com +suexamplesb.com +suioe.com +super-auswahl.de +supergreatmail.com +supermailer.jp +superplatyna.com +superrito.com +supersave.net +superstachel.de +superyp.com +suremail.info +sute.jp +svip520.cn +svk.jp +svxr.org +sweetpotato.ml +sweetxxx.de +swift-mail.net +swift10minutemail.com +syinxun.com +sylvannet.com +symphonyresume.com +syosetu.gq +syujob.accountants +szerz.com +tafmail.com +tafoi.gr +taglead.com +tagmymedia.com +tagyourself.com +talkinator.com +tanukis.org +tapchicuoihoi.com +taphear.com +tapi.re +tarzanmail.cf +tastrg.com +taukah.com +tb-on-line.net +tcwlm.com +tcwlx.com +tdtda.com +tech69.com +techblast.ch +techemail.com +techgroup.me +technoproxy.ru +teerest.com +teewars.org +tefl.ro +telecomix.pl +teleg.eu +teleworm.com +teleworm.us +tellos.xyz +teml.net +temp-link.net +temp-mail.com +temp-mail.de +temp-mail.org +temp-mail.pp.ua +temp-mail.ru +temp-mails.com +tempail.com +tempalias.com +tempe-mail.com +tempemail.biz +tempemail.co.za +tempemail.com +tempemail.net +tempinbox.co.uk +tempinbox.com +tempmail.cn +tempmail.co +tempmail.de +tempmail.eu +tempmail.it +tempmail.pp.ua +tempmail.us +tempmail.ws +tempmail2.com +tempmaildemo.com +tempmailer.com +tempmailer.de +tempmailer.net +tempmailo.com +tempomail.fr +tempomail.org +temporarily.de +temporarioemail.com.br +temporary-mail.net +temporaryemail.net +temporaryemail.us +temporaryforwarding.com +temporaryinbox.com +temporarymailaddress.com +tempr.email +tempsky.com +tempthe.net +tempymail.com +tensi.org +ternaklele.ga +testore.co +testudine.com +thanksnospam.info +thankyou2010.com +thatim.info +thc.st +theaviors.com +thebearshark.com +thecarinformation.com +thechildrensfocus.com +thecity.biz +thecloudindex.com +thediamants.org +thedirhq.info +theeyeoftruth.com +thejoker5.com +thelightningmail.net +thelimestones.com +thembones.com.au +themegreview.com +themostemail.com +thereddoors.online +theroyalweb.club +thescrappermovie.com +theteastory.info +thex.ro +thichanthit.com +thietbivanphong.asia +thisisnotmyrealemail.com +thismail.net +thisurl.website +thnikka.com +thoas.ru +thraml.com +thrma.com +throam.com +thrott.com +throwam.com +throwawayemailaddress.com +throwawaymail.com +throwawaymail.pp.ua +throya.com +thrubay.com +thunderbolt.science +thunkinator.org +thxmate.com +tiapz.com +tic.ec +tilien.com +timgiarevn.com +timkassouf.com +tinoza.org +tinyurl24.com +tipsb.com +tittbit.in +tiv.cc +tizi.com +tkitc.de +tlpn.org +tmail.com +tmail.ws +tmailinator.com +tmails.net +tmmbt.net +tmpbox.net +tmpemails.com +tmpeml.com +tmpeml.info +tmpjr.me +tmpmail.net +tmpmail.org +tmpx.sa.com +toddsbighug.com +tofeat.com +toiea.com +tokem.co +tokenmail.de +tonaeto.com +tonne.to +tonymanso.com +toomail.biz +toon.ml +top-shop-tovar.ru +top101.de +top1mail.ru +top1post.ru +topinrock.cf +topmail2.com +topmail2.net +topofertasdehoy.com +topranklist.de +toprumours.com +tormail.org +toss.pw +tosunkaya.com +totallynotfake.net +totalvista.com +totesmail.com +totoan.info +tourcc.com +tp-qa-mail.com +tpwlb.com +tqoai.com +tqosi.com +tradermail.info +tranceversal.com +trash-amil.com +trash-mail.at +trash-mail.cf +trash-mail.com +trash-mail.de +trash-mail.ga +trash-mail.gq +trash-mail.ml +trash-mail.tk +trash-me.com +trash2009.com +trash2010.com +trash2011.com +trashcanmail.com +trashdevil.com +trashdevil.de +trashemail.de +trashemails.de +trashinbox.com +trashmail.at +trashmail.com +trashmail.de +trashmail.gq +trashmail.io +trashmail.me +trashmail.net +trashmail.org +trashmail.ws +trashmailer.com +trashmailgenerator.de +trashmails.com +trashymail.com +trashymail.net +trasz.com +trayna.com +trbvm.com +trbvn.com +trbvo.com +trend-maker.ru +trgfu.com +trgovinanaveliko.info +trialmail.de +trickmail.net +trillianpro.com +triots.com +trixtrux1.ru +trollproject.com +tropicalbass.info +trungtamtoeic.com +truthfinderlogin.com +tryalert.com +tryninja.io +tryzoe.com +ttirv.org +ttszuo.xyz +tualias.com +tuofs.com +turoid.com +turual.com +turuma.com +tutuapp.bid +tvchd.com +tverya.com +twinmail.de +twkly.ml +twocowmail.net +twoweirdtricks.com +twzhhq.online +txen.de +txtadvertise.com +tyhe.ro +tyldd.com +tympe.net +uacro.com +uber-mail.com +ubismail.net +ubm.md +ucche.us +ucupdong.ml +uemail99.com +ufacturing.com +uggsrock.com +uguuchantele.com +uhe2.com +uhhu.ru +uiu.us +ujijima1129.gq +uk.to +ultra.fyi +ultrada.ru +uma3.be +umail.net +undo.it +unicodeworld.com +unids.com +unimark.org +unit7lahaina.com +unmail.ru +uooos.com +upliftnow.com +uplipht.com +uploadnolimit.com +upozowac.info +urfunktion.se +urhen.com +uroid.com +us.af +us.to +usa.cc +usako.net +usbc.be +used-product.fr +ushijima1129.cf +ushijima1129.ga +ushijima1129.gq +ushijima1129.ml +ushijima1129.tk +utiket.us +uu.gl +uu2.ovh +uuf.me +uwork4.us +uyhip.com +vaasfc4.tk +vaati.org +valemail.net +valhalladev.com +vankin.de +vctel.com +vda.ro +vddaz.com +vdig.com +veanlo.com +vemomail.win +venompen.com +veo.kr +ver0.cf +ver0.ga +ver0.gq +ver0.ml +ver0.tk +vercelli.cf +vercelli.ga +vercelli.gq +vercelli.ml +verdejo.com +vermutlich.net +veryday.ch +veryday.eu +veryday.info +veryrealemail.com +vesa.pw +vevs.de +vfemail.net +via.tokyo.jp +vickaentb.tk +victime.ninja +victoriantwins.com +vidchart.com +viditag.com +viewcastmedia.com +viewcastmedia.net +viewcastmedia.org +vikingsonly.com +vinernet.com +vintomaper.com +vipepe.com +vipmail.name +vipmail.pw +vipxm.net +viralplays.com +virtualemail.info +visal007.tk +visal168.cf +visal168.ga +visal168.gq +visal168.ml +visal168.tk +vixletdev.com +vixtricks.com +vkcode.ru +vmailing.info +vmani.com +vmpanda.com +vnedu.me +voidbay.com +volaj.com +voltaer.com +vomoto.com +vorga.org +votiputox.org +voxelcore.com +vpn.st +vps30.com +vps911.net +vradportal.com +vremonte24-store.ru +vrmtr.com +vsimcard.com +vssms.com +vtxmail.us +vubby.com +vuiy.pw +vusra.com +vztc.com +w-asertun.ru +w3internet.co.uk +wakingupesther.com +walala.org +walkmail.net +walkmail.ru +wallm.com +wanko.be +watch-harry-potter.com +watchever.biz +watchfull.net +watchironman3onlinefreefullmovie.com +wazabi.club +wbdev.tech +wbml.net +web-contact.info +web-ideal.fr +web-inc.net +web-mail.pp.ua +web2mailco.com +webcontact-france.eu +webemail.me +webhook.site +webm4il.info +webmail24.top +webtrip.ch +webuser.in +wee.my +wef.gr +weg-werf-email.de +wegwerf-email-addressen.de +wegwerf-email-adressen.de +wegwerf-email.at +wegwerf-email.de +wegwerf-email.net +wegwerf-emails.de +wegwerfadresse.de +wegwerfemail.com +wegwerfemail.de +wegwerfemail.info +wegwerfemail.net +wegwerfemail.org +wegwerfemailadresse.com +wegwerfmail.de +wegwerfmail.info +wegwerfmail.net +wegwerfmail.org +wegwerpmailadres.nl +wegwrfmail.de +wegwrfmail.net +wegwrfmail.org +wekawa.com +welikecookies.com +wellsfargocomcardholders.com +wemel.top +wetrainbayarea.com +wetrainbayarea.org +wfgdfhj.tk +wg0.com +wh4f.org +whatiaas.com +whatifanalytics.com +whatpaas.com +whatsaas.com +whiffles.org +whopy.com +whyspam.me +wibblesmith.com +wickmail.net +widaryanto.info +widget.gg +wierie.tk +wifimaple.com +wifioak.com +wikidocuslava.ru +wilemail.com +willhackforfood.biz +willselfdestruct.com +wimsg.com +winemaven.info +wins.com.br +wlist.ro +wmail.cf +wmail.club +wokcy.com +wolfmail.ml +wolfsmail.tk +wollan.info +worldspace.link +wpdork.com +wpg.im +wralawfirm.com +writeme.us +wronghead.com +ws.gy +wsym.de +wudet.men +wuespdj.xyz +wupics.com +wuuvo.com +wuzup.net +wuzupmail.net +wwjmp.com +wwwnew.eu +wxnw.net +x24.com +xagloo.co +xagloo.com +xbaby69.top +xcode.ro +xcodes.net +xcompress.com +xcoxc.com +xcpy.com +xemaps.com +xemne.com +xents.com +xjoi.com +xkx.me +xl.cx +xmail.com +xmailer.be +xmaily.com +xn--9kq967o.com +xn--d-bga.net +xojxe.com +xost.us +xoxox.cc +xperiae5.com +xrap.de +xrho.com +xvx.us +xwaretech.com +xwaretech.info +xwaretech.net +xww.ro +xxhamsterxx.ga +xxi2.com +xxlocanto.us +xxolocanto.us +xxqx3802.com +xy9ce.tk +xyzfree.net +xzsok.com +yabai-oppai.tk +yahmail.top +yahooproduct.net +yamail.win +yanet.me +yannmail.win +yapped.net +yaqp.com +yarnpedia.ga +ycare.de +ycn.ro +ye.vc +yedi.org +yeezus.ru +yep.it +yermail.net +yhg.biz +ynmrealty.com +yodx.ro +yogamaven.com +yoggm.com +yomail.info +yoo.ro +yopmail.com +yopmail.fr +yopmail.gq +yopmail.net +yopmail.pp.ua +yordanmail.cf +you-spam.com +yougotgoated.com +youmail.ga +youmailr.com +youneedmore.info +youpymail.com +yourdomain.com +youremail.cf +yourewronghereswhy.com +yourlms.biz +yourspamgoesto.space +yourtube.ml +yroid.com +yspend.com +ytpayy.com +yugasandrika.com +yui.it +yuoia.com +yuurok.com +yxzx.net +yyolf.net +z-o-e-v-a.ru +z0d.eu +z1p.biz +z86.ru +zain.site +zainmax.net +zaktouni.fr +zarabotokdoma11.ru +zasod.com +zaym-zaym.ru +zcrcd.com +zdenka.net +ze.tc +zebins.com +zebins.eu +zehnminuten.de +zehnminutenmail.de +zepp.dk +zetmail.com +zfymail.com +zhaoqian.ninja +zhaoyuanedu.cn +zhcne.com +zhewei88.com +zhorachu.com +zik.dj +zipcad.com +zipo1.gq +zippymail.info +zipsendtest.com +zoaxe.com +zoemail.com +zoemail.net +zoemail.org +zoetropes.org +zombie-hive.com +zomg.info +zsero.com +zumpul.com +zv68.com +zxcv.com +zxcvbnm.com +zymuying.com +zzi.us +zzrgg.com +zzz.com \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/actionController.ts b/backend/src/ee/controllers/v1/actionController.ts index b136b0fa4..4b3117b20 100644 --- a/backend/src/ee/controllers/v1/actionController.ts +++ b/backend/src/ee/controllers/v1/actionController.ts @@ -1,5 +1,4 @@ import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; import { Action, SecretVersion } from '../../models'; import { ActionNotFoundError } from '../../../utils/errors'; @@ -28,4 +27,4 @@ export const getAction = async (req: Request, res: Response) => { return res.status(200).send({ action }); -} \ No newline at end of file +} diff --git a/backend/src/ee/controllers/v1/cloudProductsController.ts b/backend/src/ee/controllers/v1/cloudProductsController.ts new file mode 100644 index 000000000..c7d60ca1a --- /dev/null +++ b/backend/src/ee/controllers/v1/cloudProductsController.ts @@ -0,0 +1,28 @@ +import { Request, Response } from 'express'; +import { EELicenseService } from '../../services'; +import { getLicenseServerUrl } from '../../../config'; +import { licenseServerKeyRequest } from '../../../config/request'; + +/** + * Return available cloud product information. + * Note: Nicely formatted to easily construct a table from + * @param req + * @param res + * @returns + */ +export const getCloudProducts = async (req: Request, res: Response) => { + const billingCycle = req.query['billing-cycle'] as string; + + if (EELicenseService.instanceType === 'cloud') { + const { data } = await licenseServerKeyRequest.get( + `${await getLicenseServerUrl()}/api/license-server/v1/cloud-products?billing-cycle=${billingCycle}` + ); + + return res.status(200).send(data); + } + + return res.status(200).send({ + head: [], + rows: [] + }); +} diff --git a/backend/src/ee/controllers/v1/index.ts b/backend/src/ee/controllers/v1/index.ts index aaa697286..bf3992b17 100644 --- a/backend/src/ee/controllers/v1/index.ts +++ b/backend/src/ee/controllers/v1/index.ts @@ -1,15 +1,19 @@ import * as stripeController from './stripeController'; import * as secretController from './secretController'; import * as secretSnapshotController from './secretSnapshotController'; +import * as organizationsController from './organizationsController'; import * as workspaceController from './workspaceController'; import * as actionController from './actionController'; import * as membershipController from './membershipController'; +import * as cloudProductsController from './cloudProductsController'; export { stripeController, secretController, secretSnapshotController, + organizationsController, workspaceController, actionController, - membershipController + membershipController, + cloudProductsController } \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/membershipController.ts b/backend/src/ee/controllers/v1/membershipController.ts index fcf158ba8..35534d19c 100644 --- a/backend/src/ee/controllers/v1/membershipController.ts +++ b/backend/src/ee/controllers/v1/membershipController.ts @@ -2,7 +2,8 @@ import { Request, Response } from "express"; import { Membership, Workspace } from "../../../models"; import { IMembershipPermission } from "../../../models/membership"; import { BadRequestError, UnauthorizedRequestError } from "../../../utils/errors"; -import { ABILITY_READ, ABILITY_WRITE, ADMIN, MEMBER } from "../../../variables/organization"; +import { ADMIN, MEMBER } from "../../../variables/organization"; +import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from '../../../variables'; import { Builder } from "builder-pattern" import _ from "lodash"; @@ -10,7 +11,7 @@ export const denyMembershipPermissions = async (req: Request, res: Response) => const { membershipId } = req.params; const { permissions } = req.body; const sanitizedMembershipPermissions: IMembershipPermission[] = permissions.map((permission: IMembershipPermission) => { - if (!permission.ability || !permission.environmentSlug || ![ABILITY_READ, ABILITY_WRITE].includes(permission.ability)) { + if (!permission.ability || !permission.environmentSlug || ![PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS].includes(permission.ability)) { throw BadRequestError({ message: "One or more required fields are missing from the request or have incorrect type" }) } diff --git a/backend/src/ee/controllers/v1/organizationsController.ts b/backend/src/ee/controllers/v1/organizationsController.ts new file mode 100644 index 000000000..2d2867d71 --- /dev/null +++ b/backend/src/ee/controllers/v1/organizationsController.ts @@ -0,0 +1,84 @@ +import { Request, Response } from 'express'; +import { getLicenseServerUrl } from '../../../config'; +import { licenseServerKeyRequest } from '../../../config/request'; +import { EELicenseService } from '../../services'; + +/** + * Return the organization's current plan and allowed feature set + */ +export const getOrganizationPlan = async (req: Request, res: Response) => { + const { organizationId } = req.params; + const workspaceId = req.query.workspaceId as string; + + const plan = await EELicenseService.getPlan(organizationId, workspaceId); + + return res.status(200).send({ + plan, + }); +} + +/** + * Update the organization plan to product with id [productId] + * @param req + * @param res + * @returns + */ +export const updateOrganizationPlan = async (req: Request, res: Response) => { + const { + productId + } = req.body; + + const { data } = await licenseServerKeyRequest.patch( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/cloud-plan`, + { + productId + } + ); + + return res.status(200).send(data); +} + +/** + * Return the organization's payment methods on file + */ +export const getOrganizationPmtMethods = async (req: Request, res: Response) => { + const { data: { pmtMethods } } = await licenseServerKeyRequest.get( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/billing-details/payment-methods` + ); + + return res.status(200).send({ + pmtMethods + }); +} + +/** + * Return a Stripe session URL to add payment method for organization + */ +export const addOrganizationPmtMethod = async (req: Request, res: Response) => { + const { + success_url, + cancel_url + } = req.body; + + const { data: { url } } = await licenseServerKeyRequest.post( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/billing-details/payment-methods`, + { + success_url, + cancel_url + } + ); + + return res.status(200).send({ + url + }); +} + +export const deleteOrganizationPmtMethod = async (req: Request, res: Response) => { + const { pmtMethodId } = req.params; + + const { data } = await licenseServerKeyRequest.delete( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${req.organization.customerId}/billing-details/payment-methods/${pmtMethodId}`, + ); + + return res.status(200).send(data); +} \ No newline at end of file diff --git a/backend/src/ee/controllers/v1/secretController.ts b/backend/src/ee/controllers/v1/secretController.ts index e1aca670f..9ba3c77e3 100644 --- a/backend/src/ee/controllers/v1/secretController.ts +++ b/backend/src/ee/controllers/v1/secretController.ts @@ -1,16 +1,15 @@ -import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; -import { Secret } from '../../../models'; -import { SecretVersion } from '../../models'; -import { EESecretService } from '../../services'; +import { Request, Response } from "express"; +import { Secret } from "../../../models"; +import { SecretVersion } from "../../models"; +import { EESecretService } from "../../services"; /** * Return secret versions for secret with id [secretId] - * @param req - * @param res + * @param req + * @param res */ - export const getSecretVersions = async (req: Request, res: Response) => { - /* +export const getSecretVersions = async (req: Request, res: Response) => { + /* #swagger.summary = 'Return secret versions' #swagger.description = 'Return secret versions' @@ -55,41 +54,34 @@ import { EESecretService } from '../../services'; } } */ - let secretVersions; - try { - const { secretId } = req.params; + const { secretId, workspaceId, environment, folderId } = req.params; - const offset: number = parseInt(req.query.offset as string); - const limit: number = parseInt(req.query.limit as string); - - secretVersions = await SecretVersion.find({ - secret: secretId - }) - .sort({ createdAt: -1 }) - .skip(offset) - .limit(limit); + const offset: number = parseInt(req.query.offset as string); + const limit: number = parseInt(req.query.limit as string); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get secret versions' - }); - } - - return res.status(200).send({ - secretVersions - }); -} + const secretVersions = await SecretVersion.find({ + secret: secretId, + workspace: workspaceId, + environment, + folder: folderId, + }) + .sort({ createdAt: -1 }) + .skip(offset) + .limit(limit); + + return res.status(200).send({ + secretVersions, + }); +}; /** * Roll back secret with id [secretId] to version [version] - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const rollbackSecretVersion = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Roll back secret to a version.' #swagger.description = 'Roll back secret to a version.' @@ -137,88 +129,92 @@ export const rollbackSecretVersion = async (req: Request, res: Response) => { } } */ - let secret; - try { - const { secretId } = req.params; - const { version } = req.body; - - // validate secret version - const oldSecretVersion = await SecretVersion.findOne({ - secret: secretId, - version - }); - - if (!oldSecretVersion) throw new Error('Failed to find secret version'); - - const { - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - } = oldSecretVersion; - - // update secret - secret = await Secret.findByIdAndUpdate( - secretId, - { - $inc: { - version: 1 - }, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - }, - { - new: true - } - ); - - if (!secret) throw new Error('Failed to find and update secret'); + const { secretId } = req.params; + const { version } = req.body; - // add new secret version - await new SecretVersion({ - secret: secretId, - version: secret.version, - workspace, - type, - user, - environment, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag - }).save(); - - // take secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId: secret.workspace.toString() - }); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to roll back secret version' - }); - } - - return res.status(200).send({ - secret - }); -} \ No newline at end of file + // validate secret version + const oldSecretVersion = await SecretVersion.findOne({ + secret: secretId, + version, + }).select("+secretBlindIndex"); + + if (!oldSecretVersion) throw new Error("Failed to find secret version"); + + const { + workspace, + type, + user, + environment, + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + algorithm, + folder, + keyEncoding, + } = oldSecretVersion; + + // update secret + const secret = await Secret.findByIdAndUpdate( + secretId, + { + $inc: { + version: 1, + }, + workspace, + type, + user, + environment, + ...(secretBlindIndex ? { secretBlindIndex } : {}), + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + folderId: folder, + algorithm, + keyEncoding, + }, + { + new: true, + } + ); + + if (!secret) throw new Error("Failed to find and update secret"); + + // add new secret version + await new SecretVersion({ + secret: secretId, + version: secret.version, + workspace, + type, + user, + environment, + isDeleted: false, + ...(secretBlindIndex ? { secretBlindIndex } : {}), + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + folder, + algorithm, + keyEncoding, + }).save(); + + // take secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: secret.workspace, + environment, + folderId: folder, + }); + + return res.status(200).send({ + secret, + }); +}; diff --git a/backend/src/ee/controllers/v1/secretSnapshotController.ts b/backend/src/ee/controllers/v1/secretSnapshotController.ts index ae3af7958..445add15a 100644 --- a/backend/src/ee/controllers/v1/secretSnapshotController.ts +++ b/backend/src/ee/controllers/v1/secretSnapshotController.ts @@ -1,39 +1,45 @@ -import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; -import { SecretSnapshot } from '../../models'; +import { Request, Response } from "express"; +import { + ISecretVersion, + SecretSnapshot, + TFolderRootVersionSchema, +} from "../../models"; /** * Return secret snapshot with id [secretSnapshotId] - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const getSecretSnapshot = async (req: Request, res: Response) => { - let secretSnapshot; - try { - const { secretSnapshotId } = req.params; + const { secretSnapshotId } = req.params; - secretSnapshot = await SecretSnapshot - .findById(secretSnapshotId) - .populate({ - path: 'secretVersions', - populate: { - path: 'tags', - model: 'Tag', - } - }); - - if (!secretSnapshot) throw new Error('Failed to find secret snapshot'); - - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get secret snapshot' - }); - } - - return res.status(200).send({ - secretSnapshot - }); -} \ No newline at end of file + const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId) + .lean() + .populate<{ secretVersions: ISecretVersion[] }>({ + path: 'secretVersions', + populate: { + path: 'tags', + model: 'Tag' + } + }) + .populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion"); + + if (!secretSnapshot) throw new Error("Failed to find secret snapshot"); + + const folderId = secretSnapshot.folderId; + // to show only the folder required secrets + secretSnapshot.secretVersions = secretSnapshot.secretVersions.filter( + ({ folder }) => folder === folderId + ); + + secretSnapshot.folderVersion = + secretSnapshot?.folderVersion?.nodes?.children?.map(({ id, name }) => ({ + id, + name, + })) as any; + + return res.status(200).send({ + secretSnapshot, + }); +}; diff --git a/backend/src/ee/controllers/v1/stripeController.ts b/backend/src/ee/controllers/v1/stripeController.ts index 3caa0f395..172df3220 100644 --- a/backend/src/ee/controllers/v1/stripeController.ts +++ b/backend/src/ee/controllers/v1/stripeController.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Request, Response } from 'express'; import Stripe from 'stripe'; import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config'; @@ -10,26 +9,17 @@ import { getStripeSecretKey, getStripeWebhookSecret } from '../../../config'; * @returns */ export const handleWebhook = async (req: Request, res: Response) => { - let event; - try { - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: '2022-08-01' + }); - // check request for valid stripe signature - const sig = req.headers['stripe-signature'] as string; - event = stripe.webhooks.constructEvent( - req.body, - sig, - getStripeWebhookSecret() - ); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - error: 'Failed to process webhook' - }); - } + // check request for valid stripe signature + const sig = req.headers['stripe-signature'] as string; + const event = stripe.webhooks.constructEvent( + req.body, + sig, + await getStripeWebhookSecret() + ); switch (event.type) { case '': diff --git a/backend/src/ee/controllers/v1/workspaceController.ts b/backend/src/ee/controllers/v1/workspaceController.ts index ea9bb7dab..166171ccd 100644 --- a/backend/src/ee/controllers/v1/workspaceController.ts +++ b/backend/src/ee/controllers/v1/workspaceController.ts @@ -1,25 +1,29 @@ -import { Request, Response } from 'express'; -import * as Sentry from '@sentry/node'; -import { Types } from 'mongoose'; +import { Request, Response } from "express"; +import { PipelineStage, Types } from "mongoose"; +import { Secret } from "../../../models"; import { - Secret -} from '../../../models'; -import { - SecretSnapshot, - Log, - SecretVersion, - ISecretVersion -} from '../../models'; -import { EESecretService } from '../../services'; -import { getLatestSecretVersionIds } from '../../helpers/secretVersion'; + SecretSnapshot, + Log, + SecretVersion, + ISecretVersion, + FolderVersion, + TFolderRootVersionSchema, +} from "../../models"; +import { EESecretService } from "../../services"; +import { getLatestSecretVersionIds } from "../../helpers/secretVersion"; +import Folder, { TFolderSchema } from "../../../models/folder"; +import { searchByFolderId } from "../../../services/FolderService"; /** * Return secret snapshots for workspace with id [workspaceId] - * @param req - * @param res + * @param req + * @param res */ - export const getWorkspaceSecretSnapshots = async (req: Request, res: Response) => { - /* +export const getWorkspaceSecretSnapshots = async ( + req: Request, + res: Response +) => { + /* #swagger.summary = 'Return project secret snapshot ids' #swagger.description = 'Return project secret snapshots ids' @@ -64,66 +68,60 @@ import { getLatestSecretVersionIds } from '../../helpers/secretVersion'; } } */ - let secretSnapshots; - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; + const { environment, folderId } = req.query; - const offset: number = parseInt(req.query.offset as string); - const limit: number = parseInt(req.query.limit as string); - - secretSnapshots = await SecretSnapshot.find({ - workspace: workspaceId - }) - .sort({ createdAt: -1 }) - .skip(offset) - .limit(limit); + const offset: number = parseInt(req.query.offset as string); + const limit: number = parseInt(req.query.limit as string); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get secret snapshots' - }); - } - - return res.status(200).send({ - secretSnapshots - }); -} + const secretSnapshots = await SecretSnapshot.find({ + workspace: workspaceId, + environment, + folderId: folderId || "root", + }) + .sort({ createdAt: -1 }) + .skip(offset) + .limit(limit); + + return res.status(200).send({ + secretSnapshots, + }); +}; /** * Return count of secret snapshots for workspace with id [workspaceId] - * @param req - * @param res + * @param req + * @param res */ -export const getWorkspaceSecretSnapshotsCount = async (req: Request, res: Response) => { - let count; - try { - const { workspaceId } = req.params; - count = await SecretSnapshot.countDocuments({ - workspace: workspaceId - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to count number of secret snapshots' - }); - } - - return res.status(200).send({ - count - }); -} +export const getWorkspaceSecretSnapshotsCount = async ( + req: Request, + res: Response +) => { + const { workspaceId } = req.params; + const { environment, folderId } = req.query; + + const count = await SecretSnapshot.countDocuments({ + workspace: workspaceId, + environment, + folderId: folderId || "root", + }); + + return res.status(200).send({ + count, + }); +}; /** * Rollback secret snapshot with id [secretSnapshotId] to version [version] - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ -export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Response) => { - /* +export const rollbackWorkspaceSecretSnapshot = async ( + req: Request, + res: Response +) => { + /* #swagger.summary = 'Roll back project secrets to those captured in a secret snapshot version.' #swagger.description = 'Roll back project secrets to those captured in a secret snapshot version.' @@ -173,160 +171,329 @@ export const rollbackWorkspaceSecretSnapshot = async (req: Request, res: Respons } } */ - let secrets; - try { - const { workspaceId } = req.params; - const { version } = req.body; - - // validate secret snapshot - const secretSnapshot = await SecretSnapshot.findOne({ - workspace: workspaceId, - version - }).populate<{ secretVersions: ISecretVersion[]}>('secretVersions'); - - if (!secretSnapshot) throw new Error('Failed to find secret snapshot'); - // TODO: fix any - const oldSecretVersionsObj: any = secretSnapshot.secretVersions - .reduce((accumulator, s) => ({ - ...accumulator, - [`${s.secret.toString()}`]: s - }), {}); - - const latestSecretVersionIds = await getLatestSecretVersionIds({ - secretIds: secretSnapshot.secretVersions.map((sv) => sv.secret) - }); - - // TODO: fix any - const latestSecretVersions: any = (await SecretVersion.find({ - _id: { - $in: latestSecretVersionIds.map((s) => s.versionId) - } - }, 'secret version')) - .reduce((accumulator, s) => ({ - ...accumulator, - [`${s.secret.toString()}`]: s - }), {}); - - // delete existing secrets - await Secret.deleteMany({ - workspace: workspaceId - }); + const { workspaceId } = req.params; + const { version, environment, folderId = "root" } = req.body; - // add secrets - secrets = await Secret.insertMany( - secretSnapshot.secretVersions.map((sv) => { - const secretId = sv.secret; - const { - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - createdAt - } = oldSecretVersionsObj[secretId.toString()]; - - return ({ - _id: secretId, - version: latestSecretVersions[secretId.toString()].version + 1, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - secretCommentCiphertext: '', - secretCommentIV: '', - secretCommentTag: '', - createdAt - }); - }) - ); - - // add secret versions - await SecretVersion.insertMany( - secrets.map(({ - _id, - version, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash - }) => ({ - _id: new Types.ObjectId(), - secret: _id, - version, - workspace, - type, - user, - environment, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash - })) - ); - - // update secret versions of restored secrets as not deleted - await SecretVersion.updateMany({ - secret: { - $in: secretSnapshot.secretVersions.map((sv) => sv.secret) - } - }, { - isDeleted: false - }); - - // take secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId - }); - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to roll back secret snapshot' - }); + // validate secret snapshot + const secretSnapshot = await SecretSnapshot.findOne({ + workspace: workspaceId, + version, + environment, + folderId: folderId, + }) + .populate<{ secretVersions: ISecretVersion[] }>({ + path: "secretVersions", + select: "+secretBlindIndex", + }) + .populate<{ folderVersion: TFolderRootVersionSchema }>("folderVersion"); + + if (!secretSnapshot) throw new Error("Failed to find secret snapshot"); + + const snapshotFolderTree = secretSnapshot.folderVersion; + const latestFolderTree = await Folder.findOne({ + workspace: workspaceId, + environment, + }); + + const latestFolderVersion = await FolderVersion.findOne({ + environment, + workspace: workspaceId, + "nodes.id": folderId, + }).sort({ "nodes.version": -1 }); + + const oldSecretVersionsObj: Record = {}; + const secretIds: Types.ObjectId[] = []; + const folderIds: string[] = [folderId]; + + secretSnapshot.secretVersions.forEach((snapSecVer) => { + oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer; + secretIds.push(snapSecVer.secret); + }); + + // the parent node from current latest one + // this will be modified according to the snapshot and latest snapshots + const newFolderTree = + latestFolderTree && searchByFolderId(latestFolderTree.nodes, folderId); + + if (newFolderTree) { + newFolderTree.children = snapshotFolderTree?.nodes?.children || []; + const queue = [newFolderTree]; + // a bfs algorithm in which we take the latest snapshots of all the folders in a level + while (queue.length) { + const groupByFolderId: Record = {}; + // the original queue is popped out completely to get what ever in a level + // subqueue is filled with all the children thus next level folders + // subQueue will then be transfered to the oriinal queue + const subQueue: TFolderSchema[] = []; + // get everything inside a level + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + folder.children.forEach((el) => { + folderIds.push(el.id); // push ids and data into queu + subQueue.push(el); + // to modify the original tree very fast we keep a reference object + // key with folder id and pointing to the various nodes + groupByFolderId[el.id] = el; + }); + } + // get latest snapshots of all the folder + const matchWsFoldersPipeline = { + $match: { + workspace: new Types.ObjectId(workspaceId), + environment, + folderId: { + $in: Object.keys(groupByFolderId), + }, + }, + }; + const sortByFolderIdAndVersion: PipelineStage = { + $sort: { folderId: 1, version: -1 }, + }; + const pickLatestVersionOfEachFolder = { + $group: { + _id: "$folderId", + latestVersion: { $first: "$version" }, + doc: { + $first: "$$ROOT", + }, + }, + }; + const populateSecVersion = { + $lookup: { + from: SecretVersion.collection.name, + localField: "doc.secretVersions", + foreignField: "_id", + as: "doc.secretVersions", + }, + }; + const populateFolderVersion = { + $lookup: { + from: FolderVersion.collection.name, + localField: "doc.folderVersion", + foreignField: "_id", + as: "doc.folderVersion", + }, + }; + const unwindFolderVerField = { + $unwind: { + path: "$doc.folderVersion", + preserveNullAndEmptyArrays: true, + }, + }; + const latestSnapshotsByFolders: Array<{ doc: typeof secretSnapshot }> = + await SecretSnapshot.aggregate([ + matchWsFoldersPipeline, + sortByFolderIdAndVersion, + pickLatestVersionOfEachFolder, + populateSecVersion, + populateFolderVersion, + unwindFolderVerField, + ]); + + // recursive snapshotting each level + latestSnapshotsByFolders.forEach((snap) => { + // mutate the folder tree to update the nodes to the latest version tree + // we are reconstructing the folder tree by latest snapshots here + if (groupByFolderId[snap.doc.folderId]) { + groupByFolderId[snap.doc.folderId].children = + snap.doc?.folderVersion?.nodes?.children || []; + } + + // push all children of next level snapshots + if (snap.doc.folderVersion?.nodes?.children) { + queue.push(...snap.doc.folderVersion.nodes.children); + } + + snap.doc.secretVersions.forEach((snapSecVer) => { + // record all the secrets + oldSecretVersionsObj[snapSecVer.secret.toString()] = snapSecVer; + secretIds.push(snapSecVer.secret); + }); + }); + + queue.push(...subQueue); } - - return res.status(200).send({ - secrets - }); -} + } + + // TODO: fix any + const latestSecretVersionIds = await getLatestSecretVersionIds({ + secretIds, + }); + + // TODO: fix any + const latestSecretVersions: any = ( + await SecretVersion.find( + { + _id: { + $in: latestSecretVersionIds.map((s) => s.versionId), + }, + }, + "secret version" + ) + ).reduce( + (accumulator, s) => ({ + ...accumulator, + [`${s.secret.toString()}`]: s, + }), + {} + ); + + const secDelQuery: Record = { + workspace: workspaceId, + environment, + // undefined means root thus collect all secrets + }; + if (folderId !== "root" && folderIds.length) + secDelQuery.folder = { $in: folderIds }; + + // delete existing secrets + await Secret.deleteMany(secDelQuery); + await Folder.deleteOne({ + workspace: workspaceId, + environment, + }); + + // add secrets + const secrets = await Secret.insertMany( + Object.keys(oldSecretVersionsObj).map((sv) => { + const { + secret: secretId, + workspace, + type, + user, + environment, + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + createdAt, + algorithm, + keyEncoding, + folder: secFolderId, + } = oldSecretVersionsObj[sv]; + + return { + _id: secretId, + version: latestSecretVersions[secretId.toString()].version + 1, + workspace, + type, + user, + environment, + secretBlindIndex: secretBlindIndex ?? undefined, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext: "", + secretCommentIV: "", + secretCommentTag: "", + createdAt, + algorithm, + keyEncoding, + folder: secFolderId, + }; + }) + ); + + // add secret versions + const secretV = await SecretVersion.insertMany( + secrets.map( + ({ + _id, + version, + workspace, + type, + user, + environment, + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + algorithm, + keyEncoding, + folder: secFolderId, + }) => ({ + _id: new Types.ObjectId(), + secret: _id, + version, + workspace, + type, + user, + environment, + isDeleted: false, + secretBlindIndex: secretBlindIndex ?? undefined, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + algorithm, + keyEncoding, + folder: secFolderId, + }) + ) + ); + + if (newFolderTree && latestFolderTree) { + // save the updated folder tree to the present one + newFolderTree.version = (latestFolderVersion?.nodes?.version || 0) + 1; + latestFolderTree._id = new Types.ObjectId(); + latestFolderTree.isNew = true; + await latestFolderTree.save(); + + // create new folder version + const newFolderVersion = new FolderVersion({ + workspace: workspaceId, + environment, + nodes: newFolderTree, + }); + await newFolderVersion.save(); + } + + // update secret versions of restored secrets as not deleted + await SecretVersion.updateMany( + { + secret: { + $in: Object.keys(oldSecretVersionsObj).map( + (sv) => oldSecretVersionsObj[sv].secret + ), + }, + }, + { + isDeleted: false, + } + ); + + // take secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + folderId, + }); + + return res.status(200).send({ + secrets, + }); +}; /** * Return (audit) logs for workspace with id [workspaceId] - * @param req - * @param res - * @returns + * @param req + * @param res + * @returns */ export const getWorkspaceLogs = async (req: Request, res: Response) => { - /* + /* #swagger.summary = 'Return project (audit) logs' #swagger.description = 'Return project (audit) logs' @@ -392,43 +559,32 @@ export const getWorkspaceLogs = async (req: Request, res: Response) => { } } */ - let logs - try { - const { workspaceId } = req.params; + const { workspaceId } = req.params; - const offset: number = parseInt(req.query.offset as string); - const limit: number = parseInt(req.query.limit as string); - const sortBy: string = req.query.sortBy as string; - const userId: string = req.query.userId as string; - const actionNames: string = req.query.actionNames as string; - - logs = await Log.find({ - workspace: workspaceId, - ...( userId ? { user: userId } : {}), - ...( - actionNames - ? { - actionNames: { - $in: actionNames.split(',') - } - } : {} - ) - }) - .sort({ createdAt: sortBy === 'recent' ? -1 : 1 }) - .skip(offset) - .limit(limit) - .populate('actions') - .populate('user'); + const offset: number = parseInt(req.query.offset as string); + const limit: number = parseInt(req.query.limit as string); + const sortBy: string = req.query.sortBy as string; + const userId: string = req.query.userId as string; + const actionNames: string = req.query.actionNames as string; - } catch (err) { - Sentry.setUser({ email: req.user.email }); - Sentry.captureException(err); - return res.status(400).send({ - message: 'Failed to get workspace logs' - }); - } - - return res.status(200).send({ - logs - }); -} \ No newline at end of file + const logs = await Log.find({ + workspace: workspaceId, + ...(userId ? { user: userId } : {}), + ...(actionNames + ? { + actionNames: { + $in: actionNames.split(","), + }, + } + : {}), + }) + .sort({ createdAt: sortBy === "recent" ? -1 : 1 }) + .skip(offset) + .limit(limit) + .populate("actions") + .populate("user serviceAccount serviceTokenData"); + + return res.status(200).send({ + logs, + }); +}; diff --git a/backend/src/ee/helpers/action.ts b/backend/src/ee/helpers/action.ts index eb94810f4..94e6bd24d 100644 --- a/backend/src/ee/helpers/action.ts +++ b/backend/src/ee/helpers/action.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Types } from 'mongoose'; import { Action } from '../models'; import { @@ -24,39 +23,37 @@ import { const createActionUpdateSecret = async ({ name, userId, + serviceAccountId, + serviceTokenDataId, workspaceId, secretIds }: { name: string; - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId: Types.ObjectId; secretIds: Types.ObjectId[]; }) => { - let action; - try { - const latestSecretVersions = (await getLatestNSecretSecretVersionIds({ - secretIds, - n: 2 - })) - .map((s) => ({ - oldSecretVersion: s.versions[0]._id, - newSecretVersion: s.versions[1]._id - })); - - action = await new Action({ - name, - user: userId, - workspace: workspaceId, - payload: { - secretVersions: latestSecretVersions - } - }).save(); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create update secret action'); - } + const latestSecretVersions = (await getLatestNSecretSecretVersionIds({ + secretIds, + n: 2 + })) + .map((s) => ({ + oldSecretVersion: s.versions[0]._id, + newSecretVersion: s.versions[1]._id + })); + + const action = await new Action({ + name, + user: userId, + serviceAccount: serviceAccountId, + serviceTokenData: serviceTokenDataId, + workspace: workspaceId, + payload: { + secretVersions: latestSecretVersions + } + }).save(); return action; } @@ -72,68 +69,66 @@ const createActionUpdateSecret = async ({ const createActionSecret = async ({ name, userId, + serviceAccountId, + serviceTokenDataId, workspaceId, secretIds }: { name: string; - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId: Types.ObjectId; secretIds: Types.ObjectId[]; }) => { - let action; - try { - // case: action is adding, deleting, or reading secrets - // -> add new secret versions - const latestSecretVersions = (await getLatestSecretVersionIds({ - secretIds - })) - .map((s) => ({ - newSecretVersion: s.versionId - })); - - action = await new Action({ - name, - user: userId, - workspace: workspaceId, - payload: { - secretVersions: latestSecretVersions - } - }).save(); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create action create/read/delete secret action'); - } + // case: action is adding, deleting, or reading secrets + // -> add new secret versions + const latestSecretVersions = (await getLatestSecretVersionIds({ + secretIds + })) + .map((s) => ({ + newSecretVersion: s.versionId + })); + + const action = await new Action({ + name, + user: userId, + serviceAccount: serviceAccountId, + serviceTokenData: serviceTokenDataId, + workspace: workspaceId, + payload: { + secretVersions: latestSecretVersions + } + }).save(); return action; } /** - * Create an (audit) action for user with id [userId] + * Create an (audit) action for client with id [userId], + * [serviceAccountId], or [serviceTokenDataId] * @param {Object} obj * @param {String} obj.name - name of action * @param {String} obj.userId - id of user associated with action * @returns */ -const createActionUser = ({ +const createActionClient = ({ name, - userId + userId, + serviceAccountId, + serviceTokenDataId }: { name: string; - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; }) => { - let action; - try { - action = new Action({ - name, - user: userId - }).save(); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create user action'); - } + const action = new Action({ + name, + user: userId, + serviceAccount: serviceAccountId, + serviceTokenData: serviceTokenDataId + }).save(); return action; } @@ -149,49 +144,47 @@ const createActionUser = ({ const createActionHelper = async ({ name, userId, + serviceAccountId, + serviceTokenDataId, workspaceId, secretIds, }: { name: string; - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId?: Types.ObjectId; secretIds?: Types.ObjectId[]; }) => { let action; - try { - switch (name) { - case ACTION_LOGIN: - case ACTION_LOGOUT: - action = await createActionUser({ - name, - userId - }); - break; - case ACTION_ADD_SECRETS: - case ACTION_READ_SECRETS: - case ACTION_DELETE_SECRETS: - if (!workspaceId || !secretIds) throw new Error('Missing required params workspace id or secret ids to create action secret'); - action = await createActionSecret({ - name, - userId, - workspaceId, - secretIds - }); - break; - case ACTION_UPDATE_SECRETS: - if (!workspaceId || !secretIds) throw new Error('Missing required params workspace id or secret ids to create action secret'); - action = await createActionUpdateSecret({ - name, - userId, - workspaceId, - secretIds - }); - break; - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create action'); + switch (name) { + case ACTION_LOGIN: + case ACTION_LOGOUT: + action = await createActionClient({ + name, + userId + }); + break; + case ACTION_ADD_SECRETS: + case ACTION_READ_SECRETS: + case ACTION_DELETE_SECRETS: + if (!workspaceId || !secretIds) throw new Error('Missing required params workspace id or secret ids to create action secret'); + action = await createActionSecret({ + name, + userId, + workspaceId, + secretIds + }); + break; + case ACTION_UPDATE_SECRETS: + if (!workspaceId || !secretIds) throw new Error('Missing required params workspace id or secret ids to create action secret'); + action = await createActionUpdateSecret({ + name, + userId, + workspaceId, + secretIds + }); + break; } return action; @@ -199,4 +192,4 @@ const createActionHelper = async ({ export { createActionHelper -}; \ No newline at end of file +}; diff --git a/backend/src/ee/helpers/checkMembershipPermissions.ts b/backend/src/ee/helpers/checkMembershipPermissions.ts index 50cd28917..c97a51619 100644 --- a/backend/src/ee/helpers/checkMembershipPermissions.ts +++ b/backend/src/ee/helpers/checkMembershipPermissions.ts @@ -1,8 +1,9 @@ +import { Types } from 'mongoose'; import _ from "lodash"; import { Membership } from "../../models"; -import { ABILITY_READ, ABILITY_WRITE } from "../../variables/organization"; +import { PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS } from '../../variables'; -export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, environment: any, action: any) => { +export const userHasWorkspaceAccess = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string, action: any) => { const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) if (!membershipForWorkspace) { return false @@ -18,15 +19,15 @@ export const userHasWorkspaceAccess = async (userId: any, workspaceId: any, envi return true } -export const userHasWriteOnlyAbility = async (userId: any, workspaceId: any, environment: any) => { +export const userHasWriteOnlyAbility = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string) => { const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) if (!membershipForWorkspace) { return false } const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions; - const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_WRITE }); - const isReadDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_READ }); + const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS }); + const isReadDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS }); // case: you have write only if read is blocked and write is not if (isReadDisallowed && !isWriteDisallowed) { @@ -36,15 +37,15 @@ export const userHasWriteOnlyAbility = async (userId: any, workspaceId: any, env return false } -export const userHasNoAbility = async (userId: any, workspaceId: any, environment: any) => { +export const userHasNoAbility = async (userId: Types.ObjectId, workspaceId: Types.ObjectId, environment: string) => { const membershipForWorkspace = await Membership.findOne({ workspace: workspaceId, user: userId }) if (!membershipForWorkspace) { return true } const deniedMembershipPermissions = membershipForWorkspace.deniedPermissions; - const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_WRITE }); - const isReadBlocked = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: ABILITY_READ }); + const isWriteDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS }); + const isReadBlocked = _.some(deniedMembershipPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS }); if (isReadBlocked && isWriteDisallowed) { return true diff --git a/backend/src/ee/helpers/log.ts b/backend/src/ee/helpers/log.ts index bdb0a2380..5b6d78f31 100644 --- a/backend/src/ee/helpers/log.ts +++ b/backend/src/ee/helpers/log.ts @@ -1,9 +1,9 @@ -import * as Sentry from '@sentry/node'; import { Types } from 'mongoose'; import { Log, IAction } from '../models'; + /** * Create an (audit) log * @param {Object} obj @@ -16,36 +16,35 @@ import { */ const createLogHelper = async ({ userId, + serviceAccountId, + serviceTokenDataId, workspaceId, actions, channel, ipAddress }: { - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId?: Types.ObjectId; actions: IAction[]; channel: string; ipAddress: string; }) => { - let log; - try { - log = await new Log({ - user: userId, - workspace: workspaceId ?? undefined, - actionNames: actions.map((a) => a.name), - actions, - channel, - ipAddress - }).save(); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create log'); - } + const log = await new Log({ + user: userId, + serviceAccount: serviceAccountId, + serviceTokenData: serviceTokenDataId, + workspace: workspaceId ?? undefined, + actionNames: actions.map((a) => a.name), + actions, + channel, + ipAddress + }).save(); return log; } export { createLogHelper -} \ No newline at end of file +} diff --git a/backend/src/ee/helpers/secret.ts b/backend/src/ee/helpers/secret.ts index 7edee915f..b315310cb 100644 --- a/backend/src/ee/helpers/secret.ts +++ b/backend/src/ee/helpers/secret.ts @@ -1,14 +1,11 @@ -import { Types } from 'mongoose'; -import * as Sentry from '@sentry/node'; +import { Types } from "mongoose"; +import { Secret, ISecret } from "../../models"; import { - Secret, - ISecret -} from '../../models'; -import { - SecretSnapshot, - SecretVersion, - ISecretVersion -} from '../models'; + SecretSnapshot, + SecretVersion, + ISecretVersion, + FolderVersion, +} from "../models"; /** * Save a secret snapshot that is a copy of the current state of secrets in workspace with id @@ -19,56 +16,70 @@ import { * @returns {SecretSnapshot} secretSnapshot - new secret snapshot */ const takeSecretSnapshotHelper = async ({ - workspaceId + workspaceId, + environment, + folderId = "root", }: { - workspaceId: string; + workspaceId: Types.ObjectId; + environment: string; + folderId?: string; }) => { + // get all folder ids + const secretIds = ( + await Secret.find( + { + workspace: workspaceId, + environment, + folder: folderId, + }, + "_id" + ).lean() + ).map((s) => s._id); - let secretSnapshot; - try { - const secretIds = (await Secret.find({ - workspace: workspaceId - }, '_id')).map((s) => s._id); + const latestSecretVersions = ( + await SecretVersion.aggregate([ + { + $match: { + environment, + workspace: new Types.ObjectId(workspaceId), + secret: { + $in: secretIds, + }, + }, + }, + { + $group: { + _id: "$secret", + version: { $max: "$version" }, + versionId: { $max: "$_id" }, // secret version id + }, + }, + { + $sort: { version: -1 }, + }, + ]).exec() + ).map((s) => s.versionId); + const latestFolderVersion = await FolderVersion.findOne({ + environment, + workspace: workspaceId, + "nodes.id": folderId, + }).sort({ "nodes.version": -1 }); - const latestSecretVersions = (await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds - } - } - }, - { - $group: { - _id: '$secret', - version: { $max: '$version' }, - versionId: { $max: '$_id' } // secret version id - } - }, - { - $sort: { version: -1 } - } - ]) - .exec()) - .map((s) => s.versionId); + const latestSecretSnapshot = await SecretSnapshot.findOne({ + workspace: workspaceId, + }).sort({ version: -1 }); - const latestSecretSnapshot = await SecretSnapshot.findOne({ - workspace: workspaceId - }).sort({ version: -1 }); + const secretSnapshot = await new SecretSnapshot({ + workspace: workspaceId, + environment, + version: latestSecretSnapshot ? latestSecretSnapshot.version + 1 : 1, + secretVersions: latestSecretVersions, + folderId, + folderVersion: latestFolderVersion, + }).save(); - secretSnapshot = await new SecretSnapshot({ - workspace: workspaceId, - version: latestSecretSnapshot ? latestSecretSnapshot.version + 1 : 1, - secretVersions: latestSecretVersions - }).save(); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to take a secret snapshot'); - } - - return secretSnapshot; -} + return secretSnapshot; +}; /** * Add secret versions [secretVersions] to the SecretVersion collection. @@ -77,93 +88,35 @@ const takeSecretSnapshotHelper = async ({ * @returns {SecretVersion[]} newSecretVersions - new secret versions */ const addSecretVersionsHelper = async ({ - secretVersions + secretVersions, }: { - secretVersions: ISecretVersion[] + secretVersions: ISecretVersion[]; }) => { - let newSecretVersions; - try { - newSecretVersions = await SecretVersion.insertMany(secretVersions); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error(`Failed to add secret versions [err=${err}]`); - } + const newSecretVersions = await SecretVersion.insertMany(secretVersions); - return newSecretVersions; -} + return newSecretVersions; +}; const markDeletedSecretVersionsHelper = async ({ - secretIds + secretIds, }: { - secretIds: Types.ObjectId[]; + secretIds: Types.ObjectId[]; }) => { - try { - await SecretVersion.updateMany({ - secret: { $in: secretIds } - }, { - isDeleted: true - }, { - new: true - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to mark secret versions as deleted'); - } -} - -/** - * Initialize secret versioning by setting previously unversioned - * secrets to version 1 and begin populating secret versions. - */ -const initSecretVersioningHelper = async () => { - try { - - await Secret.updateMany( - { version: { $exists: false } }, - { $set: { version: 1 } } - ); - - const unversionedSecrets: ISecret[] = await Secret.aggregate([ - { - $lookup: { - from: 'secretversions', - localField: '_id', - foreignField: 'secret', - as: 'versions', - }, - }, - { - $match: { - versions: { $size: 0 }, - }, - }, - ]); - - if (unversionedSecrets.length > 0) { - await addSecretVersionsHelper({ - secretVersions: unversionedSecrets.map((s, idx) => ({ - ...s, - secret: s._id, - version: s.version ? s.version : 1, - isDeleted: false, - workspace: s.workspace, - environment: s.environment - })) - }); - } - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to ensure that secrets are versioned'); - } -} + await SecretVersion.updateMany( + { + secret: { $in: secretIds }, + }, + { + isDeleted: true, + }, + { + new: true, + } + ); +}; export { - takeSecretSnapshotHelper, - addSecretVersionsHelper, - markDeletedSecretVersionsHelper, - initSecretVersioningHelper -} \ No newline at end of file + takeSecretSnapshotHelper, + addSecretVersionsHelper, + markDeletedSecretVersionsHelper, +}; diff --git a/backend/src/ee/helpers/secretVersion.ts b/backend/src/ee/helpers/secretVersion.ts index d5859e183..4b173f9ef 100644 --- a/backend/src/ee/helpers/secretVersion.ts +++ b/backend/src/ee/helpers/secretVersion.ts @@ -1,110 +1,82 @@ -import * as Sentry from '@sentry/node'; -import { Types } from 'mongoose'; -import { SecretVersion } from '../models'; +import { Types } from "mongoose"; +import { SecretVersion } from "../models"; /** * Return latest secret versions for secrets with ids [secretIds] * @param {Object} obj * @param {Object} obj.secretIds = ids of secrets to get latest versions for - * @returns + * @returns */ const getLatestSecretVersionIds = async ({ - secretIds + secretIds, }: { - secretIds: Types.ObjectId[]; + secretIds: Types.ObjectId[]; }) => { - - interface LatestSecretVersionId { - _id: Types.ObjectId; - version: number; - versionId: Types.ObjectId; - } - - let latestSecretVersionIds: LatestSecretVersionId[]; - try { - latestSecretVersionIds = (await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds - } - } - }, - { - $group: { - _id: '$secret', - version: { $max: '$version' }, - versionId: { $max: '$_id' } // id of latest secret version - } - }, - { - $sort: { version: -1 } - } - ]) - .exec()); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get latest secret versions'); - } - - return latestSecretVersionIds; -} + const latestSecretVersionIds = await SecretVersion.aggregate([ + { + $match: { + secret: { + $in: secretIds, + }, + }, + }, + { + $group: { + _id: "$secret", + version: { $max: "$version" }, + versionId: { $max: "$_id" }, // id of latest secret version + }, + }, + { + $sort: { version: -1 }, + }, + ]).exec(); + + return latestSecretVersionIds; +}; /** * Return latest [n] secret versions for secrets with ids [secretIds] * @param {Object} obj * @param {Object} obj.secretIds = ids of secrets to get latest versions for * @param {Number} obj.n - number of latest secret versions to return for each secret - * @returns + * @returns */ const getLatestNSecretSecretVersionIds = async ({ - secretIds, - n + secretIds, + n, }: { - secretIds: Types.ObjectId[]; - n: number; + secretIds: Types.ObjectId[]; + n: number; }) => { - - // TODO: optimize query - let latestNSecretVersions; - try { - latestNSecretVersions = (await SecretVersion.aggregate([ - { - $match: { - secret: { - $in: secretIds, - }, - }, - }, - { - $sort: { version: -1 }, - }, - { - $group: { - _id: "$secret", - versions: { $push: "$$ROOT" }, - }, - }, - { - $project: { - _id: 0, - secret: "$_id", - versions: { $slice: ["$versions", n] }, - }, - } - ])); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get latest n secret versions'); - } - - return latestNSecretVersions; -} + // TODO: optimize query + const latestNSecretVersions = await SecretVersion.aggregate([ + { + $match: { + secret: { + $in: secretIds, + }, + }, + }, + { + $sort: { version: -1 }, + }, + { + $group: { + _id: "$secret", + versions: { $push: "$$ROOT" }, + }, + }, + { + $project: { + _id: 0, + secret: "$_id", + versions: { $slice: ["$versions", n] }, + }, + }, + ]); -export { - getLatestSecretVersionIds, - getLatestNSecretSecretVersionIds -} + return latestNSecretVersions; +}; + +export { getLatestSecretVersionIds, getLatestNSecretSecretVersionIds }; diff --git a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts index 5eae3721c..af4d1e21c 100644 --- a/backend/src/ee/middleware/requireSecretSnapshotAuth.ts +++ b/backend/src/ee/middleware/requireSecretSnapshotAuth.ts @@ -15,32 +15,28 @@ import { const requireSecretSnapshotAuth = ({ acceptedRoles, }: { - acceptedRoles: string[]; + acceptedRoles: Array<'admin' | 'member'>; }) => { return async (req: Request, res: Response, next: NextFunction) => { - try { - const { secretSnapshotId } = req.params; - - const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId); - - if (!secretSnapshot) { - return next(SecretSnapshotNotFoundError({ - message: 'Failed to find secret snapshot' - })); - } - - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: secretSnapshot.workspace.toString(), - acceptedRoles - }); - - req.secretSnapshot = secretSnapshot as any; - - next(); - } catch (err) { - return next(UnauthorizedRequestError({ message: 'Unable to authenticate secret snapshot' })); + const { secretSnapshotId } = req.params; + + const secretSnapshot = await SecretSnapshot.findById(secretSnapshotId); + + if (!secretSnapshot) { + return next(SecretSnapshotNotFoundError({ + message: 'Failed to find secret snapshot' + })); } + + await validateMembership({ + userId: req.user._id, + workspaceId: secretSnapshot.workspace, + acceptedRoles + }); + + req.secretSnapshot = secretSnapshot as any; + + next(); } } diff --git a/backend/src/ee/models/action.ts b/backend/src/ee/models/action.ts index 7cdd7a355..055e144fd 100644 --- a/backend/src/ee/models/action.ts +++ b/backend/src/ee/models/action.ts @@ -11,6 +11,8 @@ import { export interface IAction { name: string; user?: Types.ObjectId, + serviceAccount?: Types.ObjectId, + serviceTokenData?: Types.ObjectId, workspace?: Types.ObjectId, payload?: { secretVersions?: Types.ObjectId[] @@ -33,8 +35,15 @@ const actionSchema = new Schema( }, user: { type: Schema.Types.ObjectId, - ref: 'User', - required: true + ref: 'User' + }, + serviceAccount: { + type: Schema.Types.ObjectId, + ref: 'ServiceAccount' + }, + serviceTokenData: { + type: Schema.Types.ObjectId, + ref: 'ServiceTokenData' }, workspace: { type: Schema.Types.ObjectId, diff --git a/backend/src/ee/models/folderVersion.ts b/backend/src/ee/models/folderVersion.ts new file mode 100644 index 000000000..f0fa5afbf --- /dev/null +++ b/backend/src/ee/models/folderVersion.ts @@ -0,0 +1,60 @@ +import { model, Schema, Types } from "mongoose"; + +export type TFolderRootVersionSchema = { + _id: Types.ObjectId; + workspace: Types.ObjectId; + environment: string; + nodes: TFolderVersionSchema; +}; + +export type TFolderVersionSchema = { + id: string; + name: string; + version: number; + children: TFolderVersionSchema[]; +}; + +const folderVersionSchema = new Schema({ + id: { + required: true, + type: String, + default: "root", + }, + name: { + required: true, + type: String, + default: "root", + }, + version: { + required: true, + type: Number, + default: 1, + }, +}); + +folderVersionSchema.add({ children: [folderVersionSchema] }); + +const folderRootVersionSchema = new Schema( + { + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, + }, + environment: { + type: String, + required: true, + }, + nodes: folderVersionSchema, + }, + { + timestamps: true, + } +); + +const FolderVersion = model( + "FolderVersion", + folderRootVersionSchema +); + +export default FolderVersion; diff --git a/backend/src/ee/models/index.ts b/backend/src/ee/models/index.ts index a6cee725e..7867674d6 100644 --- a/backend/src/ee/models/index.ts +++ b/backend/src/ee/models/index.ts @@ -1,15 +1,18 @@ -import SecretSnapshot, { ISecretSnapshot } from './secretSnapshot'; -import SecretVersion, { ISecretVersion } from './secretVersion'; -import Log, { ILog } from './log'; -import Action, { IAction } from './action'; +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, - Log, - ILog, - Action, - IAction -} \ No newline at end of file + SecretSnapshot, + ISecretSnapshot, + SecretVersion, + ISecretVersion, + FolderVersion, + TFolderRootVersionSchema, + Log, + ILog, + Action, + IAction, +}; diff --git a/backend/src/ee/models/log.ts b/backend/src/ee/models/log.ts index 47be2e58f..9ed552640 100644 --- a/backend/src/ee/models/log.ts +++ b/backend/src/ee/models/log.ts @@ -11,6 +11,8 @@ import { export interface ILog { _id: Types.ObjectId; user?: Types.ObjectId; + serviceAccount?: Types.ObjectId; + serviceTokenData?: Types.ObjectId; workspace?: Types.ObjectId; actionNames: string[]; actions: Types.ObjectId[]; @@ -24,6 +26,14 @@ const logSchema = new Schema( type: Schema.Types.ObjectId, ref: 'User' }, + serviceAccount: { + type: Schema.Types.ObjectId, + ref: 'ServiceAccount' + }, + serviceTokenData: { + type: Schema.Types.ObjectId, + ref: 'ServiceTokenData' + }, workspace: { type: Schema.Types.ObjectId, ref: 'Workspace' diff --git a/backend/src/ee/models/secretSnapshot.ts b/backend/src/ee/models/secretSnapshot.ts index c646f353a..cfc5b03b7 100644 --- a/backend/src/ee/models/secretSnapshot.ts +++ b/backend/src/ee/models/secretSnapshot.ts @@ -1,33 +1,54 @@ -import { Schema, model, Types } from 'mongoose'; +import { Schema, model, Types } from "mongoose"; export interface ISecretSnapshot { - workspace: Types.ObjectId; - version: number; - secretVersions: Types.ObjectId[]; + workspace: Types.ObjectId; + environment: string; + folderId: string | "root"; + version: number; + secretVersions: Types.ObjectId[]; + folderVersion: Types.ObjectId; } const secretSnapshotSchema = new Schema( - { - workspace: { - type: Schema.Types.ObjectId, - ref: 'Workspace', - required: true - }, - version: { - type: Number, - required: true - }, - secretVersions: [{ - type: Schema.Types.ObjectId, - ref: 'SecretVersion', - required: true - }] + { + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, }, - { - timestamps: true - } + environment: { + type: String, + required: true, + }, + folderId: { + type: String, + default: "root", + }, + version: { + type: Number, + default: 1, + required: true, + }, + secretVersions: [ + { + type: Schema.Types.ObjectId, + ref: "SecretVersion", + required: true, + }, + ], + folderVersion: { + type: Schema.Types.ObjectId, + ref: "FolderVersion", + }, + }, + { + timestamps: true, + } ); -const SecretSnapshot = model('SecretSnapshot', secretSnapshotSchema); +const SecretSnapshot = model( + "SecretSnapshot", + secretSnapshotSchema +); -export default SecretSnapshot; \ No newline at end of file +export default SecretSnapshot; diff --git a/backend/src/ee/models/secretVersion.ts b/backend/src/ee/models/secretVersion.ts index 3095b52fb..b915e640e 100644 --- a/backend/src/ee/models/secretVersion.ts +++ b/backend/src/ee/models/secretVersion.ts @@ -1,97 +1,132 @@ -import { Schema, model, Types } from 'mongoose'; +import { Schema, model, Types } from "mongoose"; import { - SECRET_SHARED, - SECRET_PERSONAL, -} from '../../variables'; + SECRET_SHARED, + SECRET_PERSONAL, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, +} from "../../variables"; export interface ISecretVersion { - secret: Types.ObjectId; - version: number; - workspace: Types.ObjectId; // new - type: string; // new - user?: Types.ObjectId; // new - environment: string; // new - isDeleted: boolean; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - tags?: string[]; + _id: Types.ObjectId; + secret: Types.ObjectId; + version: number; + workspace: Types.ObjectId; // new + type: string; // new + user?: Types.ObjectId; // new + environment: string; // new + isDeleted: boolean; + secretBlindIndex?: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + algorithm: "aes-256-gcm"; + keyEncoding: "utf8" | "base64"; + createdAt: string; + folder?: string; + tags?: string[]; } const secretVersionSchema = new Schema( - { - secret: { // could be deleted - type: Schema.Types.ObjectId, - ref: 'Secret', - required: true - }, - version: { - type: Number, - default: 1, - required: true - }, - workspace: { - type: Schema.Types.ObjectId, - ref: 'Workspace', - required: true - }, - type: { - type: String, - enum: [SECRET_SHARED, SECRET_PERSONAL], - required: true - }, - user: { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: 'User' - }, - environment: { - type: String, - required: true - }, - isDeleted: { // consider removing field - type: Boolean, - default: false, - required: true - }, - secretKeyCiphertext: { - type: String, - required: true - }, - secretKeyIV: { - type: String, // symmetric - required: true - }, - secretKeyTag: { - type: String, // symmetric - required: true - }, - secretValueCiphertext: { - type: String, - required: true - }, - secretValueIV: { - type: String, // symmetric - required: true - }, - secretValueTag: { - type: String, // symmetric - required: true - }, - tags: { - ref: 'Tag', - type: [Schema.Types.ObjectId], - default: [] - }, - }, - { - timestamps: true - } + { + secret: { + // could be deleted + type: Schema.Types.ObjectId, + ref: "Secret", + required: true, + }, + version: { + type: Number, + default: 1, + required: true, + }, + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, + }, + type: { + type: String, + enum: [SECRET_SHARED, SECRET_PERSONAL], + required: true, + }, + user: { + // user associated with the personal secret + type: Schema.Types.ObjectId, + ref: "User", + }, + environment: { + type: String, + required: true, + }, + isDeleted: { + // consider removing field + type: Boolean, + default: false, + required: true, + }, + secretBlindIndex: { + type: String, + select: false, + }, + secretKeyCiphertext: { + type: String, + required: true, + }, + secretKeyIV: { + type: String, // symmetric + required: true, + }, + secretKeyTag: { + type: String, // symmetric + required: true, + }, + secretValueCiphertext: { + type: String, + required: true, + }, + secretValueIV: { + type: String, // symmetric + required: true, + }, + secretValueTag: { + type: String, // symmetric + required: true, + }, + algorithm: { + // the encryption algorithm used + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true, + default: ALGORITHM_AES_256_GCM, + }, + keyEncoding: { + type: String, + enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], + required: true, + default: ENCODING_SCHEME_UTF8, + }, + folder: { + type: String, + required: true, + }, + tags: { + ref: 'Tag', + type: [Schema.Types.ObjectId], + default: [] + }, + }, + { + timestamps: true, + } ); -const SecretVersion = model('SecretVersion', secretVersionSchema); +const SecretVersion = model( + "SecretVersion", + secretVersionSchema +); -export default SecretVersion; \ No newline at end of file +export default SecretVersion; diff --git a/backend/src/ee/routes/v1/cloudProducts.ts b/backend/src/ee/routes/v1/cloudProducts.ts new file mode 100644 index 000000000..73af00aca --- /dev/null +++ b/backend/src/ee/routes/v1/cloudProducts.ts @@ -0,0 +1,20 @@ +import express from 'express'; +const router = express.Router(); +import { + requireAuth, + validateRequest +} from '../../../middleware'; +import { query } from 'express-validator'; +import { cloudProductsController } from '../../controllers/v1'; + +router.get( + '/', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + query('billing-cycle').exists().isIn(['monthly', 'yearly']), + validateRequest, + cloudProductsController.getCloudProducts +); + +export default router; \ 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 612715111..7568e45d6 100644 --- a/backend/src/ee/routes/v1/index.ts +++ b/backend/src/ee/routes/v1/index.ts @@ -1,11 +1,15 @@ import secret from './secret'; import secretSnapshot from './secretSnapshot'; +import organizations from './organizations'; import workspace from './workspace'; import action from './action'; +import cloudProducts from './cloudProducts'; export { secret, secretSnapshot, + organizations, workspace, - action + action, + cloudProducts } \ No newline at end of file diff --git a/backend/src/ee/routes/v1/organizations.ts b/backend/src/ee/routes/v1/organizations.ts new file mode 100644 index 000000000..711b5a17f --- /dev/null +++ b/backend/src/ee/routes/v1/organizations.ts @@ -0,0 +1,88 @@ +import express from 'express'; +const router = express.Router(); +import { + requireAuth, + requireOrganizationAuth, + validateRequest +} from '../../../middleware'; +import { param, body, query } from 'express-validator'; +import { organizationsController } from '../../controllers/v1'; +import { + OWNER, ADMIN, MEMBER, ACCEPTED +} from '../../../variables'; + +router.get( + '/:organizationId/plan', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED] + }), + param('organizationId').exists().trim(), + query('workspaceId').optional().isString(), + validateRequest, + organizationsController.getOrganizationPlan +); + +router.patch( + '/:organizationId/plan', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED] + }), + param('organizationId').exists().trim(), + body('productId').exists().isString(), + validateRequest, + organizationsController.updateOrganizationPlan +); + +router.get( + '/:organizationId/billing-details/payment-methods', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED] + }), + param('organizationId').exists().trim(), + validateRequest, + organizationsController.getOrganizationPmtMethods +); + +router.post( + '/:organizationId/billing-details/payment-methods', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED] + }), + param('organizationId').exists().trim(), + body('success_url').exists().isString(), + body('cancel_url').exists().isString(), + validateRequest, + organizationsController.addOrganizationPmtMethod +); + +router.delete( + '/:organizationId/billing-details/payment-methods/:pmtMethodId', + requireAuth({ + acceptedAuthModes: ['jwt', 'apiKey'] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED] + }), + param('organizationId').exists().trim(), + validateRequest, + organizationsController.deleteOrganizationPmtMethod +); + +export default router; \ No newline at end of file diff --git a/backend/src/ee/routes/v1/secret.ts b/backend/src/ee/routes/v1/secret.ts index 8e93919a0..3e956a388 100644 --- a/backend/src/ee/routes/v1/secret.ts +++ b/backend/src/ee/routes/v1/secret.ts @@ -7,7 +7,12 @@ import { } from '../../../middleware'; import { query, param, body } from 'express-validator'; import { secretController } from '../../controllers/v1'; -import { ADMIN, MEMBER } from '../../../variables'; +import { + ADMIN, + MEMBER, + PERMISSION_READ_SECRETS, + PERMISSION_WRITE_SECRETS +} from '../../../variables'; router.get( '/:secretId/secret-versions', @@ -15,7 +20,8 @@ router.get( acceptedAuthModes: ['jwt', 'apiKey'] }), requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_READ_SECRETS] }), param('secretId').exists().trim(), query('offset').exists().isInt(), @@ -30,7 +36,8 @@ router.post( acceptedAuthModes: ['jwt', 'apiKey'] }), requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS] }), param('secretId').exists().trim(), body('version').exists().isInt(), diff --git a/backend/src/ee/routes/v1/secretSnapshot.ts b/backend/src/ee/routes/v1/secretSnapshot.ts index d10da4456..80aa7d1ee 100644 --- a/backend/src/ee/routes/v1/secretSnapshot.ts +++ b/backend/src/ee/routes/v1/secretSnapshot.ts @@ -7,7 +7,7 @@ import { requireAuth, validateRequest } from '../../../middleware'; -import { param, body } from 'express-validator'; +import { param } from 'express-validator'; import { ADMIN, MEMBER } from '../../../variables'; import { secretSnapshotController } from '../../controllers/v1'; diff --git a/backend/src/ee/routes/v1/workspace.ts b/backend/src/ee/routes/v1/workspace.ts index a799d073b..2b840892f 100644 --- a/backend/src/ee/routes/v1/workspace.ts +++ b/backend/src/ee/routes/v1/workspace.ts @@ -1,72 +1,82 @@ -import express from 'express'; +import express from "express"; const router = express.Router(); import { - requireAuth, - requireWorkspaceAuth, - validateRequest -} from '../../../middleware'; -import { param, query, body } from 'express-validator'; -import { ADMIN, MEMBER } from '../../../variables'; -import { workspaceController } from '../../controllers/v1'; + requireAuth, + requireWorkspaceAuth, + validateRequest, +} from "../../../middleware"; +import { param, query, body } from "express-validator"; +import { ADMIN, MEMBER } from "../../../variables"; +import { workspaceController } from "../../controllers/v1"; router.get( - '/:workspaceId/secret-snapshots', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - param('workspaceId').exists().trim(), - query('offset').exists().isInt(), - query('limit').exists().isInt(), - validateRequest, - workspaceController.getWorkspaceSecretSnapshots + "/:workspaceId/secret-snapshots", + requireAuth({ + acceptedAuthModes: ["jwt", "apiKey"], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "params", + }), + param("workspaceId").exists().trim(), + query("environment").isString().exists().trim(), + query("folderId").default("root").isString().trim(), + query("offset").exists().isInt(), + query("limit").exists().isInt(), + validateRequest, + workspaceController.getWorkspaceSecretSnapshots ); router.get( - '/:workspaceId/secret-snapshots/count', - requireAuth({ - acceptedAuthModes: ['jwt'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - param('workspaceId').exists().trim(), - validateRequest, - workspaceController.getWorkspaceSecretSnapshotsCount + "/:workspaceId/secret-snapshots/count", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "params", + }), + param("workspaceId").exists().trim(), + query("environment").isString().exists().trim(), + query("folderId").default("root").isString().trim(), + validateRequest, + workspaceController.getWorkspaceSecretSnapshotsCount ); router.post( - '/:workspaceId/secret-snapshots/rollback', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - param('workspaceId').exists().trim(), - body('version').exists().isInt(), - validateRequest, - workspaceController.rollbackWorkspaceSecretSnapshot + "/:workspaceId/secret-snapshots/rollback", + requireAuth({ + acceptedAuthModes: ["jwt", "apiKey"], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "params", + }), + param("workspaceId").exists().trim(), + body("environment").isString().exists().trim(), + query("folderId").default("root").isString().exists().trim(), + body("version").exists().isInt(), + validateRequest, + workspaceController.rollbackWorkspaceSecretSnapshot ); router.get( - '/:workspaceId/logs', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - param('workspaceId').exists().trim(), - query('offset').exists().isInt(), - query('limit').exists().isInt(), - query('sortBy'), - query('userId'), - query('actionNames'), - validateRequest, - workspaceController.getWorkspaceLogs + "/:workspaceId/logs", + requireAuth({ + acceptedAuthModes: ["jwt", "apiKey"], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "params", + }), + param("workspaceId").exists().trim(), + query("offset").exists().isInt(), + query("limit").exists().isInt(), + query("sortBy"), + query("userId"), + query("actionNames"), + validateRequest, + workspaceController.getWorkspaceLogs ); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/ee/services/EELicenseService.ts b/backend/src/ee/services/EELicenseService.ts index 4bd811340..e8fe9253e 100644 --- a/backend/src/ee/services/EELicenseService.ts +++ b/backend/src/ee/services/EELicenseService.ts @@ -1,12 +1,150 @@ +import * as Sentry from '@sentry/node'; +import NodeCache from 'node-cache'; +import { + getLicenseKey, + getLicenseServerKey, + getLicenseServerUrl +} from '../../config'; +import { + licenseKeyRequest, + licenseServerKeyRequest, + refreshLicenseServerKeyToken, + refreshLicenseKeyToken +} from '../../config/request'; +import { Organization } from '../../models'; +import { OrganizationNotFoundError } from '../../utils/errors'; + +interface FeatureSet { + _id: string | null; + slug: 'starter' | 'team' | 'pro' | 'enterprise' | null; + tier: number; + workspaceLimit: number | null; + workspacesUsed: number; + memberLimit: number | null; + membersUsed: number; + environmentLimit: number | null; + environmentsUsed: number; + secretVersioning: boolean; + pitRecovery: boolean; + rbac: boolean; + customRateLimits: boolean; + customAlerts: boolean; + auditLogs: boolean; + envLimit?: number | null; +} + /** - * Class to handle Enterprise Edition license actions + * Class to handle license/plan configurations: + * - Infisical Cloud: Fetch and cache customer plans in [localFeatureSet] + * - Self-hosted regular: Use default global feature set + * - Self-hosted enterprise: Fetch and update global feature set */ class EELicenseService { - private readonly _isLicenseValid: boolean; + private readonly _isLicenseValid: boolean; // TODO: deprecate + + public instanceType: 'self-hosted' | 'enterprise-self-hosted' | 'cloud' = 'self-hosted'; + + public globalFeatureSet: FeatureSet = { + _id: null, + slug: null, + tier: -1, + workspaceLimit: null, + workspacesUsed: 0, + memberLimit: null, + membersUsed: 0, + environmentLimit: null, + environmentsUsed: 0, + secretVersioning: true, + pitRecovery: true, + rbac: true, + customRateLimits: true, + customAlerts: true, + auditLogs: false, + envLimit: null + } + + public localFeatureSet: NodeCache; - constructor(licenseKey: string) { + constructor() { this._isLicenseValid = true; + this.localFeatureSet = new NodeCache({ + stdTTL: 300 + }); + } + + public async getPlan(organizationId: string, workspaceId?: string): Promise { + try { + if (this.instanceType === 'cloud') { + const cachedPlan = this.localFeatureSet.get(`${organizationId}-${workspaceId ?? ''}`); + if (cachedPlan) { + return cachedPlan; + } + + const organization = await Organization.findById(organizationId); + if (!organization) throw OrganizationNotFoundError(); + + let url = `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`; + + if (workspaceId) { + url += `?workspaceId=${workspaceId}`; + } + + const { data: { currentPlan } } = await licenseServerKeyRequest.get(url); + + // cache fetched plan for organization + this.localFeatureSet.set(`${organizationId}-${workspaceId ?? ''}`, currentPlan); + + return currentPlan; + } + } catch (err) { + return this.globalFeatureSet; + } + + return this.globalFeatureSet; + } + + public async refreshPlan(organizationId: string, workspaceId?: string) { + if (this.instanceType === 'cloud') { + this.localFeatureSet.del(`${organizationId}-${workspaceId ?? ''}`); + await this.getPlan(organizationId, workspaceId); + } + } + + public async initGlobalFeatureSet() { + const licenseServerKey = await getLicenseServerKey(); + const licenseKey = await getLicenseKey(); + + try { + if (licenseServerKey) { + // license server key is present -> validate it + const token = await refreshLicenseServerKeyToken() + + if (token) { + this.instanceType = 'cloud'; + } + + return; + } + + if (licenseKey) { + // license key is present -> validate it + const token = await refreshLicenseKeyToken(); + + if (token) { + const { data: { currentPlan } } = await licenseKeyRequest.get( + `${await getLicenseServerUrl()}/api/license/v1/plan` + ); + + this.globalFeatureSet = currentPlan; + this.instanceType = 'enterprise-self-hosted'; + } + } + } catch (err) { + // case: self-hosted free + Sentry.setUser(null); + Sentry.captureException(err); + } } public get isLicenseValid(): boolean { @@ -14,4 +152,4 @@ class EELicenseService { } } -export default new EELicenseService('N/A'); \ No newline at end of file +export default new EELicenseService(); diff --git a/backend/src/ee/services/EELogService.ts b/backend/src/ee/services/EELogService.ts index bbe03e09e..81d26765f 100644 --- a/backend/src/ee/services/EELogService.ts +++ b/backend/src/ee/services/EELogService.ts @@ -26,12 +26,16 @@ class EELogService { */ static async createLog({ userId, + serviceAccountId, + serviceTokenDataId, workspaceId, actions, channel, ipAddress }: { - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId?: Types.ObjectId; actions: IAction[]; channel: string; @@ -40,6 +44,8 @@ class EELogService { if (!EELicenseService.isLicenseValid) return null; return await createLogHelper({ userId, + serviceAccountId, + serviceTokenDataId, workspaceId, actions, channel, @@ -59,17 +65,23 @@ class EELogService { static async createAction({ name, userId, + serviceAccountId, + serviceTokenDataId, workspaceId, secretIds }: { name: string; - userId: Types.ObjectId; + userId?: Types.ObjectId; + serviceAccountId?: Types.ObjectId; + serviceTokenDataId?: Types.ObjectId; workspaceId?: Types.ObjectId; secretIds?: Types.ObjectId[]; }) { return await createActionHelper({ name, userId, + serviceAccountId, + serviceTokenDataId, workspaceId, secretIds }); diff --git a/backend/src/ee/services/EESecretService.ts b/backend/src/ee/services/EESecretService.ts index cea614c96..a0803dd36 100644 --- a/backend/src/ee/services/EESecretService.ts +++ b/backend/src/ee/services/EESecretService.ts @@ -1,10 +1,9 @@ import { Types } from 'mongoose'; import { ISecretVersion } from '../models'; -import { - takeSecretSnapshotHelper, - addSecretVersionsHelper, - markDeletedSecretVersionsHelper, - initSecretVersioningHelper +import { + takeSecretSnapshotHelper, + addSecretVersionsHelper, + markDeletedSecretVersionsHelper, } from '../helpers/secret'; import EELicenseService from './EELicenseService'; @@ -12,67 +11,65 @@ import EELicenseService from './EELicenseService'; * Class to handle Enterprise Edition secret actions */ class EESecretService { - - /** - * Save a secret snapshot that is a copy of the current state of secrets in workspace with id - * [workspaceId] under a new snapshot with incremented version under the - * SecretSnapshot collection. - * Requires a valid license key [licenseKey] - * @param {Object} obj - * @param {String} obj.workspaceId - * @returns {SecretSnapshot} secretSnapshot - new secret snpashot - */ - static async takeSecretSnapshot({ - workspaceId - }: { - workspaceId: string; - }) { - if (!EELicenseService.isLicenseValid) return; - return await takeSecretSnapshotHelper({ workspaceId }); - } - - /** - * Add secret versions [secretVersions] to the SecretVersion collection. - * @param {Object} obj - * @param {Object[]} obj.secretVersions - * @returns {SecretVersion[]} newSecretVersions - new secret versions - */ - static async addSecretVersions({ - secretVersions - }: { - secretVersions: ISecretVersion[]; - }) { - if (!EELicenseService.isLicenseValid) return; - return await addSecretVersionsHelper({ - secretVersions - }); - } + /** + * Save a secret snapshot that is a copy of the current state of secrets in workspace with id + * [workspaceId] under a new snapshot with incremented version under the + * SecretSnapshot collection. + * Requires a valid license key [licenseKey] + * @param {Object} obj + * @param {String} obj.workspaceId + * @returns {SecretSnapshot} secretSnapshot - new secret snpashot + */ + static async takeSecretSnapshot({ + workspaceId, + environment, + folderId, + }: { + workspaceId: Types.ObjectId; + environment: string; + folderId?: string; + }) { + if (!EELicenseService.isLicenseValid) return; + return await takeSecretSnapshotHelper({ + workspaceId, + environment, + folderId, + }); + } - /** - * Mark secret versions associated with secrets with ids [secretIds] - * as deleted. - * @param {Object} obj - * @param {ObjectId[]} obj.secretIds - secret ids - */ - static async markDeletedSecretVersions({ - secretIds - }: { - secretIds: Types.ObjectId[]; - }) { - if (!EELicenseService.isLicenseValid) return; - await markDeletedSecretVersionsHelper({ - secretIds - }); - } - - /** - * Initialize secret versioning by setting previously unversioned - * secrets to version 1 and begin populating secret versions. - */ - static async initSecretVersioning() { - if (!EELicenseService.isLicenseValid) return; - await initSecretVersioningHelper(); - } + /** + * Add secret versions [secretVersions] to the SecretVersion collection. + * @param {Object} obj + * @param {Object[]} obj.secretVersions + * @returns {SecretVersion[]} newSecretVersions - new secret versions + */ + static async addSecretVersions({ + secretVersions, + }: { + secretVersions: ISecretVersion[]; + }) { + if (!EELicenseService.isLicenseValid) return; + return await addSecretVersionsHelper({ + secretVersions, + }); + } + + /** + * Mark secret versions associated with secrets with ids [secretIds] + * as deleted. + * @param {Object} obj + * @param {ObjectId[]} obj.secretIds - secret ids + */ + static async markDeletedSecretVersions({ + secretIds, + }: { + secretIds: Types.ObjectId[]; + }) { + if (!EELicenseService.isLicenseValid) return; + await markDeletedSecretVersionsHelper({ + secretIds, + }); + } } -export default EESecretService; \ No newline at end of file +export default EESecretService; diff --git a/backend/src/events/secret.ts b/backend/src/events/secret.ts index 479255a31..6007dd682 100644 --- a/backend/src/events/secret.ts +++ b/backend/src/events/secret.ts @@ -1,3 +1,4 @@ +import { Types } from 'mongoose'; import { EVENT_PUSH_SECRETS, EVENT_PULL_SECRETS @@ -22,13 +23,16 @@ interface PushSecret { * @returns */ const eventPushSecrets = ({ - workspaceId + workspaceId, + environment }: { - workspaceId: string; + workspaceId: Types.ObjectId; + environment?: string; }) => { return ({ name: EVENT_PUSH_SECRETS, workspaceId, + environment, payload: { } diff --git a/backend/src/helpers/auth.ts b/backend/src/helpers/auth.ts index a08dcf2cc..ce61f3650 100644 --- a/backend/src/helpers/auth.ts +++ b/backend/src/helpers/auth.ts @@ -1,15 +1,19 @@ -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import jwt from 'jsonwebtoken'; import bcrypt from 'bcrypt'; import { IUser, User, ServiceTokenData, - APIKeyData + ServiceAccount, + APIKeyData, + TokenVersion, + ITokenVersion } from '../models'; import { AccountNotFoundError, ServiceTokenDataNotFoundError, + ServiceAccountNotFoundError, APIKeyDataNotFoundError, UnauthorizedRequestError, BadRequestError @@ -17,27 +21,33 @@ import { import { getJwtAuthLifetime, getJwtAuthSecret, + getJwtProviderAuthSecret, getJwtRefreshLifetime, getJwtRefreshSecret } from '../config'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; /** * * @param {Object} obj * @param {Object} obj.headers - HTTP request headers object */ -const validateAuthMode = ({ +export const validateAuthMode = ({ headers, acceptedAuthModes }: { headers: { [key: string]: string | string[] | undefined }, acceptedAuthModes: string[] }) => { - // TODO: refactor middleware const apiKey = headers['x-api-key']; const authHeader = headers['authorization']; - let authTokenType, authTokenValue; + let authMode, authTokenValue; if (apiKey === undefined && authHeader === undefined) { // case: no auth or X-API-KEY header present throw BadRequestError({ message: 'Missing Authorization or X-API-KEY in request header.' }); @@ -45,7 +55,7 @@ const validateAuthMode = ({ if (typeof apiKey === 'string') { // case: treat request authentication type as via X-API-KEY (i.e. API Key) - authTokenType = 'apiKey'; + authMode = AUTH_MODE_API_KEY; authTokenValue = apiKey; } @@ -61,20 +71,24 @@ const validateAuthMode = ({ switch (tokenValue.split('.', 1)[0]) { case 'st': - authTokenType = 'serviceToken'; + authMode = AUTH_MODE_SERVICE_TOKEN; + break; + case 'sa': + authMode = AUTH_MODE_SERVICE_ACCOUNT; break; default: - authTokenType = 'jwt'; + authMode = AUTH_MODE_JWT; } + authTokenValue = tokenValue; } - if (!authTokenType || !authTokenValue) throw BadRequestError({ message: 'Missing valid Authorization or X-API-KEY in request header.' }); + if (!authMode || !authTokenValue) throw BadRequestError({ message: 'Missing valid Authorization or X-API-KEY in request header.' }); - if (!acceptedAuthModes.includes(authTokenType)) throw BadRequestError({ message: 'The provided authentication type is not supported.' }); + if (!acceptedAuthModes.includes(authMode)) throw BadRequestError({ message: 'The provided authentication type is not supported.' }); return ({ - authTokenType, + authMode, authTokenValue }); } @@ -85,32 +99,42 @@ const validateAuthMode = ({ * @param {String} obj.authTokenValue - JWT token value * @returns {User} user - user corresponding to JWT token */ -const getAuthUserPayload = async ({ +export const getAuthUserPayload = async ({ authTokenValue }: { authTokenValue: string; }) => { - let user; - try { - const decodedToken = ( - jwt.verify(authTokenValue, getJwtAuthSecret()) - ); + const decodedToken = ( + jwt.verify(authTokenValue, await getJwtAuthSecret()) + ); - user = await User.findOne({ - _id: decodedToken.userId - }).select('+publicKey'); + const user = await User.findOne({ + _id: new Types.ObjectId(decodedToken.userId) + }).select('+publicKey +accessVersion'); - if (!user) throw AccountNotFoundError({ message: 'Failed to find User' }); + if (!user) throw AccountNotFoundError({ message: 'Failed to find user' }); - if (!user?.publicKey) throw UnauthorizedRequestError({ message: 'Failed to authenticate User with partially set up account' }); + if (!user?.publicKey) throw UnauthorizedRequestError({ message: 'Failed to authenticate user with partially set up account' }); - } catch (err) { - throw UnauthorizedRequestError({ - message: 'Failed to authenticate JWT token' - }); - } + const tokenVersion = await TokenVersion.findOneAndUpdate({ + _id: new Types.ObjectId(decodedToken.tokenVersionId), + user: user._id + }, { + lastUsed: new Date() + }); + + if (!tokenVersion) throw UnauthorizedRequestError({ + message: 'Failed to validate access token' + }); + + if (decodedToken.accessVersion !== tokenVersion.accessVersion) throw UnauthorizedRequestError({ + message: 'Failed to validate access token' + }); - return user; + return ({ + user, + tokenVersionId: tokenVersion._id + }); } /** @@ -119,88 +143,124 @@ const getAuthUserPayload = async ({ * @param {String} obj.authTokenValue - service token value * @returns {ServiceTokenData} serviceTokenData - service token data */ -const getAuthSTDPayload = async ({ +export const getAuthSTDPayload = async ({ authTokenValue }: { authTokenValue: string; }) => { - let serviceTokenData; - try { - const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); + const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); - // TODO: optimize double query - serviceTokenData = await ServiceTokenData - .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt'); + let serviceTokenData = await ServiceTokenData + .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt'); - if (!serviceTokenData) { - throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); - } else if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) { - // case: service token expired - await ServiceTokenData.findByIdAndDelete(serviceTokenData._id); - throw UnauthorizedRequestError({ - message: 'Failed to authenticate expired service token' - }); - } - - const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash); - if (!isMatch) throw UnauthorizedRequestError({ - message: 'Failed to authenticate service token' - }); - - serviceTokenData = await ServiceTokenData - .findById(TOKEN_IDENTIFIER) - .select('+encryptedKey +iv +tag') - .populate<{user: IUser}>('user'); - - if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); - - } catch (err) { + if (!serviceTokenData) { + throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); + } else if (serviceTokenData?.expiresAt && new Date(serviceTokenData.expiresAt) < new Date()) { + // case: service token expired + await ServiceTokenData.findByIdAndDelete(serviceTokenData._id); throw UnauthorizedRequestError({ - message: 'Failed to authenticate service token' + message: 'Failed to authenticate expired service token' }); } + const isMatch = await bcrypt.compare(TOKEN_SECRET, serviceTokenData.secretHash); + if (!isMatch) throw UnauthorizedRequestError({ + message: 'Failed to authenticate service token' + }); + + serviceTokenData = await ServiceTokenData + .findOneAndUpdate({ + _id: new Types.ObjectId(TOKEN_IDENTIFIER) + }, { + lastUsed: new Date() + }, { + new: true + }) + .select('+encryptedKey +iv +tag'); + + if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ message: 'Failed to find service token data' }); + return serviceTokenData; } +/** + * Return service account access key payload + * @param {Object} obj + * @param {String} obj.authTokenValue - service account access token value + * @returns {ServiceAccount} serviceAccount + */ +export const getAuthSAAKPayload = async ({ + authTokenValue +}: { + authTokenValue: string; +}) => { + const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); + + const serviceAccount = await ServiceAccount.findById( + Buffer.from(TOKEN_IDENTIFIER, 'base64').toString('hex') + ).select('+secretHash'); + + if (!serviceAccount) { + throw ServiceAccountNotFoundError({ message: 'Failed to find service account' }); + } + + const result = await bcrypt.compare(TOKEN_SECRET, serviceAccount.secretHash); + if (!result) throw UnauthorizedRequestError({ + message: 'Failed to authenticate service account access key' + }); + + return serviceAccount; +} + /** * Return API key data payload corresponding to API key [authTokenValue] * @param {Object} obj * @param {String} obj.authTokenValue - API key value * @returns {APIKeyData} apiKeyData - API key data */ -const getAuthAPIKeyPayload = async ({ +export const getAuthAPIKeyPayload = async ({ authTokenValue }: { authTokenValue: string; }) => { - let user; - try { - const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); + const [_, TOKEN_IDENTIFIER, TOKEN_SECRET] = <[string, string, string]>authTokenValue.split('.', 3); - const apiKeyData = await APIKeyData - .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt') - .populate('user', '+publicKey'); + let apiKeyData = await APIKeyData + .findById(TOKEN_IDENTIFIER, '+secretHash +expiresAt') + .populate<{ user: IUser }>('user', '+publicKey'); - if (!apiKeyData) { - throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' }); - } else if (apiKeyData?.expiresAt && new Date(apiKeyData.expiresAt) < new Date()) { - // case: API key expired - await APIKeyData.findByIdAndDelete(apiKeyData._id); - throw UnauthorizedRequestError({ - message: 'Failed to authenticate expired API key' - }); - } - - const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKeyData.secretHash); - if (!isMatch) throw UnauthorizedRequestError({ - message: 'Failed to authenticate API key' - }); - - user = apiKeyData.user; - } catch (err) { + if (!apiKeyData) { + throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' }); + } else if (apiKeyData?.expiresAt && new Date(apiKeyData.expiresAt) < new Date()) { + // case: API key expired + await APIKeyData.findByIdAndDelete(apiKeyData._id); throw UnauthorizedRequestError({ - message: 'Failed to authenticate API key' + message: 'Failed to authenticate expired API key' + }); + } + + const isMatch = await bcrypt.compare(TOKEN_SECRET, apiKeyData.secretHash); + if (!isMatch) throw UnauthorizedRequestError({ + message: 'Failed to authenticate API key' + }); + + apiKeyData = await APIKeyData.findOneAndUpdate({ + _id: new Types.ObjectId(TOKEN_IDENTIFIER) + }, { + lastUsed: new Date() + }, { + new: true + }); + + if (!apiKeyData) { + throw APIKeyDataNotFoundError({ message: 'Failed to find API key data' }); + } + + const user = await User.findById(apiKeyData.user).select('+publicKey'); + + if (!user) { + throw AccountNotFoundError({ + message: 'Failed to find user' }); } @@ -215,32 +275,58 @@ const getAuthAPIKeyPayload = async ({ * @return {String} obj.token - issued JWT token * @return {String} obj.refreshToken - issued refresh token */ -const issueAuthTokens = async ({ userId }: { userId: string }) => { - let token: string; - let refreshToken: string; - try { - // issue tokens - token = createToken({ - payload: { - userId - }, - expiresIn: getJwtAuthLifetime(), - secret: getJwtAuthSecret() - }); +export const issueAuthTokens = async ({ + userId, + ip, + userAgent +}: { + userId: Types.ObjectId; + ip: string; + userAgent: string; +}) => { + let tokenVersion: ITokenVersion | null; - refreshToken = createToken({ - payload: { - userId - }, - expiresIn: getJwtRefreshLifetime(), - secret: getJwtRefreshSecret() - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to issue tokens'); + // continue with (session) token version matching existing ip and user agent + tokenVersion = await TokenVersion.findOne({ + user: userId, + ip, + userAgent + }); + + if (!tokenVersion) { + // case: no existing ip and user agent exists + // -> create new (session) token version for ip and user agent + tokenVersion = await new TokenVersion({ + user: userId, + refreshVersion: 0, + accessVersion: 0, + ip, + userAgent, + lastUsed: new Date() + }).save(); } + // issue tokens + const token = createToken({ + payload: { + userId, + tokenVersionId: tokenVersion._id.toString(), + accessVersion: tokenVersion.accessVersion + }, + expiresIn: await getJwtAuthLifetime(), + secret: await getJwtAuthSecret() + }); + + const refreshToken = createToken({ + payload: { + userId, + tokenVersionId: tokenVersion._id.toString(), + refreshVersion: tokenVersion.refreshVersion + }, + expiresIn: await getJwtRefreshLifetime(), + secret: await getJwtRefreshSecret() + }); + return { token, refreshToken @@ -252,20 +338,17 @@ const issueAuthTokens = async ({ userId }: { userId: string }) => { * @param {Object} obj * @param {String} obj.userId - id of user whose tokens are cleared. */ -const clearTokens = async ({ userId }: { userId: string }): Promise => { - try { - // increment refreshVersion on user by 1 - User.findOneAndUpdate({ - _id: userId - }, { - $inc: { - refreshVersion: 1 - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - } +export const clearTokens = async (tokenVersionId: Types.ObjectId): Promise => { + // increment refreshVersion on user by 1 + + await TokenVersion.findOneAndUpdate({ + _id: tokenVersionId + }, { + $inc: { + refreshVersion: 1, + accessVersion: 1 + } + }); }; /** @@ -276,7 +359,7 @@ const clearTokens = async ({ userId }: { userId: string }): Promise => { * @param {String} obj.secret - (JWT) secret such as [JWT_AUTH_SECRET] * @param {String} obj.expiresIn - string describing time span such as '10h' or '7d' */ -const createToken = ({ +export const createToken = ({ payload, expiresIn, secret @@ -285,23 +368,32 @@ const createToken = ({ expiresIn: string | number; secret: string; }) => { - try { - return jwt.sign(payload, secret, { - expiresIn - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create a token'); - } + return jwt.sign(payload, secret, { + expiresIn + }); }; -export { - validateAuthMode, - getAuthUserPayload, - getAuthSTDPayload, - getAuthAPIKeyPayload, - createToken, - issueAuthTokens, - clearTokens -}; +export const validateProviderAuthToken = async ({ + email, + user, + providerAuthToken, +}: { + email: string; + user: IUser, + providerAuthToken?: string; +}) => { + if (!providerAuthToken) { + throw new Error('Invalid authentication request.'); + } + + const decodedToken = ( + jwt.verify(providerAuthToken, await getJwtProviderAuthSecret()) + ); + + if ( + decodedToken.authProvider !== user.authProvider || + decodedToken.email !== email + ) { + throw new Error('Invalid authentication credentials.') + } +} \ No newline at end of file diff --git a/backend/src/helpers/bot.ts b/backend/src/helpers/bot.ts index 5cfbeebf5..439f7c531 100644 --- a/backend/src/helpers/bot.ts +++ b/backend/src/helpers/bot.ts @@ -1,57 +1,101 @@ -import * as Sentry from '@sentry/node'; +import { Types } from "mongoose"; import { - Bot, - BotKey, - Secret, - ISecret, - IUser -} from '../models'; -import { - generateKeyPair, - encryptSymmetric, - decryptSymmetric, - decryptAsymmetric + Bot, + BotKey, + Secret, + ISecret, + IUser +} from "../models"; +import { + generateKeyPair, + encryptSymmetric128BitHexKeyUTF8, + decryptSymmetric128BitHexKeyUTF8, + decryptAsymmetric } from '../utils/crypto'; -import { SECRET_SHARED } from '../variables'; -import { getEncryptionKey } from '../config'; +import { + SECRET_SHARED, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 +} from "../variables"; +import { + getEncryptionKey, + getRootEncryptionKey, + client +} from "../config"; +import { InternalServerError } from "../utils/errors"; /** * Create an inactive bot with name [name] for workspace with id [workspaceId] - * @param {Object} obj + * @param {Object} obj * @param {String} obj.name - name of bot * @param {String} obj.workspaceId - id of workspace that bot belongs to */ -const createBot = async ({ - name, - workspaceId, +export const createBot = async ({ + name, + workspaceId, }: { - name: string; - workspaceId: string; + name: string; + workspaceId: Types.ObjectId; }) => { - let bot; - try { - const { publicKey, privateKey } = generateKeyPair(); - const { ciphertext, iv, tag } = encryptSymmetric({ - plaintext: privateKey, - key: getEncryptionKey() - }); + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const { publicKey, privateKey } = generateKeyPair(); + + if (rootEncryptionKey) { + const { + ciphertext, + iv, + tag + } = client.encryptSymmetric(privateKey, rootEncryptionKey); - bot = await new Bot({ - name, - workspace: workspaceId, - isActive: false, - publicKey, - encryptedPrivateKey: ciphertext, - iv, - tag - }).save(); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create bot'); - } - - return bot; + return await new Bot({ + name, + workspace: workspaceId, + isActive: false, + publicKey, + encryptedPrivateKey: ciphertext, + iv, + tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64 + }).save(); + + } else if (encryptionKey) { + const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: privateKey, + key: await getEncryptionKey(), + }); + + return await new Bot({ + name, + workspace: workspaceId, + isActive: false, + publicKey, + encryptedPrivateKey: ciphertext, + iv, + tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }).save(); + } + + throw InternalServerError({ + message: 'Failed to create new bot due to missing encryption key' + }); +}; + +/** + * Return whether or not workspace with id [workspaceId] is end-to-end encrypted + * @param {Types.ObjectId} workspaceId - id of workspace to check + */ +export const getIsWorkspaceE2EEHelper = async (workspaceId: Types.ObjectId) => { + const botKey = await BotKey.exists({ + workspace: workspaceId + }); + + return botKey ? false : true; } /** @@ -61,126 +105,126 @@ const createBot = async ({ * @param {String} obj.workspaceId - id of workspace * @param {String} obj.environment - environment */ -const getSecretsHelper = async ({ - workspaceId, - environment +export const getSecretsBotHelper = async ({ + workspaceId, + environment, }: { - workspaceId: string; - environment: string; + workspaceId: Types.ObjectId; + environment: string; }) => { - const content = {} as any; - try { - const key = await getKey({ workspaceId }); - const secrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_SHARED - }); - - secrets.forEach((secret: ISecret) => { - const secretKey = decryptSymmetric({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - key - }); + const content = {} as any; + const key = await getKey({ workspaceId: workspaceId }); + const secrets = await Secret.find({ + workspace: workspaceId, + environment, + type: SECRET_SHARED, + }); - const secretValue = decryptSymmetric({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - key - }); + secrets.forEach((secret: ISecret) => { + const secretKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretKeyCiphertext, + iv: secret.secretKeyIV, + tag: secret.secretKeyTag, + key, + }); - content[secretKey] = secretValue; - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get secrets'); - } + const secretValue = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretValueCiphertext, + iv: secret.secretValueIV, + tag: secret.secretValueTag, + key, + }); - return content; -} + content[secretKey] = secretValue; + }); + + return content; +}; /** - * Return bot's copy of the workspace key for workspace + * Return bot's copy of the workspace key for workspace * with id [workspaceId] * @param {Object} obj * @param {String} obj.workspaceId - id of workspace * @returns {String} key - decrypted workspace key */ -const getKey = async ({ workspaceId }: { workspaceId: string }) => { - let key; - try { - const botKey = await BotKey.findOne({ - workspace: workspaceId - }).populate<{ sender: IUser }>('sender', 'publicKey'); - - if (!botKey) throw new Error('Failed to find bot key'); - - const bot = await Bot.findOne({ - workspace: workspaceId - }).select('+encryptedPrivateKey +iv +tag'); - - if (!bot) throw new Error('Failed to find bot'); - if (!bot.isActive) throw new Error('Bot is not active'); - - const privateKeyBot = decryptSymmetric({ - ciphertext: bot.encryptedPrivateKey, - iv: bot.iv, - tag: bot.tag, - key: getEncryptionKey() - }); - - key = decryptAsymmetric({ - ciphertext: botKey.encryptedKey, - nonce: botKey.nonce, - publicKey: botKey.sender.publicKey as string, - privateKey: privateKeyBot - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get workspace key'); - } +export const getKey = async ({ workspaceId }: { workspaceId: Types.ObjectId }) => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const botKey = await BotKey.findOne({ + workspace: workspaceId, + }) + .populate<{ sender: IUser }>("sender", "publicKey"); + + if (!botKey) throw new Error("Failed to find bot key"); + + const bot = await Bot.findOne({ + workspace: workspaceId, + }).select("+encryptedPrivateKey +iv +tag +algorithm +keyEncoding"); + + if (!bot) throw new Error("Failed to find bot"); + if (!bot.isActive) throw new Error("Bot is not active"); + + if (rootEncryptionKey && bot.keyEncoding === ENCODING_SCHEME_BASE64) { + // case: encoding scheme is base64 + const privateKeyBot = client.decryptSymmetric(bot.encryptedPrivateKey, rootEncryptionKey, bot.iv, bot.tag); + + return decryptAsymmetric({ + ciphertext: botKey.encryptedKey, + nonce: botKey.nonce, + publicKey: botKey.sender.publicKey as string, + privateKey: privateKeyBot, + }); + } else if (encryptionKey && bot.keyEncoding === ENCODING_SCHEME_UTF8) { - return key; -} + // case: encoding scheme is utf8 + const privateKeyBot = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: bot.encryptedPrivateKey, + iv: bot.iv, + tag: bot.tag, + key: encryptionKey + }); + + return decryptAsymmetric({ + ciphertext: botKey.encryptedKey, + nonce: botKey.nonce, + publicKey: botKey.sender.publicKey as string, + privateKey: privateKeyBot, + }); + } + + throw InternalServerError({ + message: "Failed to obtain bot's copy of workspace key needed for bot operations" + }); +}; /** * Return symmetrically encrypted [plaintext] using the - * key for workspace with id [workspaceId] + * key for workspace with id [workspaceId] * @param {Object} obj1 * @param {String} obj1.workspaceId - id of workspace * @param {String} obj1.plaintext - plaintext to encrypt */ -const encryptSymmetricHelper = async ({ - workspaceId, - plaintext +export const encryptSymmetricHelper = async ({ + workspaceId, + plaintext, }: { - workspaceId: string; - plaintext: string; + workspaceId: Types.ObjectId; + plaintext: string; }) => { - - try { - const key = await getKey({ workspaceId }); - const { ciphertext, iv, tag } = encryptSymmetric({ - plaintext, - key - }); - - return ({ - ciphertext, - iv, - tag - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform symmetric encryption with bot'); - } -} + const key = await getKey({ workspaceId: workspaceId }); + const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ + plaintext, + key, + }); + + return { + ciphertext, + iv, + tag, + }; +}; /** * Return symmetrically decrypted [ciphertext] using the * key for workspace with id [workspaceId] @@ -190,40 +234,24 @@ const encryptSymmetricHelper = async ({ * @param {String} obj.iv - iv * @param {String} obj.tag - tag */ -const decryptSymmetricHelper = async ({ - workspaceId, +export const decryptSymmetricHelper = async ({ + workspaceId, + ciphertext, + iv, + tag, +}: { + workspaceId: Types.ObjectId; + ciphertext: string; + iv: string; + tag: string; +}) => { + const key = await getKey({ workspaceId: workspaceId }); + const plaintext = decryptSymmetric128BitHexKeyUTF8({ ciphertext, iv, - tag -}: { - workspaceId: string; - ciphertext: string; - iv: string; - tag: string; -}) => { - let plaintext; - try { - const key = await getKey({ workspaceId }); - const plaintext = decryptSymmetric({ - ciphertext, - iv, - tag, - key - }); - - return plaintext; - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform symmetric decryption with bot'); - } - - return plaintext; -} + tag, + key, + }); -export { - createBot, - getSecretsHelper, - encryptSymmetricHelper, - decryptSymmetricHelper -} \ No newline at end of file + return plaintext; +}; \ No newline at end of file diff --git a/backend/src/helpers/database.ts b/backend/src/helpers/database.ts index 9d128ea47..b9284bbf8 100644 --- a/backend/src/helpers/database.ts +++ b/backend/src/helpers/database.ts @@ -1,5 +1,4 @@ import mongoose from 'mongoose'; -import { EESecretService } from '../ee/services'; import { getLogger } from '../utils/logger'; /** @@ -8,7 +7,7 @@ import { getLogger } from '../utils/logger'; * @param {String} obj.mongoURL - mongo connection string * @returns */ -const initDatabaseHelper = async ({ +export const initDatabaseHelper = async ({ mongoURL }: { mongoURL: string; @@ -19,11 +18,10 @@ const initDatabaseHelper = async ({ // allow empty strings to pass the required validator mongoose.Schema.Types.String.checkRequired(v => typeof v === 'string'); - getLogger("database").info("Database connection established"); - - await EESecretService.initSecretVersioning(); + (await getLogger("database")).info("Database connection established"); + } catch (err) { - getLogger("database").error(`Unable to establish Database connection due to the error.\n${err}`); + (await getLogger("database")).error(`Unable to establish Database connection due to the error.\n${err}`); } return mongoose.connection; @@ -32,7 +30,7 @@ const initDatabaseHelper = async ({ /** * Close database conection */ -const closeDatabaseHelper = async () => { +export const closeDatabaseHelper = async () => { return Promise.all([ new Promise((resolve) => { if (mongoose.connection && mongoose.connection.readyState == 1) { @@ -43,9 +41,4 @@ const closeDatabaseHelper = async () => { } }) ]); -} - -export { - initDatabaseHelper, - closeDatabaseHelper } \ No newline at end of file diff --git a/backend/src/helpers/event.ts b/backend/src/helpers/event.ts index 4128752e5..47c243749 100644 --- a/backend/src/helpers/event.ts +++ b/backend/src/helpers/event.ts @@ -1,12 +1,13 @@ -import { Bot, IBot } from '../models'; -import * as Sentry from '@sentry/node'; -import { EVENT_PUSH_SECRETS } from '../variables'; -import { IntegrationService } from '../services'; +import { Types } from "mongoose"; +import { Bot, IBot } from "../models"; +import { EVENT_PUSH_SECRETS } from "../variables"; +import { IntegrationService } from "../services"; interface Event { - name: string; - workspaceId: string; - payload: any; + name: string; + workspaceId: Types.ObjectId; + environment?: string; + payload: any; } /** @@ -17,35 +18,23 @@ interface Event { * @param {String} obj.event.workspaceId - id of workspace that event is part of * @param {Object} obj.event.payload - payload of event (depends on event) */ -const handleEventHelper = async ({ - event -}: { - event: Event; -}) => { - const { workspaceId } = event; - - // TODO: moduralize bot check into separate function - const bot = await Bot.findOne({ - workspace: workspaceId, - isActive: true - }); - - if (!bot) return; - - try { - switch (event.name) { - case EVENT_PUSH_SECRETS: - IntegrationService.syncIntegrations({ - workspaceId - }); - break; - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - } -} +export const handleEventHelper = async ({ event }: { event: Event }) => { + const { workspaceId, environment } = event; -export { - handleEventHelper -} \ No newline at end of file + // TODO: moduralize bot check into separate function + const bot = await Bot.findOne({ + workspace: workspaceId, + isActive: true, + }); + + if (!bot) return; + + switch (event.name) { + case EVENT_PUSH_SECRETS: + IntegrationService.syncIntegrations({ + workspaceId, + environment, + }); + break; + } +}; \ No newline at end of file diff --git a/backend/src/helpers/index.ts b/backend/src/helpers/index.ts new file mode 100644 index 000000000..b9d85f871 --- /dev/null +++ b/backend/src/helpers/index.ts @@ -0,0 +1,17 @@ +export * from './auth'; +export * from './bot'; +export * from './database'; +export * from './event'; +export * from './integration'; +export * from './key'; +export * from './membership'; +export * from './membershipOrg'; +export * from './nodemailer'; +export * from './organization'; +export * from './rateLimiter'; +export * from './secret'; +export * from './secrets'; +export * from './signup'; +export * from './token'; +export * from './user'; +export * from './workspace'; \ No newline at end of file diff --git a/backend/src/helpers/integration.ts b/backend/src/helpers/integration.ts index 27afbb4b1..b6f4b0915 100644 --- a/backend/src/helpers/integration.ts +++ b/backend/src/helpers/integration.ts @@ -1,17 +1,20 @@ -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Bot, Integration, - IntegrationAuth, + IntegrationAuth } from '../models'; import { exchangeCode, exchangeRefresh, syncSecrets } from '../integrations'; import { BotService } from '../services'; import { INTEGRATION_VERCEL, - INTEGRATION_NETLIFY + INTEGRATION_NETLIFY, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8 } from '../variables'; -import { UnauthorizedRequestError } from '../utils/errors'; -import RequestError from '../utils/requestError'; +import { + UnauthorizedRequestError, +} from '../utils/errors'; interface Update { workspace: string; @@ -32,7 +35,7 @@ interface Update { * @param {String} obj.code - code * @returns {IntegrationAuth} integrationAuth - integration auth after OAuth2 code-token exchange */ -const handleOAuthExchangeHelper = async ({ +export const handleOAuthExchangeHelper = async ({ workspaceId, integration, code, @@ -43,66 +46,59 @@ const handleOAuthExchangeHelper = async ({ code: string; environment: string; }) => { - let integrationAuth; - try { - const bot = await Bot.findOne({ - workspace: workspaceId, - isActive: true + const bot = await Bot.findOne({ + workspace: workspaceId, + isActive: true + }); + + if (!bot) throw new Error('Bot must be enabled for OAuth2 code-token exchange'); + + // exchange code for access and refresh tokens + const res = await exchangeCode({ + integration, + code + }); + + const update: Update = { + workspace: workspaceId, + integration + } + + switch (integration) { + case INTEGRATION_VERCEL: + update.teamId = res.teamId; + break; + case INTEGRATION_NETLIFY: + update.accountId = res.accountId; + break; + } + + const integrationAuth = await IntegrationAuth.findOneAndUpdate({ + workspace: workspaceId, + integration + }, update, { + new: true, + upsert: true + }); + + if (res.refreshToken) { + // case: refresh token returned from exchange + // set integration auth refresh token + await setIntegrationAuthRefreshHelper({ + integrationAuthId: integrationAuth._id.toString(), + refreshToken: res.refreshToken }); - - if (!bot) throw new Error('Bot must be enabled for OAuth2 code-token exchange'); - - // exchange code for access and refresh tokens - const res = await exchangeCode({ - integration, - code + } + + if (res.accessToken) { + // case: access token returned from exchange + // set integration auth access token + await setIntegrationAuthAccessHelper({ + integrationAuthId: integrationAuth._id.toString(), + accessId: null, + accessToken: res.accessToken, + accessExpiresAt: res.accessExpiresAt }); - - const update: Update = { - workspace: workspaceId, - integration - } - - switch (integration) { - case INTEGRATION_VERCEL: - update.teamId = res.teamId; - break; - case INTEGRATION_NETLIFY: - update.accountId = res.accountId; - break; - } - - integrationAuth = await IntegrationAuth.findOneAndUpdate({ - workspace: workspaceId, - integration - }, update, { - new: true, - upsert: true - }); - - if (res.refreshToken) { - // case: refresh token returned from exchange - // set integration auth refresh token - await setIntegrationAuthRefreshHelper({ - integrationAuthId: integrationAuth._id.toString(), - refreshToken: res.refreshToken - }); - } - - if (res.accessToken) { - // case: access token returned from exchange - // set integration auth access token - await setIntegrationAuthAccessHelper({ - integrationAuthId: integrationAuth._id.toString(), - accessId: null, - accessToken: res.accessToken, - accessExpiresAt: res.accessExpiresAt - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to handle OAuth2 code-token exchange') } return integrationAuth; @@ -113,49 +109,47 @@ const handleOAuthExchangeHelper = async ({ * @param {Object} obj * @param {Object} obj.workspaceId - id of workspace */ -const syncIntegrationsHelper = async ({ - workspaceId +export const syncIntegrationsHelper = async ({ + workspaceId, + environment }: { - workspaceId: string; + workspaceId: Types.ObjectId; + environment?: string; }) => { - let integrations; - try { - integrations = await Integration.find({ - workspace: workspaceId, - isActive: true, - app: { $ne: null } + 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({ // issue here? + workspaceId: integration.workspace, + environment: integration.environment }); - // 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({ // issue here? - workspaceId: integration.workspace.toString(), - environment: integration.environment - }); + const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth); + if (!integrationAuth) throw new Error('Failed to find integration auth'); + + // get integration auth access token + const access = await getIntegrationAuthAccessHelper({ + integrationAuthId: integration.integrationAuth + }); - const integrationAuth = await IntegrationAuth.findById(integration.integrationAuth); - if (!integrationAuth) throw new Error('Failed to find integration auth'); - - // get integration auth access token - const access = await getIntegrationAuthAccessHelper({ - integrationAuthId: integration.integrationAuth.toString() - }); - - // sync secrets to integration - await syncSecrets({ - integration, - integrationAuth, - secrets, - accessId: access.accessId, - accessToken: access.accessToken - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to sync secrets to integrations'); + // sync secrets to integration + await syncSecrets({ + integration, + integrationAuth, + secrets, + accessId: access.accessId === undefined ? null : access.accessId, + accessToken: access.accessToken + }); } } @@ -167,31 +161,19 @@ const syncIntegrationsHelper = async ({ * @param {String} obj.integrationAuthId - id of integration auth * @param {String} refreshToken - decrypted refresh token */ - const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => { - let refreshToken; - - try { - const integrationAuth = await IntegrationAuth - .findById(integrationAuthId) - .select('+refreshCiphertext +refreshIV +refreshTag'); +export const getIntegrationAuthRefreshHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => { + const integrationAuth = await IntegrationAuth + .findById(integrationAuthId) + .select('+refreshCiphertext +refreshIV +refreshTag'); - if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'}); + if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'}); - refreshToken = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - ciphertext: integrationAuth.refreshCiphertext as string, - iv: integrationAuth.refreshIV as string, - tag: integrationAuth.refreshTag as string - }); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - if(err instanceof RequestError) - throw err - else - throw new Error('Failed to get integration refresh token'); - } + const refreshToken = await BotService.decryptSymmetric({ + workspaceId: integrationAuth.workspace, + ciphertext: integrationAuth.refreshCiphertext as string, + iv: integrationAuth.refreshIV as string, + tag: integrationAuth.refreshTag as string + }); return refreshToken; } @@ -204,53 +186,43 @@ const syncIntegrationsHelper = async ({ * @param {String} obj.integrationAuthId - id of integration auth * @returns {String} accessToken - decrypted access token */ -const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: string }) => { +export const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) => { let accessId; let accessToken; - try { - const integrationAuth = await IntegrationAuth - .findById(integrationAuthId) - .select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext +accessIdCiphertext +accessIdIV +accessIdTag'); + const integrationAuth = await IntegrationAuth + .findById(integrationAuthId) + .select('workspace integration +accessCiphertext +accessIV +accessTag +accessExpiresAt + refreshCiphertext +accessIdCiphertext +accessIdIV +accessIdTag'); - if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'}); + if (!integrationAuth) throw UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'}); - accessToken = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - ciphertext: integrationAuth.accessCiphertext as string, - iv: integrationAuth.accessIV as string, - tag: integrationAuth.accessTag as string - }); + accessToken = await BotService.decryptSymmetric({ + workspaceId: integrationAuth.workspace, + ciphertext: integrationAuth.accessCiphertext as string, + iv: integrationAuth.accessIV as string, + tag: integrationAuth.accessTag as string + }); - if (integrationAuth?.accessExpiresAt && integrationAuth?.refreshCiphertext) { - // there is a access token expiration date - // and refresh token to exchange with the OAuth2 server - - if (integrationAuth.accessExpiresAt < new Date()) { - // access token is expired - const refreshToken = await getIntegrationAuthRefreshHelper({ integrationAuthId }); - accessToken = await exchangeRefresh({ - integrationAuth, - refreshToken - }); - } - } + if (integrationAuth?.accessExpiresAt && integrationAuth?.refreshCiphertext) { + // there is a access token expiration date + // and refresh token to exchange with the OAuth2 server - if (integrationAuth?.accessIdCiphertext && integrationAuth?.accessIdIV && integrationAuth?.accessIdTag) { - accessId = await BotService.decryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - ciphertext: integrationAuth.accessIdCiphertext as string, - iv: integrationAuth.accessIdIV as string, - tag: integrationAuth.accessIdTag as string + if (integrationAuth.accessExpiresAt < new Date()) { + // access token is expired + const refreshToken = await getIntegrationAuthRefreshHelper({ integrationAuthId }); + accessToken = await exchangeRefresh({ + integrationAuth, + refreshToken }); } - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - if(err instanceof RequestError) - throw err - else - throw new Error('Failed to get integration access token'); + } + + if (integrationAuth?.accessIdCiphertext && integrationAuth?.accessIdIV && integrationAuth?.accessIdTag) { + accessId = await BotService.decryptSymmetric({ + workspaceId: integrationAuth.workspace, + ciphertext: integrationAuth.accessIdCiphertext as string, + iv: integrationAuth.accessIdIV as string, + tag: integrationAuth.accessIdTag as string + }); } return ({ @@ -267,7 +239,7 @@ const getIntegrationAuthAccessHelper = async ({ integrationAuthId }: { integrati * @param {String} obj.integrationAuthId - id of integration auth * @param {String} obj.refreshToken - refresh token */ -const setIntegrationAuthRefreshHelper = async ({ +export const setIntegrationAuthRefreshHelper = async ({ integrationAuthId, refreshToken }: { @@ -275,32 +247,27 @@ const setIntegrationAuthRefreshHelper = async ({ refreshToken: string; }) => { - let integrationAuth; - try { - integrationAuth = await IntegrationAuth - .findById(integrationAuthId); - - if (!integrationAuth) throw new Error('Failed to find integration auth'); - - const obj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - plaintext: refreshToken - }); - - integrationAuth = await IntegrationAuth.findOneAndUpdate({ - _id: integrationAuthId - }, { - refreshCiphertext: obj.ciphertext, - refreshIV: obj.iv, - refreshTag: obj.tag - }, { - new: true - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to set integration auth refresh token'); - } + let integrationAuth = await IntegrationAuth + .findById(integrationAuthId); + + if (!integrationAuth) throw new Error('Failed to find integration auth'); + + const obj = await BotService.encryptSymmetric({ + workspaceId: integrationAuth.workspace, + plaintext: refreshToken + }); + + integrationAuth = await IntegrationAuth.findOneAndUpdate({ + _id: integrationAuthId + }, { + refreshCiphertext: obj.ciphertext, + refreshIV: obj.iv, + refreshTag: obj.tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }, { + new: true + }); return integrationAuth; } @@ -314,7 +281,7 @@ const setIntegrationAuthRefreshHelper = async ({ * @param {String} obj.accessToken - access token * @param {Date} obj.accessExpiresAt - expiration date of access token */ -const setIntegrationAuthAccessHelper = async ({ +export const setIntegrationAuthAccessHelper = async ({ integrationAuthId, accessId, accessToken, @@ -325,52 +292,38 @@ const setIntegrationAuthAccessHelper = async ({ accessToken: string; accessExpiresAt: Date | undefined; }) => { - let integrationAuth; - try { - integrationAuth = await IntegrationAuth.findById(integrationAuthId); - - if (!integrationAuth) throw new Error('Failed to find integration auth'); - - const encryptedAccessTokenObj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - plaintext: accessToken - }); - - let encryptedAccessIdObj; - if (accessId) { - encryptedAccessIdObj = await BotService.encryptSymmetric({ - workspaceId: integrationAuth.workspace.toString(), - plaintext: accessId - }); - } - - integrationAuth = await IntegrationAuth.findOneAndUpdate({ - _id: integrationAuthId - }, { - accessIdCiphertext: encryptedAccessIdObj?.ciphertext ?? undefined, - accessIdIV: encryptedAccessIdObj?.iv ?? undefined, - accessIdTag: encryptedAccessIdObj?.tag ?? undefined, - accessCiphertext: encryptedAccessTokenObj.ciphertext, - accessIV: encryptedAccessTokenObj.iv, - accessTag: encryptedAccessTokenObj.tag, - accessExpiresAt - }, { - new: true - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to save integration auth access token'); + let integrationAuth = await IntegrationAuth.findById(integrationAuthId); + + if (!integrationAuth) throw new Error('Failed to find integration auth'); + + const encryptedAccessTokenObj = await BotService.encryptSymmetric({ + workspaceId: integrationAuth.workspace, + plaintext: accessToken + }); + + let encryptedAccessIdObj; + if (accessId) { + encryptedAccessIdObj = await BotService.encryptSymmetric({ + workspaceId: integrationAuth.workspace, + plaintext: accessId + }); } + integrationAuth = await IntegrationAuth.findOneAndUpdate({ + _id: integrationAuthId + }, { + accessIdCiphertext: encryptedAccessIdObj?.ciphertext ?? undefined, + accessIdIV: encryptedAccessIdObj?.iv ?? undefined, + accessIdTag: encryptedAccessIdObj?.tag ?? undefined, + accessCiphertext: encryptedAccessTokenObj.ciphertext, + accessIV: encryptedAccessTokenObj.iv, + accessTag: encryptedAccessTokenObj.tag, + accessExpiresAt, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }, { + new: true + }); + return integrationAuth; -} - -export { - handleOAuthExchangeHelper, - syncIntegrationsHelper, - getIntegrationAuthRefreshHelper, - getIntegrationAuthAccessHelper, - setIntegrationAuthRefreshHelper, - setIntegrationAuthAccessHelper } \ No newline at end of file diff --git a/backend/src/helpers/key.ts b/backend/src/helpers/key.ts index 76fdcac3b..afb4f6396 100644 --- a/backend/src/helpers/key.ts +++ b/backend/src/helpers/key.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Key, IKey } from '../models'; interface Key { @@ -18,7 +17,7 @@ interface Key { * @param {String} obj.keys.nonce - nonce for encryption * @param {String} obj.keys.userId - id of receiver user */ -const pushKeys = async ({ +export const pushKeys = async ({ userId, workspaceId, keys @@ -27,36 +26,28 @@ const pushKeys = async ({ workspaceId: string; keys: Key[]; }): Promise => { - try { - // filter out already-inserted keys - const keysSet = new Set( - ( - await Key.find( - { - workspace: workspaceId - }, - 'receiver' - ) - ).map((k: IKey) => k.receiver.toString()) - ); + // filter out already-inserted keys + const keysSet = new Set( + ( + await Key.find( + { + workspace: workspaceId + }, + 'receiver' + ) + ).map((k: IKey) => k.receiver.toString()) + ); - keys = keys.filter((key) => !keysSet.has(key.userId)); + keys = keys.filter((key) => !keysSet.has(key.userId)); - // add new shared keys only - await Key.insertMany( - keys.map((k) => ({ - encryptedKey: k.encryptedKey, - nonce: k.nonce, - sender: userId, - receiver: k.userId, - workspace: workspaceId - })) - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to push access keys'); - } -}; - -export { pushKeys }; + // add new shared keys only + await Key.insertMany( + keys.map((k) => ({ + encryptedKey: k.encryptedKey, + nonce: k.nonce, + sender: userId, + receiver: k.userId, + workspace: workspaceId + })) + ); +}; \ No newline at end of file diff --git a/backend/src/helpers/membership.ts b/backend/src/helpers/membership.ts index 406162a8e..976297512 100644 --- a/backend/src/helpers/membership.ts +++ b/backend/src/helpers/membership.ts @@ -1,5 +1,6 @@ -import * as Sentry from '@sentry/node'; -import { Membership, Key } from '../models'; +import { Types } from "mongoose"; +import { Membership, Key } from "../models"; +import { MembershipNotFoundError, BadRequestError } from "../utils/errors"; /** * Validate that user with id [userId] is a member of workspace with id [workspaceId] @@ -9,54 +10,45 @@ import { Membership, Key } from '../models'; * @param {String} obj.workspaceId - id of workspace * @returns {Membership} membership - membership of user with id [userId] for workspace with id [workspaceId] */ -const validateMembership = async ({ +export const validateMembership = async ({ userId, workspaceId, acceptedRoles, }: { - userId: string; - workspaceId: string; - acceptedRoles: string[]; + userId: Types.ObjectId | string; + workspaceId: Types.ObjectId | string; + acceptedRoles?: Array<"admin" | "member">; }) => { - - let membership; - //TODO: Refactor code to take advantage of using RequestError. It's possible to create new types of errors for more detailed errors - try { - membership = await Membership.findOne({ - user: userId, - workspace: workspaceId - }).populate("workspace"); - - if (!membership) throw new Error('Failed to find membership'); - - if (!acceptedRoles.includes(membership.role)) { - throw new Error('Failed to validate membership role'); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to validate membership'); - } - - return membership; -} + const membership = await Membership.findOne({ + user: userId, + workspace: workspaceId, + }).populate("workspace"); + + if (!membership) { + throw MembershipNotFoundError({ + message: "Failed to find workspace membership", + }); + } + + if (acceptedRoles) { + if (!acceptedRoles.includes(membership.role)) { + throw BadRequestError({ + message: "Failed authorization for membership role", + }); + } + } + + return membership; +}; /** * Return membership matching criteria specified in query [queryObj] * @param {Object} queryObj - query object * @return {Object} membership - membership */ -const findMembership = async (queryObj: any) => { - let membership; - try { - membership = await Membership.findOne(queryObj); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to find membership'); - } - - return membership; +export const findMembership = async (queryObj: any) => { + const membership = await Membership.findOne(queryObj); + return membership; }; /** @@ -67,40 +59,33 @@ const findMembership = async (queryObj: any) => { * @param {String} obj.workspaceId - id of workspace. * @param {String[]} obj.roles - roles of users. */ -const addMemberships = async ({ +export const addMemberships = async ({ userIds, workspaceId, roles }: { - userIds: string[]; - workspaceId: string; - roles: string[]; + userIds: string[]; + workspaceId: string; + roles: string[]; }): Promise => { - try { - const operations = userIds.map((userId, idx) => { - return { - updateOne: { - filter: { - user: userId, - workspace: workspaceId, - role: roles[idx] - }, - update: { - user: userId, - workspace: workspaceId, - role: roles[idx] - }, - upsert: true - } - }; - }); - - await Membership.bulkWrite(operations as any); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to add users to workspace'); - } + const operations = userIds.map((userId, idx) => { + return { + updateOne: { + filter: { + user: userId, + workspace: workspaceId, + role: roles[idx], + }, + update: { + user: userId, + workspace: workspaceId, + role: roles[idx], + }, + upsert: true, + }, + }; + }); + await Membership.bulkWrite(operations as any); }; /** @@ -108,33 +93,19 @@ const addMemberships = async ({ * @param {Object} obj * @param {String} obj.membershipId - id of membership to delete */ -const deleteMembership = async ({ membershipId }: { membershipId: string }) => { - let deletedMembership; - try { - deletedMembership = await Membership.findOneAndDelete({ - _id: membershipId - }); +export const deleteMembership = async ({ membershipId }: { membershipId: string }) => { + const deletedMembership = await Membership.findOneAndDelete({ + _id: membershipId + }); - // delete keys associated with the membership - if (deletedMembership?.user) { - // case: membership had a registered user - await Key.deleteMany({ - receiver: deletedMembership.user, - workspace: deletedMembership.workspace - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to delete membership'); - } + // delete keys associated with the membership + if (deletedMembership?.user) { + // case: membership had a registered user + await Key.deleteMany({ + receiver: deletedMembership.user, + workspace: deletedMembership.workspace, + }); + } return deletedMembership; }; - -export { - validateMembership, - addMemberships, - findMembership, - deleteMembership -}; diff --git a/backend/src/helpers/membershipOrg.ts b/backend/src/helpers/membershipOrg.ts index 4de4be82d..f29f3cec0 100644 --- a/backend/src/helpers/membershipOrg.ts +++ b/backend/src/helpers/membershipOrg.ts @@ -1,40 +1,56 @@ -import * as Sentry from '@sentry/node'; import { Types } from 'mongoose'; -import { MembershipOrg, Workspace, Membership, Key } from '../models'; +import { + MembershipOrg, + Workspace, + Membership, + Key +} from '../models'; +import { + MembershipOrgNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; /** * Validate that user with id [userId] is a member of organization with id [organizationId] * and has at least one of the roles in [acceptedRoles] - * + * @param {Object} obj + * @param {Types.ObjectId} obj.userId + * @param {Types.ObjectId} obj.organizationId + * @param {String[]} obj.acceptedRoles */ -const validateMembership = async ({ +export const validateMembershipOrg = async ({ userId, organizationId, - acceptedRoles + acceptedRoles, + acceptedStatuses }: { - userId: string; - organizationId: string; - acceptedRoles: string[]; + userId: Types.ObjectId; + organizationId: Types.ObjectId; + acceptedRoles?: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses?: Array<'invited' | 'accepted'>; }) => { - let membership; - try { - membership = await MembershipOrg.findOne({ - user: new Types.ObjectId(userId), - organization: new Types.ObjectId(organizationId) - }); - - if (!membership) throw new Error('Failed to find organization membership'); - - if (!acceptedRoles.includes(membership.role)) { - throw new Error('Failed to validate organization membership role'); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to validate organization membership'); + const membershipOrg = await MembershipOrg.findOne({ + user: userId, + organization: organizationId + }); + + if (!membershipOrg) { + throw MembershipOrgNotFoundError({ message: 'Failed to find organization membership' }); } - return membership; + if (acceptedRoles) { + if (!acceptedRoles.includes(membershipOrg.role)) { + throw UnauthorizedRequestError({ message: 'Failed to validate organization membership role' }); + } + } + + if (acceptedStatuses) { + if (!acceptedStatuses.includes(membershipOrg.status)) { + throw UnauthorizedRequestError({ message: 'Failed to validate organization membership status' }); + } + } + + return membershipOrg; } /** @@ -43,16 +59,8 @@ const validateMembership = async ({ * @param {Object} queryObj - query object * @return {Object} membershipOrg - membership */ -const findMembershipOrg = (queryObj: any) => { - let membershipOrg; - try { - membershipOrg = MembershipOrg.findOne(queryObj); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to find organization membership'); - } - +export const findMembershipOrg = (queryObj: any) => { + const membershipOrg = MembershipOrg.findOne(queryObj); return membershipOrg; }; @@ -64,7 +72,7 @@ const findMembershipOrg = (queryObj: any) => { * @param {String} obj.organizationId - id of organization. * @param {String[]} obj.roles - roles of users. */ -const addMembershipsOrg = async ({ +export const addMembershipsOrg = async ({ userIds, organizationId, roles, @@ -75,33 +83,27 @@ const addMembershipsOrg = async ({ roles: string[]; statuses: string[]; }) => { - try { - const operations = userIds.map((userId, idx) => { - return { - updateOne: { - filter: { - user: userId, - organization: organizationId, - role: roles[idx], - status: statuses[idx] - }, - update: { - user: userId, - organization: organizationId, - role: roles[idx], - status: statuses[idx] - }, - upsert: true - } - }; - }); + const operations = userIds.map((userId, idx) => { + return { + updateOne: { + filter: { + user: userId, + organization: organizationId, + role: roles[idx], + status: statuses[idx] + }, + update: { + user: userId, + organization: organizationId, + role: roles[idx], + status: statuses[idx] + }, + upsert: true + } + }; + }); - await MembershipOrg.bulkWrite(operations as any); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to add users to organization'); - } + await MembershipOrg.bulkWrite(operations as any); }; /** @@ -109,55 +111,41 @@ const addMembershipsOrg = async ({ * @param {Object} obj * @param {String} obj.membershipOrgId - id of organization membership to delete */ -const deleteMembershipOrg = async ({ +export const deleteMembershipOrg = async ({ membershipOrgId }: { membershipOrgId: string; }) => { - let deletedMembershipOrg; - try { - deletedMembershipOrg = await MembershipOrg.findOneAndDelete({ - _id: membershipOrgId - }); + const deletedMembershipOrg = await MembershipOrg.findOneAndDelete({ + _id: membershipOrgId + }); - if (!deletedMembershipOrg) throw new Error('Failed to delete organization membership'); + if (!deletedMembershipOrg) throw new Error('Failed to delete organization membership'); - // delete keys associated with organization membership - if (deletedMembershipOrg?.user) { - // case: organization membership had a registered user + // delete keys associated with organization membership + if (deletedMembershipOrg?.user) { + // case: organization membership had a registered user - const workspaces = ( - await Workspace.find({ - organization: deletedMembershipOrg.organization - }) - ).map((w) => w._id.toString()); + const workspaces = ( + await Workspace.find({ + organization: deletedMembershipOrg.organization + }) + ).map((w) => w._id.toString()); - await Membership.deleteMany({ - user: deletedMembershipOrg.user, - workspace: { - $in: workspaces - } - }); + await Membership.deleteMany({ + user: deletedMembershipOrg.user, + workspace: { + $in: workspaces + } + }); - await Key.deleteMany({ - receiver: deletedMembershipOrg.user, - workspace: { - $in: workspaces - } - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to delete organization membership'); - } + await Key.deleteMany({ + receiver: deletedMembershipOrg.user, + workspace: { + $in: workspaces + } + }); + } return deletedMembershipOrg; -}; - -export { - validateMembership, - findMembershipOrg, - addMembershipsOrg, - deleteMembershipOrg -}; +}; \ No newline at end of file diff --git a/backend/src/helpers/nodemailer.ts b/backend/src/helpers/nodemailer.ts index fe7c05044..ffd39d7dd 100644 --- a/backend/src/helpers/nodemailer.ts +++ b/backend/src/helpers/nodemailer.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import fs from 'fs'; import path from 'path'; import handlebars from 'handlebars'; @@ -14,7 +13,7 @@ let smtpTransporter: nodemailer.Transporter; * @param {String[]} obj.recipients - email addresses of people to send email to * @param {Object} obj.substitutions - object containing template substitutions */ -const sendMail = async ({ +export const sendMail = async ({ template, subjectLine, recipients, @@ -25,30 +24,23 @@ const sendMail = async ({ recipients: string[]; substitutions: any; }) => { - if (getSmtpConfigured()) { - try { - const html = fs.readFileSync( - path.resolve(__dirname, '../templates/' + template), - 'utf8' - ); - const temp = handlebars.compile(html); - const htmlToSend = temp(substitutions); + if (await getSmtpConfigured()) { + const html = fs.readFileSync( + path.resolve(__dirname, '../templates/' + template), + 'utf8' + ); + const temp = handlebars.compile(html); + const htmlToSend = temp(substitutions); - await smtpTransporter.sendMail({ - from: `"${getSmtpFromName()}" <${getSmtpFromAddress()}>`, - to: recipients.join(', '), - subject: subjectLine, - html: htmlToSend - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - } + await smtpTransporter.sendMail({ + from: `"${await getSmtpFromName()}" <${await getSmtpFromAddress()}>`, + to: recipients.join(', '), + subject: subjectLine, + html: htmlToSend + }); } }; -const setTransporter = (transporter: nodemailer.Transporter) => { +export const setTransporter = (transporter: nodemailer.Transporter) => { smtpTransporter = transporter; -}; - -export { sendMail, setTransporter }; +}; \ No newline at end of file diff --git a/backend/src/helpers/organization.ts b/backend/src/helpers/organization.ts index fb559df1b..b88fbdf12 100644 --- a/backend/src/helpers/organization.ts +++ b/backend/src/helpers/organization.ts @@ -1,14 +1,25 @@ -import * as Sentry from '@sentry/node'; -import Stripe from 'stripe'; -import { Types } from 'mongoose'; -import { ACCEPTED } from '../variables'; -import { Organization, MembershipOrg } from '../models'; -import { - getStripeSecretKey, - getStripeProductPro, - getStripeProductTeam, - getStripeProductStarter +import Stripe from "stripe"; +import { Types } from "mongoose"; +import { Organization, MembershipOrg } from "../models"; +import { + ACCEPTED +} from "../variables"; +import { + getStripeSecretKey, + getStripeProductPro, + getStripeProductTeam, + getStripeProductStarter, +} from "../config"; +import { + EELicenseService +} from '../ee/services'; +import { + getLicenseServerUrl } from '../config'; +import { + licenseServerKeyRequest, + licenseKeyRequest +} from '../config/request'; /** * Create an organization with name [name] @@ -17,44 +28,38 @@ import { * @param {String} obj.email - POC email that will receive invoice info * @param {Object} organization - new organization */ -const createOrganization = async ({ - name, - email +export const createOrganization = async ({ + name, + email, }: { - name: string; - email: string; + name: string; + email: string; }) => { - let organization; - try { - // register stripe account - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + let organization; + // register stripe account + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: "2022-08-01", + }); - if (getStripeSecretKey()) { - const customer = await stripe.customers.create({ - email, - description: name - }); + if (await getStripeSecretKey()) { + const customer = await stripe.customers.create({ + email, + description: name, + }); - organization = await new Organization({ - name, - customerId: customer.id - }).save(); - } else { - organization = await new Organization({ - name - }).save(); - } + organization = await new Organization({ + name, + customerId: customer.id, + }).save(); + } else { + organization = await new Organization({ + name, + }).save(); + } - await initSubscriptionOrg({ organizationId: organization._id }); - } catch (err) { - Sentry.setUser({ email }); - Sentry.captureException(err); - throw new Error(`Failed to create organization [err=${err}]`); - } + await initSubscriptionOrg({ organizationId: organization._id }); - return organization; + return organization; }; /** @@ -65,58 +70,53 @@ const createOrganization = async ({ * @return {Object} obj.stripeSubscription - new stripe subscription * @return {Subscription} obj.subscription - new subscription */ -const initSubscriptionOrg = async ({ - organizationId +export const initSubscriptionOrg = async ({ + organizationId, }: { - organizationId: Types.ObjectId; + organizationId: Types.ObjectId; }) => { - let stripeSubscription; - let subscription; - try { - // find organization - const organization = await Organization.findOne({ - _id: organizationId - }); + let stripeSubscription; + let subscription; - if (organization) { - if (organization.customerId) { - // initialize starter subscription with quantity of 0 - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + // find organization + const organization = await Organization.findOne({ + _id: organizationId, + }); - const productToPriceMap = { - starter: getStripeProductStarter(), - team: getStripeProductTeam(), - pro: getStripeProductPro() - }; + if (organization) { + if (organization.customerId) { + // initialize starter subscription with quantity of 0 + const stripe = new Stripe(await getStripeSecretKey(), { + apiVersion: "2022-08-01", + }); - stripeSubscription = await stripe.subscriptions.create({ - customer: organization.customerId, - items: [ - { - price: productToPriceMap['starter'], - quantity: 1 - } - ], - payment_behavior: 'default_incomplete', - proration_behavior: 'none', - expand: ['latest_invoice.payment_intent'] - }); - } - } else { - throw new Error('Failed to initialize free organization subscription'); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to initialize free organization subscription'); - } + const productToPriceMap = { + starter: await getStripeProductStarter(), + team: await getStripeProductTeam(), + pro: await getStripeProductPro(), + }; - return { - stripeSubscription, - subscription - }; + stripeSubscription = await stripe.subscriptions.create({ + customer: organization.customerId, + items: [ + { + price: productToPriceMap["starter"], + quantity: 1, + }, + ], + payment_behavior: "default_incomplete", + proration_behavior: "none", + expand: ["latest_invoice.payment_intent"], + }); + } + } else { + throw new Error("Failed to initialize free organization subscription"); + } + + return { + stripeSubscription, + subscription, + }; }; /** @@ -125,54 +125,52 @@ const initSubscriptionOrg = async ({ * @param {Object} obj * @param {Number} obj.organizationId - id of subscription's organization */ -const updateSubscriptionOrgQuantity = async ({ - organizationId +export const updateSubscriptionOrgQuantity = async ({ + organizationId, }: { - organizationId: string; + organizationId: string; }) => { - let stripeSubscription; - try { - // find organization - const organization = await Organization.findOne({ - _id: organizationId - }); + let stripeSubscription; + // find organization + const organization = await Organization.findOne({ + _id: organizationId, + }); - if (organization && organization.customerId) { - const quantity = await MembershipOrg.countDocuments({ - organization: organizationId, - status: ACCEPTED - }); + if (organization && organization.customerId) { + if (EELicenseService.instanceType === 'cloud') { + // instance of Infisical is a cloud instance + const quantity = await MembershipOrg.countDocuments({ + organization: new Types.ObjectId(organizationId), + status: ACCEPTED, + }); + + await licenseServerKeyRequest.patch( + `${await getLicenseServerUrl()}/api/license-server/v1/customers/${organization.customerId}/cloud-plan`, + { + quantity + } + ); - const stripe = new Stripe(getStripeSecretKey(), { - apiVersion: '2022-08-01' - }); + EELicenseService.localFeatureSet.del(organizationId); + } + } - const subscription = ( - await stripe.subscriptions.list({ - customer: organization.customerId - }) - ).data[0]; + if (EELicenseService.instanceType === 'enterprise-self-hosted') { + // instance of Infisical is an enterprise self-hosted instance + + const usedSeats = await MembershipOrg.countDocuments({ + status: ACCEPTED + }); - stripeSubscription = await stripe.subscriptions.update(subscription.id, { - items: [ - { - id: subscription.items.data[0].id, - price: subscription.items.data[0].price.id, - quantity - } - ] - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - } + await licenseKeyRequest.patch( + `${await getLicenseServerUrl()}/api/license/v1/license`, + { + usedSeats + } + ); + } - return stripeSubscription; -}; + await EELicenseService.refreshPlan(organizationId); -export { - createOrganization, - initSubscriptionOrg, - updateSubscriptionOrgQuantity + return stripeSubscription; }; \ No newline at end of file diff --git a/backend/src/helpers/rateLimiter.ts b/backend/src/helpers/rateLimiter.ts index 432bd5f97..9e9d022eb 100644 --- a/backend/src/helpers/rateLimiter.ts +++ b/backend/src/helpers/rateLimiter.ts @@ -1,43 +1,64 @@ import rateLimit from 'express-rate-limit'; +const MongoStore = require('rate-limit-mongo'); -// 120 requests per minute -const apiLimiter = rateLimit({ - windowMs: 60 * 1000, - max: 240, +// 200 per minute +export const apiLimiter = rateLimit({ + store: new MongoStore({ + uri: process.env.MONGO_URL, + expireTimeMs: 1000 * 60, + collectionName: "expressRateRecords-apiLimiter", + errorHandler: console.error.bind(null, 'rate-limit-mongo') + }), + windowMs: 1000 * 60, + max: 200, standardHeaders: true, legacyHeaders: false, skip: (request) => { return request.path === '/healthcheck' || request.path === '/api/status' }, keyGenerator: (req, res) => { - return req.clientIp + return req.realIP } }); -// 10 requests per minute -const authLimiter = rateLimit({ - windowMs: 60 * 1000, - max: 10, +// 50 requests per 1 hours +const authLimit = rateLimit({ + store: new MongoStore({ + uri: process.env.MONGO_URL, + expireTimeMs: 1000 * 60 * 60, + errorHandler: console.error.bind(null, 'rate-limit-mongo'), + collectionName: "expressRateRecords-authLimit", + }), + windowMs: 1000 * 60 * 60, + max: 50, standardHeaders: true, legacyHeaders: false, keyGenerator: (req, res) => { - return req.clientIp + return req.realIP } }); -// 10 requests per hour -const passwordLimiter = rateLimit({ - windowMs: 60 * 60 * 1000, - max: 10, +// 5 requests per 1 hour +export const passwordLimiter = rateLimit({ + store: new MongoStore({ + uri: process.env.MONGO_URL, + expireTimeMs: 1000 * 60 * 60, + errorHandler: console.error.bind(null, 'rate-limit-mongo'), + collectionName: "expressRateRecords-passwordLimiter", + }), + windowMs: 1000 * 60 * 60, + max: 5, standardHeaders: true, legacyHeaders: false, keyGenerator: (req, res) => { - return req.clientIp + return req.realIP } }); -export { - apiLimiter, - authLimiter, - passwordLimiter -}; +export const authLimiter = (req: any, res: any, next: any) => { + if (process.env.NODE_ENV === 'production') { + authLimit(req, res, next); + } else { + next(); + } +}; \ No newline at end of file diff --git a/backend/src/helpers/secret.ts b/backend/src/helpers/secret.ts index c0f57f3ef..31f6c6c9c 100644 --- a/backend/src/helpers/secret.ts +++ b/backend/src/helpers/secret.ts @@ -1,114 +1,52 @@ -import * as Sentry from '@sentry/node'; -import { Types } from 'mongoose'; +import { Types } from "mongoose"; +import { Secret, ISecret } from "../models"; +import { EESecretService, EELogService } from "../ee/services"; +import { IAction, SecretVersion } from "../ee/models"; import { - Secret, - ISecret, - Membership -} from '../models'; -import { - EESecretService, - EELogService -} from '../ee/services'; -import { - IAction -} from '../ee/models'; -import { - SECRET_SHARED, - SECRET_PERSONAL, - ACTION_ADD_SECRETS, - ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS, - ACTION_READ_SECRETS -} from '../variables'; -import _ from 'lodash'; -import { ABILITY_WRITE } from '../variables/organization'; -import { BadRequestError, UnauthorizedRequestError } from '../utils/errors'; - -/** - * Validate that user with id [userId] can modify secrets with ids [secretIds] - * @param {Object} obj - * @param {Object} obj.userId - id of user to validate - * @param {Object} obj.secretIds - secret ids - * @returns {Secret[]} secrets - */ -const validateSecrets = async ({ - userId, - secretIds -}: { - userId: string; - secretIds: string[]; -}) => { - let secrets; - try { - secrets = await Secret.find({ - _id: { - $in: secretIds.map((secretId: string) => new Types.ObjectId(secretId)) - } - }); - - if (secrets.length != secretIds.length) { - throw BadRequestError({ message: 'Unable to validate some secrets' }) - } - - const userMemberships = await Membership.find({ user: userId }) - const userMembershipById = _.keyBy(userMemberships, 'workspace'); - const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString())); - - // for each secret check if the secret belongs to a workspace the user is a member of - secrets.forEach((secret: ISecret) => { - if (workspaceIdsSet.has(secret.workspace.toString())) { - const deniedMembershipPermissions = userMembershipById[secret.workspace.toString()].deniedPermissions; - const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: secret.environment, ability: ABILITY_WRITE }); - - if (isDisallowed) { - throw UnauthorizedRequestError({ message: 'You do not have the required permissions to perform this action' }); - } - } else { - throw BadRequestError({ message: 'You cannot edit secrets of a workspace you are not a member of' }); - } - }); - - } catch (err) { - throw BadRequestError({ message: 'Unable to validate secrets' }) - } - - return secrets; -} + SECRET_SHARED, + SECRET_PERSONAL, + ACTION_ADD_SECRETS, + ACTION_UPDATE_SECRETS, + ACTION_DELETE_SECRETS, + ACTION_READ_SECRETS, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, +} from "../variables"; interface V1PushSecret { - ciphertextKey: string; - ivKey: string; - tagKey: string; - hashKey: string; - ciphertextValue: string; - ivValue: string; - tagValue: string; - hashValue: string; - ciphertextComment: string; - ivComment: string; - tagComment: string; - hashComment: string; - type: 'shared' | 'personal'; + ciphertextKey: string; + ivKey: string; + tagKey: string; + hashKey: string; + ciphertextValue: string; + ivValue: string; + tagValue: string; + hashValue: string; + ciphertextComment: string; + ivComment: string; + tagComment: string; + hashComment: string; + type: "shared" | "personal"; } interface V2PushSecret { - type: string; // personal or shared - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretKeyHash: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretValueHash: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentHash?: string; + type: string; // personal or shared + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretKeyHash: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretValueHash: string; + secretCommentCiphertext?: string; + secretCommentIV?: string; + secretCommentTag?: string; + secretCommentHash?: string; } interface Update { - [index: string]: any; + [index: string]: any; } /** @@ -122,227 +60,235 @@ interface Update { * @param {String} obj.environment - environment for secrets * @param {Object[]} obj.secrets - secrets to push */ -const v1PushSecrets = async ({ - userId, - workspaceId, - environment, - secrets, +export const v1PushSecrets = async ({ + userId, + workspaceId, + environment, + secrets, }: { - userId: string; - workspaceId: string; - environment: string; - secrets: V1PushSecret[]; + userId: string; + workspaceId: string; + environment: string; + secrets: V1PushSecret[]; }): Promise => { - // TODO: clean up function and fix up types - try { - // construct useful data structures - const oldSecrets = await getSecrets({ - userId, - workspaceId, - environment - }); + // TODO: clean up function and fix up types + // construct useful data structures + const oldSecrets = await getSecrets({ + userId, + workspaceId, + environment, + }); - const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) => - ({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s }) - , {}); - const newSecretsObj: any = secrets.reduce((accumulator, s) => - ({ ...accumulator, [`${s.type}-${s.hashKey}`]: s }) - , {}); + const oldSecretsObj: any = oldSecrets.reduce( + (accumulator, s: any) => ({ + ...accumulator, + [`${s.type}-${s.secretKeyHash}`]: s, + }), + {} + ); + const newSecretsObj: any = secrets.reduce( + (accumulator, s) => ({ ...accumulator, [`${s.type}-${s.hashKey}`]: s }), + {} + ); - // handle deleting secrets - const toDelete = oldSecrets - .filter( - (s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj) - ) - .map((s) => s._id); - if (toDelete.length > 0) { - await Secret.deleteMany({ - _id: { $in: toDelete } - }); + // handle deleting secrets + const toDelete = oldSecrets + .filter((s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj)) + .map((s) => s._id); + if (toDelete.length > 0) { + await Secret.deleteMany({ + _id: { $in: toDelete }, + }); - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete - }); - } + await EESecretService.markDeletedSecretVersions({ + secretIds: toDelete, + }); + } - const toUpdate = oldSecrets - .filter((s) => { - if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { - if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue - || s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment) { - // case: filter secrets where value or comment changed - return true; - } + const toUpdate = oldSecrets.filter((s) => { + if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { + if ( + s.secretValueHash !== + newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashValue || + s.secretCommentHash !== + newSecretsObj[`${s.type}-${s.secretKeyHash}`].hashComment + ) { + // case: filter secrets where value or comment changed + return true; + } - if (!s.version) { - // case: filter (legacy) secrets that were not versioned - return true; - } - } + if (!s.version) { + // case: filter (legacy) secrets that were not versioned + return true; + } + } - return false; - }); + return false; + }); - const operations = toUpdate - .map((s) => { - const { - ciphertextValue, - ivValue, - tagValue, - hashValue, - ciphertextComment, - ivComment, - tagComment, - hashComment - } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; + const operations = toUpdate.map((s) => { + const { + ciphertextValue, + ivValue, + tagValue, + hashValue, + ciphertextComment, + ivComment, + tagComment, + hashComment, + } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; - const update: Update = { - secretValueCiphertext: ciphertextValue, - secretValueIV: ivValue, - secretValueTag: tagValue, - secretValueHash: hashValue, - secretCommentCiphertext: ciphertextComment, - secretCommentIV: ivComment, - secretCommentTag: tagComment, - secretCommentHash: hashComment, - } + const update: Update = { + secretValueCiphertext: ciphertextValue, + secretValueIV: ivValue, + secretValueTag: tagValue, + secretValueHash: hashValue, + secretCommentCiphertext: ciphertextComment, + secretCommentIV: ivComment, + secretCommentTag: tagComment, + secretCommentHash: hashComment, + }; - if (!s.version) { - // case: (legacy) secret was not versioned - update.version = 1; - } else { - update['$inc'] = { - version: 1 - } - } + if (!s.version) { + // case: (legacy) secret was not versioned + update.version = 1; + } else { + update["$inc"] = { + version: 1, + }; + } - if (s.type === SECRET_PERSONAL) { - // attach user associated with the personal secret - update['user'] = userId; - } + if (s.type === SECRET_PERSONAL) { + // attach user associated with the personal secret + update["user"] = userId; + } - return { - updateOne: { - filter: { - _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id - }, - update - } - }; - }); - await Secret.bulkWrite(operations as any); + return { + updateOne: { + filter: { + _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id, + }, + update, + }, + }; + }); + await Secret.bulkWrite(operations as any); - // (EE) add secret versions for updated secrets - await EESecretService.addSecretVersions({ - secretVersions: toUpdate.map(({ - _id, - version, - type, - secretKeyHash, - }) => { - const newSecret = newSecretsObj[`${type}-${secretKeyHash}`]; - return ({ - _id: new Types.ObjectId(), - secret: _id, - version: version ? version + 1 : 1, - workspace: new Types.ObjectId(workspaceId), - type: newSecret.type, - user: new Types.ObjectId(userId), - environment, - isDeleted: false, - secretKeyCiphertext: newSecret.ciphertextKey, - secretKeyIV: newSecret.ivKey, - secretKeyTag: newSecret.tagKey, - secretKeyHash: newSecret.hashKey, - secretValueCiphertext: newSecret.ciphertextValue, - secretValueIV: newSecret.ivValue, - secretValueTag: newSecret.tagValue, - secretValueHash: newSecret.hashValue - }) - }) - }); + // (EE) add secret versions for updated secrets + await EESecretService.addSecretVersions({ + secretVersions: toUpdate.map(({ _id, version, type, secretKeyHash }) => { + const newSecret = newSecretsObj[`${type}-${secretKeyHash}`]; + return new SecretVersion({ + secret: _id, + version: version ? version + 1 : 1, + workspace: new Types.ObjectId(workspaceId), + type: newSecret.type, + user: new Types.ObjectId(userId), + environment, + isDeleted: false, + secretKeyCiphertext: newSecret.ciphertextKey, + secretKeyIV: newSecret.ivKey, + secretKeyTag: newSecret.tagKey, + secretKeyHash: newSecret.hashKey, + secretValueCiphertext: newSecret.ciphertextValue, + secretValueIV: newSecret.ivValue, + secretValueTag: newSecret.tagValue, + secretValueHash: newSecret.hashValue, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + }), + }); - // handle adding new secrets - const toAdd = secrets.filter((s) => !(`${s.type}-${s.hashKey}` in oldSecretsObj)); + // handle adding new secrets + const toAdd = secrets.filter( + (s) => !(`${s.type}-${s.hashKey}` in oldSecretsObj) + ); - if (toAdd.length > 0) { - // add secrets - const newSecrets: ISecret[] = (await Secret.insertMany( - toAdd.map((s, idx) => { - const obj: any = { - version: 1, - workspace: workspaceId, - type: toAdd[idx].type, - environment, - secretKeyCiphertext: s.ciphertextKey, - secretKeyIV: s.ivKey, - secretKeyTag: s.tagKey, - secretKeyHash: s.hashKey, - secretValueCiphertext: s.ciphertextValue, - secretValueIV: s.ivValue, - secretValueTag: s.tagValue, - secretValueHash: s.hashValue, - secretCommentCiphertext: s.ciphertextComment, - secretCommentIV: s.ivComment, - secretCommentTag: s.tagComment, - secretCommentHash: s.hashComment - }; + if (toAdd.length > 0) { + // add secrets + const newSecrets: ISecret[] = ( + await Secret.insertMany( + toAdd.map((s, idx) => { + const obj: any = { + version: 1, + workspace: workspaceId, + type: toAdd[idx].type, + environment, + secretKeyCiphertext: s.ciphertextKey, + secretKeyIV: s.ivKey, + secretKeyTag: s.tagKey, + secretKeyHash: s.hashKey, + secretValueCiphertext: s.ciphertextValue, + secretValueIV: s.ivValue, + secretValueTag: s.tagValue, + secretValueHash: s.hashValue, + secretCommentCiphertext: s.ciphertextComment, + secretCommentIV: s.ivComment, + secretCommentTag: s.tagComment, + secretCommentHash: s.hashComment, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }; - if (toAdd[idx].type === 'personal') { - obj['user' as keyof typeof obj] = userId; - } + if (toAdd[idx].type === "personal") { + obj["user" as keyof typeof obj] = userId; + } - return obj; - }) - )).map((insertedSecret) => insertedSecret.toObject()); + return obj; + }) + ) + ).map((insertedSecret) => insertedSecret.toObject()); - // (EE) add secret versions for new secrets - EESecretService.addSecretVersions({ - secretVersions: newSecrets.map(({ - _id, - version, - workspace, - type, - user, - environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash - }) => ({ - _id: new Types.ObjectId(), - secret: _id, - version, - workspace, - type, - user, - environment, - isDeleted: false, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretKeyHash, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash - })) - }); - } + // (EE) add secret versions for new secrets + EESecretService.addSecretVersions({ + secretVersions: newSecrets.map( + ({ + _id, + version, + workspace, + type, + user, + environment, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretKeyHash, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretValueHash, + algorithm, + keyEncoding, + }) => + new SecretVersion({ + secret: _id, + version, + workspace, + type, + user, + environment, + isDeleted: false, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretKeyHash, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretValueHash, + algorithm, + keyEncoding, + }) + ), + }); + } - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to push shared and personal secrets'); - } + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }); }; /** @@ -358,213 +304,222 @@ const v1PushSecrets = async ({ * @param {String} obj.channel - channel (web/cli/auto) * @param {String} obj.ipAddress - ip address of request to push secrets */ -const v2PushSecrets = async ({ - userId, - workspaceId, - environment, - secrets, - channel, - ipAddress +export const v2PushSecrets = async ({ + userId, + workspaceId, + environment, + secrets, + channel, + ipAddress, }: { - userId: string; - workspaceId: string; - environment: string; - secrets: V2PushSecret[]; - channel: string; - ipAddress: string; + userId: string; + workspaceId: string; + environment: string; + secrets: V2PushSecret[]; + channel: string; + ipAddress: string; }): Promise => { - // TODO: clean up function and fix up types - try { - const actions: IAction[] = []; + // TODO: clean up function and fix up types + const actions: IAction[] = []; - // construct useful data structures - const oldSecrets = await getSecrets({ - userId, - workspaceId, - environment - }); + // construct useful data structures + const oldSecrets = await getSecrets({ + userId, + workspaceId, + environment, + }); - const oldSecretsObj: any = oldSecrets.reduce((accumulator, s: any) => - ({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s }) - , {}); - const newSecretsObj: any = secrets.reduce((accumulator, s) => - ({ ...accumulator, [`${s.type}-${s.secretKeyHash}`]: s }) - , {}); + const oldSecretsObj: any = oldSecrets.reduce( + (accumulator, s: any) => ({ + ...accumulator, + [`${s.type}-${s.secretKeyHash}`]: s, + }), + {} + ); + const newSecretsObj: any = secrets.reduce( + (accumulator, s) => ({ + ...accumulator, + [`${s.type}-${s.secretKeyHash}`]: s, + }), + {} + ); - // handle deleting secrets - const toDelete = oldSecrets - .filter( - (s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj) - ) - .map((s) => s._id); - if (toDelete.length > 0) { - await Secret.deleteMany({ - _id: { $in: toDelete } - }); + // handle deleting secrets + const toDelete = oldSecrets + .filter((s: ISecret) => !(`${s.type}-${s.secretKeyHash}` in newSecretsObj)) + .map((s) => s._id); + if (toDelete.length > 0) { + await Secret.deleteMany({ + _id: { $in: toDelete }, + }); - await EESecretService.markDeletedSecretVersions({ - secretIds: toDelete - }); + await EESecretService.markDeletedSecretVersions({ + secretIds: toDelete, + }); - const deleteAction = await EELogService.createAction({ - name: ACTION_DELETE_SECRETS, - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(userId), - secretIds: toDelete - }); + const deleteAction = await EELogService.createAction({ + name: ACTION_DELETE_SECRETS, + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(userId), + secretIds: toDelete, + }); - deleteAction && actions.push(deleteAction); - } + deleteAction && actions.push(deleteAction); + } - const toUpdate = oldSecrets - .filter((s) => { - if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { - if (s.secretValueHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash - || s.secretCommentHash !== newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash) { - // case: filter secrets where value or comment changed - return true; - } + const toUpdate = oldSecrets.filter((s) => { + if (`${s.type}-${s.secretKeyHash}` in newSecretsObj) { + if ( + s.secretValueHash !== + newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretValueHash || + s.secretCommentHash !== + newSecretsObj[`${s.type}-${s.secretKeyHash}`].secretCommentHash + ) { + // case: filter secrets where value or comment changed + return true; + } - if (!s.version) { - // case: filter (legacy) secrets that were not versioned - return true; - } - } + if (!s.version) { + // case: filter (legacy) secrets that were not versioned + return true; + } + } - return false; - }); + return false; + }); - if (toUpdate.length > 0) { - const operations = toUpdate - .map((s) => { - const { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentHash, - } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; + if (toUpdate.length > 0) { + const operations = toUpdate.map((s) => { + const { + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretValueHash, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + secretCommentHash, + } = newSecretsObj[`${s.type}-${s.secretKeyHash}`]; - const update: Update = { - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretValueHash, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag, - secretCommentHash, - } + const update: Update = { + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretValueHash, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + secretCommentHash, + }; - if (!s.version) { - // case: (legacy) secret was not versioned - update.version = 1; - } else { - update['$inc'] = { - version: 1 - } - } + if (!s.version) { + // case: (legacy) secret was not versioned + update.version = 1; + } else { + update["$inc"] = { + version: 1, + }; + } - if (s.type === SECRET_PERSONAL) { - // attach user associated with the personal secret - update['user'] = userId; - } + if (s.type === SECRET_PERSONAL) { + // attach user associated with the personal secret + update["user"] = userId; + } - return { - updateOne: { - filter: { - _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id - }, - update - } - }; - }); - await Secret.bulkWrite(operations as any); + return { + updateOne: { + filter: { + _id: oldSecretsObj[`${s.type}-${s.secretKeyHash}`]._id, + }, + update, + }, + }; + }); + await Secret.bulkWrite(operations as any); - // (EE) add secret versions for updated secrets - await EESecretService.addSecretVersions({ - secretVersions: toUpdate.map((s) => { - return ({ - ...newSecretsObj[`${s.type}-${s.secretKeyHash}`], - secret: s._id, - version: s.version ? s.version + 1 : 1, - workspace: new Types.ObjectId(workspaceId), - user: s.user, - environment: s.environment, - isDeleted: false - }) - }) - }); + // (EE) add secret versions for updated secrets + await EESecretService.addSecretVersions({ + secretVersions: toUpdate.map((s) => { + return { + ...newSecretsObj[`${s.type}-${s.secretKeyHash}`], + secret: s._id, + version: s.version ? s.version + 1 : 1, + workspace: new Types.ObjectId(workspaceId), + user: s.user, + environment: s.environment, + isDeleted: false, + }; + }), + }); - const updateAction = await EELogService.createAction({ - name: ACTION_UPDATE_SECRETS, - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId), - secretIds: toUpdate.map((u) => u._id) - }); + const updateAction = await EELogService.createAction({ + name: ACTION_UPDATE_SECRETS, + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(workspaceId), + secretIds: toUpdate.map((u) => u._id), + }); - updateAction && actions.push(updateAction); - } + updateAction && actions.push(updateAction); + } - // handle adding new secrets - const toAdd = secrets.filter((s) => !(`${s.type}-${s.secretKeyHash}` in oldSecretsObj)); + // handle adding new secrets + const toAdd = secrets.filter( + (s) => !(`${s.type}-${s.secretKeyHash}` in oldSecretsObj) + ); - if (toAdd.length > 0) { - // add secrets - const newSecrets = await Secret.insertMany( - toAdd.map((s, idx) => ({ - ...s, - version: 1, - workspace: workspaceId, - type: toAdd[idx].type, - environment, - ...(toAdd[idx].type === 'personal' ? { user: userId } : {}) - })) - ); + if (toAdd.length > 0) { + // add secrets + const newSecrets = await Secret.insertMany( + toAdd.map((s, idx) => ({ + ...s, + version: 1, + workspace: workspaceId, + type: toAdd[idx].type, + environment, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + ...(toAdd[idx].type === "personal" ? { user: userId } : {}), + })) + ); - // (EE) add secret versions for new secrets - EESecretService.addSecretVersions({ - secretVersions: newSecrets.map((secretDocument) => { - return { - ...secretDocument.toObject(), - secret: secretDocument._id, - isDeleted: false - } - }) - }); + // (EE) add secret versions for new secrets + EESecretService.addSecretVersions({ + secretVersions: newSecrets.map((secretDocument: ISecret) => { + return new SecretVersion({ + ...secretDocument, + secret: secretDocument._id, + isDeleted: false, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + }), + }); - const addAction = await EELogService.createAction({ - name: ACTION_ADD_SECRETS, - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId), - secretIds: newSecrets.map((n) => n._id) - }); - addAction && actions.push(addAction); - } + const addAction = await EELogService.createAction({ + name: ACTION_ADD_SECRETS, + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(workspaceId), + secretIds: newSecrets.map((n) => n._id), + }); + addAction && actions.push(addAction); + } - // (EE) take a secret snapshot - await EESecretService.takeSecretSnapshot({ - workspaceId - }) + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId: new Types.ObjectId(workspaceId), + environment, + }); - // (EE) create (audit) log - if (actions.length > 0) { - await EELogService.createLog({ - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId), - actions, - channel, - ipAddress - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to push shared and personal secrets'); - } + // (EE) create (audit) log + if (actions.length > 0) { + await EELogService.createLog({ + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(workspaceId), + actions, + channel, + ipAddress, + }); + } }; /** @@ -575,42 +530,34 @@ const v2PushSecrets = async ({ * @param {String} obj.workspaceId - id of workspace to pull from * @param {String} obj.environment - environment for secrets */ -const getSecrets = async ({ - userId, - workspaceId, - environment +export const getSecrets = async ({ + userId, + workspaceId, + environment, }: { - userId: string; - workspaceId: string; - environment: string; + userId: string; + workspaceId: string; + environment: string; }): Promise => { - let secrets: any; // TODO: FIX any + // get shared workspace secrets + const sharedSecrets = await Secret.find({ + workspace: workspaceId, + environment, + type: SECRET_SHARED, + }); - try { - // get shared workspace secrets - const sharedSecrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_SHARED - }); + // get personal workspace secrets + const personalSecrets = await Secret.find({ + workspace: workspaceId, + environment, + type: SECRET_PERSONAL, + user: userId, + }); - // get personal workspace secrets - const personalSecrets = await Secret.find({ - workspace: workspaceId, - environment, - type: SECRET_PERSONAL, - user: userId - }); + // concat shared and personal workspace secrets + const secrets = personalSecrets.concat(sharedSecrets); - // concat shared and personal workspace secrets - secrets = personalSecrets.concat(sharedSecrets); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to pull shared and personal secrets'); - } - - return secrets; + return secrets; }; /** @@ -623,49 +570,42 @@ const getSecrets = async ({ * @param {String} obj.channel - channel (web/cli/auto) * @param {String} obj.ipAddress - ip address of request to push secrets */ -const pullSecrets = async ({ - userId, - workspaceId, - environment, - channel, - ipAddress +export const pullSecrets = async ({ + userId, + workspaceId, + environment, + channel, + ipAddress, }: { - userId: string; - workspaceId: string; - environment: string; - channel: string; - ipAddress: string; + userId: string; + workspaceId: string; + environment: string; + channel: string; + ipAddress: string; }): Promise => { - let secrets: any; + const secrets = await getSecrets({ + userId, + workspaceId, + environment, + }); - try { - secrets = await getSecrets({ - userId, - workspaceId, - environment - }) + const readAction = await EELogService.createAction({ + name: ACTION_READ_SECRETS, + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(workspaceId), + secretIds: secrets.map((n: any) => n._id), + }); - const readAction = await EELogService.createAction({ - name: ACTION_READ_SECRETS, - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId), - secretIds: secrets.map((n: any) => n._id) - }); + readAction && + (await EELogService.createLog({ + userId: new Types.ObjectId(userId), + workspaceId: new Types.ObjectId(workspaceId), + actions: [readAction], + channel, + ipAddress, + })); - readAction && await EELogService.createLog({ - userId: new Types.ObjectId(userId), - workspaceId: new Types.ObjectId(workspaceId), - actions: [readAction], - channel, - ipAddress - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to pull shared and personal secrets'); - } - - return secrets; + return secrets; }; /** @@ -674,49 +614,34 @@ const pullSecrets = async ({ * @param {Object} obj * @param {Object} obj.secrets */ -const reformatPullSecrets = ({ secrets }: { secrets: ISecret[] }) => { - let reformatedSecrets; - try { - reformatedSecrets = secrets.map((s) => ({ - _id: s._id, - workspace: s.workspace, - type: s.type, - environment: s.environment, - secretKey: { - workspace: s.workspace, - ciphertext: s.secretKeyCiphertext, - iv: s.secretKeyIV, - tag: s.secretKeyTag, - hash: s.secretKeyHash - }, - secretValue: { - workspace: s.workspace, - ciphertext: s.secretValueCiphertext, - iv: s.secretValueIV, - tag: s.secretValueTag, - hash: s.secretValueHash - }, - secretComment: { - workspace: s.workspace, - ciphertext: s.secretCommentCiphertext, - iv: s.secretCommentIV, - tag: s.secretCommentTag, - hash: s.secretCommentHash - } - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to reformat pulled secrets'); - } +export const reformatPullSecrets = ({ secrets }: { secrets: ISecret[] }) => { + const reformatedSecrets = secrets.map((s) => ({ + _id: s._id, + workspace: s.workspace, + type: s.type, + environment: s.environment, + secretKey: { + workspace: s.workspace, + ciphertext: s.secretKeyCiphertext, + iv: s.secretKeyIV, + tag: s.secretKeyTag, + hash: s.secretKeyHash, + }, + secretValue: { + workspace: s.workspace, + ciphertext: s.secretValueCiphertext, + iv: s.secretValueIV, + tag: s.secretValueTag, + hash: s.secretValueHash, + }, + secretComment: { + workspace: s.workspace, + ciphertext: s.secretCommentCiphertext, + iv: s.secretCommentIV, + tag: s.secretCommentTag, + hash: s.secretCommentHash, + }, + })); - return reformatedSecrets; -}; - -export { - validateSecrets, - v1PushSecrets, - v2PushSecrets, - pullSecrets, - reformatPullSecrets -}; + return reformatedSecrets; +}; \ No newline at end of file diff --git a/backend/src/helpers/secrets.ts b/backend/src/helpers/secrets.ts new file mode 100644 index 000000000..d7cc31cda --- /dev/null +++ b/backend/src/helpers/secrets.ts @@ -0,0 +1,949 @@ +import { Types } from "mongoose"; +import { + CreateSecretParams, + GetSecretsParams, + GetSecretParams, + UpdateSecretParams, + DeleteSecretParams, +} from '../interfaces/services/SecretService'; +import { + Secret, + ISecret, + SecretBlindIndexData, + ServiceTokenData, +} from "../models"; +import { SecretVersion } from "../ee/models"; +import { + BadRequestError, + SecretNotFoundError, + SecretBlindIndexDataNotFoundError, + InternalServerError, + UnauthorizedRequestError, +} from "../utils/errors"; +import { + SECRET_PERSONAL, + SECRET_SHARED, + ACTION_ADD_SECRETS, + ACTION_READ_SECRETS, + ACTION_UPDATE_SECRETS, + ACTION_DELETE_SECRETS, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, +} from "../variables"; +import crypto from "crypto"; +import * as argon2 from "argon2"; +import { + encryptSymmetric128BitHexKeyUTF8, + decryptSymmetric128BitHexKeyUTF8, +} from '../utils/crypto'; +import { TelemetryService } from '../services'; +import { getEncryptionKey, client, getRootEncryptionKey } from "../config"; +import { EESecretService, EELogService } from "../ee/services"; +import { + getAuthDataPayloadIdObj, + getAuthDataPayloadUserObj, +} from "../utils/auth"; +import { getFolderIdFromServiceToken } from "../services/FolderService"; + +/** + * Returns an object containing secret [secret] but with its value, key, comment decrypted. + * + * Precondition: the workspace for secret [secret] must have E2EE disabled + * @param {ISecret} secret - secret to repackage to raw + * @param {String} key - symmetric key to use to decrypt secret + * @returns + */ +export const repackageSecretToRaw = ({ + secret, + key +}:{ + secret: ISecret; + key: string; +}) => { + + const secretKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretKeyCiphertext, + iv: secret.secretKeyIV, + tag: secret.secretKeyTag, + key + }); + + const secretValue = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretValueCiphertext, + iv: secret.secretValueIV, + tag: secret.secretValueTag, + key + }); + + let secretComment: string = ''; + + if (secret.secretCommentCiphertext && secret.secretCommentIV && secret.secretCommentTag) { + secretComment = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secret.secretCommentCiphertext, + iv: secret.secretCommentIV, + tag: secret.secretCommentTag, + key + }); + } + + return ({ + _id: secret._id, + version: secret.version, + workspace: secret.workspace, + type: secret.type, + environment: secret.environment, + user: secret.user, + secretKey, + secretValue, + secretComment + }); +} + +/** + * Create secret blind index data containing encrypted blind index [salt] + * for workspace with id [workspaceId] + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId + */ +export const createSecretBlindIndexDataHelper = async ({ + workspaceId, +}: { + workspaceId: Types.ObjectId; +}) => { + // initialize random blind index salt for workspace + const salt = crypto.randomBytes(16).toString("base64"); + + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if (rootEncryptionKey) { + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag, + } = client.encryptSymmetric(salt, rootEncryptionKey); + + return await new SecretBlindIndexData({ + workspace: workspaceId, + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64, + }).save(); + } else { + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag, + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: salt, + key: encryptionKey, + }); + + return await new SecretBlindIndexData({ + workspace: workspaceId, + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }).save(); + } +}; + +/** + * Get secret blind index salt for workspace with id [workspaceId] + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId - id of workspace to get salt for + * @returns + */ +export const getSecretBlindIndexSaltHelper = async ({ + workspaceId, +}: { + workspaceId: Types.ObjectId; +}) => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const secretBlindIndexData = await SecretBlindIndexData.findOne({ + workspace: workspaceId, + }).select("+algorithm +keyEncoding"); + + if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError(); + + if ( + rootEncryptionKey && + secretBlindIndexData.keyEncoding === ENCODING_SCHEME_BASE64 + ) { + return client.decryptSymmetric( + secretBlindIndexData.encryptedSaltCiphertext, + rootEncryptionKey, + secretBlindIndexData.saltIV, + secretBlindIndexData.saltTag + ); + } else if ( + encryptionKey && + secretBlindIndexData.keyEncoding === ENCODING_SCHEME_UTF8 + ) { + // decrypt workspace salt + return decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secretBlindIndexData.encryptedSaltCiphertext, + iv: secretBlindIndexData.saltIV, + tag: secretBlindIndexData.saltTag, + key: encryptionKey, + }); + } + + throw InternalServerError({ + message: "Failed to obtain workspace salt needed for secret blind indexing", + }); +}; + +/** + * Generate blind index for secret with name [secretName] + * and salt [salt] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to generate blind index for + * @param {String} obj.salt - base64-salt + */ +export const generateSecretBlindIndexWithSaltHelper = async ({ + secretName, + salt, +}: { + secretName: string; + salt: string; +}) => { + // generate secret blind index + const secretBlindIndex = ( + await argon2.hash(secretName, { + type: argon2.argon2id, + salt: Buffer.from(salt, "base64"), + saltLength: 16, // default 16 bytes + memoryCost: 65536, // default pool of 64 MiB per thread. + hashLength: 32, + parallelism: 1, + raw: true, + }) + ).toString("base64"); + + return secretBlindIndex; +}; + +/** + * Generate blind index for secret with name [secretName] + * for workspace with id [workspaceId] + * @param {Object} obj + * @param {Stringj} obj.secretName - name of secret to generate blind index for + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + */ +export const generateSecretBlindIndexHelper = async ({ + secretName, + workspaceId, +}: { + secretName: string; + workspaceId: Types.ObjectId; +}) => { + // check if workspace blind index data exists + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const secretBlindIndexData = await SecretBlindIndexData.findOne({ + workspace: workspaceId, + }).select("+algorithm +keyEncoding"); + + if (!secretBlindIndexData) throw SecretBlindIndexDataNotFoundError(); + + let salt; + if ( + rootEncryptionKey && + secretBlindIndexData.keyEncoding === ENCODING_SCHEME_BASE64 + ) { + salt = client.decryptSymmetric( + secretBlindIndexData.encryptedSaltCiphertext, + rootEncryptionKey, + secretBlindIndexData.saltIV, + secretBlindIndexData.saltTag + ); + + const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({ + secretName, + salt, + }); + + return secretBlindIndex; + } else if ( + encryptionKey && + secretBlindIndexData.keyEncoding === ENCODING_SCHEME_UTF8 + ) { + // decrypt workspace salt + salt = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secretBlindIndexData.encryptedSaltCiphertext, + iv: secretBlindIndexData.saltIV, + tag: secretBlindIndexData.saltTag, + key: encryptionKey, + }); + + const secretBlindIndex = await generateSecretBlindIndexWithSaltHelper({ + secretName, + salt, + }); + + return secretBlindIndex; + } + + throw InternalServerError({ + message: "Failed to generate secret blind index", + }); +}; + +/** + * Create secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to create + * @param {Types.ObjectId} obj.workspaceId - id of workspace to create secret for + * @param {String} obj.environment - environment in workspace to create secret for + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ +export const createSecretHelper = async ({ + secretName, + workspaceId, + environment, + type, + authData, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + secretPath = "/", +}: CreateSecretParams) => { + + const secretBlindIndex = await generateSecretBlindIndexHelper({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + }); + + // if using service token filter towards the folderId by secretpath + if (authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = authData.authPayload; + if (secretPath !== serviceTkScopedSecretPath) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + const folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + + const exists = await Secret.exists({ + secretBlindIndex, + workspace: new Types.ObjectId(workspaceId), + folder: folderId, + type, + ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), + }); + + if (exists) + throw BadRequestError({ + message: "Failed to create secret that already exists", + }); + + if (type === SECRET_PERSONAL) { + // case: secret type is personal -> check if a corresponding shared secret + // with the same blind index [secretBlindIndex] exists + + const exists = await Secret.exists({ + secretBlindIndex, + folder: folderId, + workspace: new Types.ObjectId(workspaceId), + type: SECRET_SHARED, + }); + + if (!exists) + throw BadRequestError({ + message: + "Failed to create personal secret override for no corresponding shared secret", + }); + } + + // create secret + const secret = await new Secret({ + version: 1, + workspace: new Types.ObjectId(workspaceId), + environment, + type, + ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag, + folder: folderId, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }).save(); + + const secretVersion = new SecretVersion({ + secret: secret._id, + version: secret.version, + workspace: secret.workspace, + type, + folder: folderId, + ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), + environment: secret.environment, + isDeleted: false, + secretBlindIndex, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + + // (EE) add version for new secret + await EESecretService.addSecretVersions({ + secretVersions: [secretVersion], + }); + + // (EE) create (audit) log + const action = await EELogService.createAction({ + name: ACTION_ADD_SECRETS, + ...getAuthDataPayloadIdObj(authData), + workspaceId, + secretIds: [secret._id], + }); + + action && + (await EELogService.createLog({ + ...getAuthDataPayloadIdObj(authData), + workspaceId, + actions: [action], + channel: authData.authChannel, + ipAddress: authData.authIP, + })); + + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId, + }); + + const postHogClient = await TelemetryService.getPostHogClient(); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets added", + distinctId: await TelemetryService.getDistinctId({ + authData, + }), + properties: { + numberOfSecrets: 1, + environment, + workspaceId, + folderId, + channel: authData.authChannel, + userAgent: authData.authUserAgent, + }, + }); + } + + return secret; +}; + +/** + * Get secrets for workspace with id [workspaceId] and environment [environment] + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId - id of workspace + * @param {String} obj.environment - environment in workspace + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ +export const getSecretsHelper = async ({ + workspaceId, + environment, + authData, + secretPath = "/", +}: GetSecretsParams) => { + let secrets: ISecret[] = []; + // if using service token filter towards the folderId by secretpath + if (authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = authData.authPayload; + if (secretPath !== serviceTkScopedSecretPath) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + const folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + + // get personal secrets first + secrets = await Secret.find({ + workspace: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + type: SECRET_PERSONAL, + ...getAuthDataPayloadUserObj(authData), + }).lean(); + + // concat with shared secrets + secrets = secrets.concat( + await Secret.find({ + workspace: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + type: SECRET_SHARED, + secretBlindIndex: { + $nin: secrets.map((secret) => secret.secretBlindIndex), + }, + }).lean() + ); + + // (EE) create (audit) log + const action = await EELogService.createAction({ + name: ACTION_READ_SECRETS, + ...getAuthDataPayloadIdObj(authData), + workspaceId, + secretIds: secrets.map((secret) => secret._id), + }); + + action && + (await EELogService.createLog({ + ...getAuthDataPayloadIdObj(authData), + workspaceId, + actions: [action], + channel: authData.authChannel, + ipAddress: authData.authIP, + })); + + const postHogClient = await TelemetryService.getPostHogClient(); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets pulled", + distinctId: await TelemetryService.getDistinctId({ + authData, + }), + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + folderId, + channel: authData.authChannel, + userAgent: authData.authUserAgent, + }, + }); + } + + return secrets; +}; + +/** + * Get secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to get + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ +export const getSecretHelper = async ({ + secretName, + workspaceId, + environment, + type, + authData, + secretPath = "/", +}: GetSecretParams) => { + const secretBlindIndex = await generateSecretBlindIndexHelper({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + }); + let secret: ISecret | null = null; + // if using service token filter towards the folderId by secretpath + if (authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = authData.authPayload; + if (secretPath !== serviceTkScopedSecretPath) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + const folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + + // try getting personal secret first (if exists) + secret = await Secret.findOne({ + secretBlindIndex, + workspace: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + type: type ?? SECRET_PERSONAL, + ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), + }).lean(); + + if (!secret) { + // case: failed to find personal secret matching criteria + // -> find shared secret matching criteria + secret = await Secret.findOne({ + secretBlindIndex, + workspace: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + type: SECRET_SHARED, + }).lean(); + } + + if (!secret) throw SecretNotFoundError(); + + // (EE) create (audit) log + const action = await EELogService.createAction({ + name: ACTION_READ_SECRETS, + ...getAuthDataPayloadIdObj(authData), + workspaceId, + secretIds: [secret._id], + }); + + action && + (await EELogService.createLog({ + ...getAuthDataPayloadIdObj(authData), + workspaceId, + actions: [action], + channel: authData.authChannel, + ipAddress: authData.authIP, + })); + + const postHogClient = await TelemetryService.getPostHogClient(); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets pull", + distinctId: await TelemetryService.getDistinctId({ + authData, + }), + properties: { + numberOfSecrets: 1, + environment, + workspaceId, + folderId, + channel: authData.authChannel, + userAgent: authData.authUserAgent, + }, + }); + } + + return secret; +}; + +/** + * Update secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to update + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {String} obj.secretValueCiphertext - ciphertext of secret value + * @param {String} obj.secretValueIV - IV of secret value + * @param {String} obj.secretValueTag - tag of secret value + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + +export const updateSecretHelper = async ({ + secretName, + workspaceId, + environment, + type, + authData, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretPath, +}: UpdateSecretParams) => { + const secretBlindIndex = await generateSecretBlindIndexHelper({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + }); + + let secret: ISecret | null = null; + // if using service token filter towards the folderId by secretpath + if (authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = authData.authPayload; + if (secretPath !== serviceTkScopedSecretPath) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + const folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + + if (type === SECRET_SHARED) { + // case: update shared secret + secret = await Secret.findOneAndUpdate( + { + secretBlindIndex, + workspace: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + type, + }, + { + secretValueCiphertext, + secretValueIV, + secretValueTag, + $inc: { version: 1 }, + }, + { + new: true, + } + ); + } else { + // case: update personal secret + + secret = await Secret.findOneAndUpdate( + { + secretBlindIndex, + workspace: new Types.ObjectId(workspaceId), + environment, + type, + folder: folderId, + ...getAuthDataPayloadUserObj(authData), + }, + { + secretValueCiphertext, + secretValueIV, + secretValueTag, + $inc: { version: 1 }, + }, + { + new: true, + } + ); + } + + if (!secret) throw SecretNotFoundError(); + + const secretVersion = new SecretVersion({ + secret: secret._id, + version: secret.version, + workspace: secret.workspace, + folder: folderId, + type, + ...(type === SECRET_PERSONAL ? getAuthDataPayloadUserObj(authData) : {}), + environment: secret.environment, + isDeleted: false, + secretBlindIndex, + secretKeyCiphertext: secret.secretKeyCiphertext, + secretKeyIV: secret.secretKeyIV, + secretKeyTag: secret.secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + + // (EE) add version for new secret + await EESecretService.addSecretVersions({ + secretVersions: [secretVersion], + }); + + // (EE) create (audit) log + const action = await EELogService.createAction({ + name: ACTION_UPDATE_SECRETS, + ...getAuthDataPayloadIdObj(authData), + workspaceId, + secretIds: [secret._id], + }); + + action && + (await EELogService.createLog({ + ...getAuthDataPayloadIdObj(authData), + workspaceId, + actions: [action], + channel: authData.authChannel, + ipAddress: authData.authIP, + })); + + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId: secret?.folder, + }); + + const postHogClient = await TelemetryService.getPostHogClient(); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets modified", + distinctId: await TelemetryService.getDistinctId({ + authData, + }), + properties: { + numberOfSecrets: 1, + environment, + workspaceId, + folderId, + channel: authData.authChannel, + userAgent: authData.authUserAgent, + }, + }); + } + + return secret; +}; + +/** + * Delete secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to delete + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ +export const deleteSecretHelper = async ({ + secretName, + workspaceId, + environment, + type, + authData, + secretPath = "/", +}: DeleteSecretParams) => { + const secretBlindIndex = await generateSecretBlindIndexHelper({ + secretName, + workspaceId: new Types.ObjectId(workspaceId), + }); + + // if using service token filter towards the folderId by secretpath + if (authData.authPayload instanceof ServiceTokenData) { + const { secretPath: serviceTkScopedSecretPath } = authData.authPayload; + + if (secretPath !== serviceTkScopedSecretPath) { + throw UnauthorizedRequestError({ message: "Folder Permission Denied" }); + } + } + const folderId = await getFolderIdFromServiceToken( + workspaceId, + environment, + secretPath + ); + + let secrets: ISecret[] = []; + let secret: ISecret | null = null; + + if (type === SECRET_SHARED) { + secrets = await Secret.find({ + secretBlindIndex, + workspaceId: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + }).lean(); + + secret = await Secret.findOneAndDelete({ + secretBlindIndex, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + folder: folderId, + }).lean(); + + await Secret.deleteMany({ + secretBlindIndex, + workspaceId: new Types.ObjectId(workspaceId), + environment, + folder: folderId, + }); + } else { + secret = await Secret.findOneAndDelete({ + secretBlindIndex, + folder: folderId, + workspaceId: new Types.ObjectId(workspaceId), + environment, + type, + ...getAuthDataPayloadUserObj(authData), + }).lean(); + + if (secret) { + secrets = [secret]; + } + } + + if (!secret) throw SecretNotFoundError(); + + await EESecretService.markDeletedSecretVersions({ + secretIds: secrets.map((secret) => secret._id), + }); + + // (EE) create (audit) log + const action = await EELogService.createAction({ + name: ACTION_DELETE_SECRETS, + ...getAuthDataPayloadIdObj(authData), + workspaceId, + secretIds: secrets.map((secret) => secret._id), + }); + + action && (await EELogService.createLog({ + ...getAuthDataPayloadIdObj(authData), + workspaceId, + actions: [action], + channel: authData.authChannel, + ipAddress: authData.authIP, + })); + + // (EE) take a secret snapshot + await EESecretService.takeSecretSnapshot({ + workspaceId, + environment, + folderId: secret?.folder, + }); + + const postHogClient = await TelemetryService.getPostHogClient(); + + if (postHogClient) { + postHogClient.capture({ + event: "secrets deleted", + distinctId: await TelemetryService.getDistinctId({ + authData, + }), + properties: { + numberOfSecrets: secrets.length, + environment, + workspaceId, + folderId, + channel: authData.authChannel, + userAgent: authData.authUserAgent, + }, + }); + } + + return ({ + secrets, + secret + }); +}; diff --git a/backend/src/helpers/signup.ts b/backend/src/helpers/signup.ts index dfca96736..d747de20d 100644 --- a/backend/src/helpers/signup.ts +++ b/backend/src/helpers/signup.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { IUser } from '../models'; import { createOrganization } from './organization'; import { addMembershipsOrg } from './membershipOrg'; @@ -14,29 +13,21 @@ import { TOKEN_EMAIL_CONFIRMATION } from '../variables'; * @param {String} obj.email - email * @returns {Boolean} success - whether or not operation was successful */ -const sendEmailVerification = async ({ email }: { email: string }) => { - try { - const token = await TokenService.createToken({ - type: TOKEN_EMAIL_CONFIRMATION, - email - }); +export const sendEmailVerification = async ({ email }: { email: string }) => { + const token = await TokenService.createToken({ + type: TOKEN_EMAIL_CONFIRMATION, + email + }); - // send mail - await sendMail({ - template: 'emailVerification.handlebars', - subjectLine: 'Infisical confirmation code', - recipients: [email], - substitutions: { - code: token - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error( - "Ouch. We weren't able to send your email verification code" - ); - } + // send mail + await sendMail({ + template: 'emailVerification.handlebars', + subjectLine: 'Infisical confirmation code', + recipients: [email], + substitutions: { + code: token + } + }); }; /** @@ -45,24 +36,18 @@ const sendEmailVerification = async ({ email }: { email: string }) => { * @param {String} obj.email - emai * @param {String} obj.code - code that was sent to [email] */ -const checkEmailVerification = async ({ +export const checkEmailVerification = async ({ email, code }: { email: string; code: string; }) => { - try { - await TokenService.validateToken({ - type: TOKEN_EMAIL_CONFIRMATION, - email, - token: code - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Oops. We weren't able to verify"); - } + await TokenService.validateToken({ + type: TOKEN_EMAIL_CONFIRMATION, + email, + token: code + }); }; /** @@ -72,7 +57,7 @@ const checkEmailVerification = async ({ * @param {String} obj.organizationName - name of organization to initialize * @param {IUser} obj.user - user who we are initializing for */ -const initializeDefaultOrg = async ({ +export const initializeDefaultOrg = async ({ organizationName, user }: { @@ -96,6 +81,4 @@ const initializeDefaultOrg = async ({ } catch (err) { throw new Error(`Failed to initialize default organization and workspace [err=${err}]`); } -}; - -export { sendEmailVerification, checkEmailVerification, initializeDefaultOrg }; +}; \ No newline at end of file diff --git a/backend/src/helpers/token.ts b/backend/src/helpers/token.ts index 0f6a88cc9..66bae1a15 100644 --- a/backend/src/helpers/token.ts +++ b/backend/src/helpers/token.ts @@ -1,16 +1,15 @@ -import * as Sentry from '@sentry/node'; -import { Types } from 'mongoose'; -import { TokenData } from '../models'; -import crypto from 'crypto'; -import bcrypt from 'bcrypt'; +import { Types } from "mongoose"; +import { TokenData } from "../models"; +import crypto from "crypto"; +import bcrypt from "bcrypt"; import { - TOKEN_EMAIL_CONFIRMATION, - TOKEN_EMAIL_MFA, - TOKEN_EMAIL_ORG_INVITATION, - TOKEN_EMAIL_PASSWORD_RESET -} from '../variables'; -import { UnauthorizedRequestError } from '../utils/errors'; -import { getSaltRounds } from '../config'; + TOKEN_EMAIL_CONFIRMATION, + TOKEN_EMAIL_MFA, + TOKEN_EMAIL_ORG_INVITATION, + TOKEN_EMAIL_PASSWORD_RESET, +} from "../variables"; +import { UnauthorizedRequestError } from "../utils/errors"; +import { getSaltRounds } from "../config"; /** * Create and store a token in the database for purpose [type] @@ -21,195 +20,196 @@ import { getSaltRounds } from '../config'; * @param {Types.ObjectId} obj.organizationId * @returns {String} token - the created token */ -const createTokenHelper = async ({ - type, - email, - phoneNumber, - organizationId +export const createTokenHelper = async ({ + type, + email, + phoneNumber, + organizationId, }: { - type: 'emailConfirmation' | 'emailMfa' | 'organizationInvitation' | 'passwordReset'; + type: + | "emailConfirmation" + | "emailMfa" + | "organizationInvitation" + | "passwordReset"; + email?: string; + phoneNumber?: string; + organizationId?: Types.ObjectId; +}) => { + let token, expiresAt, triesLeft; + // generate random token based on specified token use-case + // type [type] + switch (type) { + case TOKEN_EMAIL_CONFIRMATION: + // generate random 6-digit code + token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); + expiresAt = new Date(new Date().getTime() + 86400000); + break; + case TOKEN_EMAIL_MFA: + // generate random 6-digit code + token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); + triesLeft = 5; + expiresAt = new Date(new Date().getTime() + 300000); + break; + case TOKEN_EMAIL_ORG_INVITATION: + // generate random hex + token = crypto.randomBytes(16).toString("hex"); + expiresAt = new Date(new Date().getTime() + 259200000); + break; + case TOKEN_EMAIL_PASSWORD_RESET: + // generate random hex + token = crypto.randomBytes(16).toString("hex"); + expiresAt = new Date(new Date().getTime() + 86400000); + break; + default: + token = crypto.randomBytes(16).toString("hex"); + expiresAt = new Date(); + break; + } + + interface TokenDataQuery { + type: string; email?: string; phoneNumber?: string; - organizationId?: Types.ObjectId -}) => { - let token, expiresAt, triesLeft; - try { - // generate random token based on specified token use-case - // type [type] - switch (type) { - case TOKEN_EMAIL_CONFIRMATION: - // generate random 6-digit code - token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); - expiresAt = new Date((new Date()).getTime() + 86400000); - break; - case TOKEN_EMAIL_MFA: - // generate random 6-digit code - token = String(crypto.randomInt(Math.pow(10, 5), Math.pow(10, 6) - 1)); - triesLeft = 5; - expiresAt = new Date((new Date()).getTime() + 300000); - break; - case TOKEN_EMAIL_ORG_INVITATION: - // generate random hex - token = crypto.randomBytes(16).toString('hex'); - expiresAt = new Date((new Date()).getTime() + 259200000); - break; - case TOKEN_EMAIL_PASSWORD_RESET: - // generate random hex - token = crypto.randomBytes(16).toString('hex'); - expiresAt = new Date((new Date()).getTime() + 86400000); - break; - default: - token = crypto.randomBytes(16).toString('hex'); - expiresAt = new Date(); - break; - } - - interface TokenDataQuery { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - } - - interface TokenDataUpdate { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - tokenHash: string; - triesLeft?: number; - expiresAt: Date; - } + organization?: Types.ObjectId; + } - const query: TokenDataQuery = { type }; - const update: TokenDataUpdate = { - type, - tokenHash: await bcrypt.hash(token, getSaltRounds()), - expiresAt - } + interface TokenDataUpdate { + type: string; + email?: string; + phoneNumber?: string; + organization?: Types.ObjectId; + tokenHash: string; + triesLeft?: number; + expiresAt: Date; + } - if (email) { - query.email = email; - update.email = email; - } - if (phoneNumber) { - query.phoneNumber = phoneNumber; - update.phoneNumber = phoneNumber; - } - if (organizationId) { - query.organization = organizationId - update.organization = organizationId - } - - if (triesLeft) { - update.triesLeft = triesLeft; - } - - await TokenData.findOneAndUpdate( - query, - update, - { - new: true, - upsert: true - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error( - "Failed to create token" - ); - } - - return token; -} + const query: TokenDataQuery = { type }; + const update: TokenDataUpdate = { + type, + tokenHash: await bcrypt.hash(token, await getSaltRounds()), + expiresAt, + }; + + if (email) { + query.email = email; + update.email = email; + } + if (phoneNumber) { + query.phoneNumber = phoneNumber; + update.phoneNumber = phoneNumber; + } + if (organizationId) { + query.organization = organizationId; + update.organization = organizationId; + } + + if (triesLeft) { + update.triesLeft = triesLeft; + } + + await TokenData.findOneAndUpdate(query, update, { + new: true, + upsert: true, + }); + + return token; +}; /** - * + * * @param {Object} obj * @param {String} obj.email - email associated with the token * @param {String} obj.token - value of the token */ -const validateTokenHelper = async ({ - type, - email, - phoneNumber, - organizationId, - token +export const validateTokenHelper = async ({ + type, + email, + phoneNumber, + organizationId, + token, }: { - type: 'emailConfirmation' | 'emailMfa' | 'organizationInvitation' | 'passwordReset'; + type: + | "emailConfirmation" + | "emailMfa" + | "organizationInvitation" + | "passwordReset"; + email?: string; + phoneNumber?: string; + organizationId?: Types.ObjectId; + token: string; +}) => { + interface Query { + type: string; email?: string; phoneNumber?: string; - organizationId?: Types.ObjectId; - token: string; -}) => { - interface Query { - type: string; - email?: string; - phoneNumber?: string; - organization?: Types.ObjectId; - } + organization?: Types.ObjectId; + } - const query: Query = { type }; + const query: Query = { type }; - if (email) { query.email = email; } - if (phoneNumber) { query.phoneNumber = phoneNumber; } - if (organizationId) { query.organization = organizationId; } + if (email) { + query.email = email; + } + if (phoneNumber) { + query.phoneNumber = phoneNumber; + } + if (organizationId) { + query.organization = organizationId; + } - const tokenData = await TokenData.findOne(query).select('+tokenHash'); - - if (!tokenData) throw new Error('Failed to find token to validate'); - - if (tokenData.expiresAt < new Date()) { - // case: token expired - await TokenData.findByIdAndDelete(tokenData._id); - throw UnauthorizedRequestError({ - message: 'MFA session expired. Please log in again', - context: { - code: 'mfa_expired' - } - }); - } + const tokenData = await TokenData.findOne(query).select("+tokenHash"); - const isValid = await bcrypt.compare(token, tokenData.tokenHash); - if (!isValid) { - // case: token is not valid - if (tokenData?.triesLeft !== undefined) { - // case: token has a try-limit - if (tokenData.triesLeft === 1) { - // case: token is out of tries - await TokenData.findByIdAndDelete(tokenData._id); - } else { - // case: token has more than 1 try left - await TokenData.findByIdAndUpdate(tokenData._id, { - triesLeft: tokenData.triesLeft - 1 - }, { - new: true - }); - } + if (!tokenData) throw new Error("Failed to find token to validate"); - throw UnauthorizedRequestError({ - message: 'MFA code is invalid', - context: { - code: 'mfa_invalid', - triesLeft: tokenData.triesLeft - 1 - } - }); - } - - throw UnauthorizedRequestError({ - message: 'MFA code is invalid', - context: { - code: 'mfa_invalid' - } - }); - } - - // case: token is valid + if (tokenData.expiresAt < new Date()) { + // case: token expired await TokenData.findByIdAndDelete(tokenData._id); -} + throw UnauthorizedRequestError({ + message: "MFA session expired. Please log in again", + context: { + code: "mfa_expired", + }, + }); + } -export { - createTokenHelper, - validateTokenHelper -} \ No newline at end of file + const isValid = await bcrypt.compare(token, tokenData.tokenHash); + if (!isValid) { + // case: token is not valid + if (tokenData?.triesLeft !== undefined) { + // case: token has a try-limit + if (tokenData.triesLeft === 1) { + // case: token is out of tries + await TokenData.findByIdAndDelete(tokenData._id); + } else { + // case: token has more than 1 try left + await TokenData.findByIdAndUpdate( + tokenData._id, + { + triesLeft: tokenData.triesLeft - 1, + }, + { + new: true, + } + ); + } + + throw UnauthorizedRequestError({ + message: "MFA code is invalid", + context: { + code: "mfa_invalid", + triesLeft: tokenData.triesLeft - 1, + }, + }); + } + + throw UnauthorizedRequestError({ + message: "MFA code is invalid", + context: { + code: "mfa_invalid", + }, + }); + } + + // case: token is valid + await TokenData.findByIdAndDelete(tokenData._id); +}; \ No newline at end of file diff --git a/backend/src/helpers/user.ts b/backend/src/helpers/user.ts index 932a4bd81..a69b72695 100644 --- a/backend/src/helpers/user.ts +++ b/backend/src/helpers/user.ts @@ -1,5 +1,7 @@ -import * as Sentry from '@sentry/node'; -import { IUser, User } from '../models'; +import { + IUser, + User, +} from '../models'; import { sendMail } from './nodemailer'; /** @@ -8,17 +10,10 @@ import { sendMail } from './nodemailer'; * @param {String} obj.email - email of user to initialize * @returns {Object} user - the initialized user */ -const setupAccount = async ({ email }: { email: string }) => { - let user; - try { - user = await new User({ - email - }).save(); - } catch (err) { - Sentry.setUser({ email }); - Sentry.captureException(err); - throw new Error('Failed to set up account'); - } +export const setupAccount = async ({ email }: { email: string }) => { + const user = await new User({ + email + }).save(); return user; }; @@ -41,7 +36,7 @@ const setupAccount = async ({ email }: { email: string }) => { * @param {String} obj.verifier - verifier for auth SRP * @returns {Object} user - the completed user */ -const completeAccount = async ({ +export const completeAccount = async ({ userId, firstName, lastName, @@ -70,34 +65,27 @@ const completeAccount = async ({ salt: string; verifier: string; }) => { - let user; - try { - const options = { - new: true - }; - user = await User.findByIdAndUpdate( - userId, - { - firstName, - lastName, - encryptionVersion, - protectedKey, - protectedKeyIV, - protectedKeyTag, - publicKey, - encryptedPrivateKey, - iv: encryptedPrivateKeyIV, - tag: encryptedPrivateKeyTag, - salt, - verifier - }, - options - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to complete account set up'); - } + const options = { + new: true + }; + const user = await User.findByIdAndUpdate( + userId, + { + firstName, + lastName, + encryptionVersion, + protectedKey, + protectedKeyIV, + protectedKeyTag, + publicKey, + encryptedPrivateKey, + iv: encryptedPrivateKeyIV, + tag: encryptedPrivateKeyTag, + salt, + verifier + }, + options + ); return user; }; @@ -109,7 +97,7 @@ const completeAccount = async ({ * @param {String} obj.ip - login ip address * @param {String} obj.userAgent - login user-agent */ -const checkUserDevice = async ({ +export const checkUserDevice = async ({ user, ip, userAgent @@ -144,6 +132,4 @@ const checkUserDevice = async ({ } }); } -} - -export { setupAccount, completeAccount, checkUserDevice }; +} \ No newline at end of file diff --git a/backend/src/helpers/workspace.ts b/backend/src/helpers/workspace.ts index b43252bf3..694540f86 100644 --- a/backend/src/helpers/workspace.ts +++ b/backend/src/helpers/workspace.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { Workspace, Bot, @@ -7,6 +6,8 @@ import { Secret } from '../models'; import { createBot } from '../helpers/bot'; +import { EELicenseService } from '../ee/services'; +import { SecretService } from '../services'; /** * Create a workspace with name [name] in organization with id [organizationId] @@ -15,30 +16,32 @@ import { createBot } from '../helpers/bot'; * @param {String} organizationId - id of organization to create workspace in * @param {Object} workspace - new workspace */ -const createWorkspace = async ({ +export const createWorkspace = async ({ name, organizationId }: { name: string; organizationId: string; }) => { - let workspace; - try { - // create workspace - workspace = await new Workspace({ - name, - organization: organizationId - }).save(); - - const bot = await createBot({ - name: 'Infisical Bot', - workspaceId: workspace._id.toString() - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to create workspace'); - } + // create workspace + const workspace = await new Workspace({ + name, + organization: organizationId, + autoCapitalization: true + }).save(); + + // initialize bot for workspace + await createBot({ + name: 'Infisical Bot', + workspaceId: workspace._id + }); + + // initialize blind index salt for workspace + await SecretService.createSecretBlindIndexData({ + workspaceId: workspace._id + }); + + await EELicenseService.refreshPlan(organizationId); return workspace; }; @@ -49,26 +52,18 @@ const createWorkspace = async ({ * @param {Object} obj * @param {String} obj.id - id of workspace to delete */ -const deleteWorkspace = async ({ id }: { id: string }) => { - try { - await Workspace.deleteOne({ _id: id }); - await Bot.deleteOne({ - workspace: id - }); - await Membership.deleteMany({ - workspace: id - }); - await Secret.deleteMany({ - workspace: id - }); - await Key.deleteMany({ - workspace: id - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to delete workspace'); - } +export const deleteWorkspace = async ({ id }: { id: string }) => { + await Workspace.deleteOne({ _id: id }); + await Bot.deleteOne({ + workspace: id + }); + await Membership.deleteMany({ + workspace: id + }); + await Secret.deleteMany({ + workspace: id + }); + await Key.deleteMany({ + workspace: id + }); }; - -export { createWorkspace, deleteWorkspace }; diff --git a/backend/src/index.ts b/backend/src/index.ts index 03534a927..af3e0b24b 100644 --- a/backend/src/index.ts +++ b/backend/src/index.ts @@ -1,183 +1,185 @@ -import mongoose from 'mongoose'; -import dotenv from 'dotenv'; +import dotenv from "dotenv"; dotenv.config(); -import infisical from 'infisical-node'; -import express from 'express'; -import helmet from 'helmet'; -import cors from 'cors'; -import * as Sentry from '@sentry/node'; -import { DatabaseService } from './services'; -import { setUpHealthEndpoint } from './services/health'; -import { initSmtp } from './services/smtp'; -import { logTelemetryMessage } from './services'; -import { setTransporter } from './helpers/nodemailer'; -import { createTestUserForDevelopment } from './utils/addDevelopmentUser'; +import express from "express"; // eslint-disable-next-line @typescript-eslint/no-var-requires -const { patchRouterParam } = require('./utils/patchAsyncRoutes'); - -import cookieParser from 'cookie-parser'; -import swaggerUi = require('swagger-ui-express'); +require('express-async-errors'); +import helmet from "helmet"; +import cors from "cors"; +import { DatabaseService } from "./services"; +import { EELicenseService } from "./ee/services"; +import { setUpHealthEndpoint } from "./services/health"; +import cookieParser from "cookie-parser"; +import swaggerUi = require("swagger-ui-express"); // eslint-disable-next-line @typescript-eslint/no-var-requires -const swaggerFile = require('../spec.json'); +const swaggerFile = require("../spec.json"); // eslint-disable-next-line @typescript-eslint/no-var-requires -const requestIp = require('request-ip'); -import { apiLimiter } from './helpers/rateLimiter'; +import { apiLimiter } from "./helpers/rateLimiter"; import { - workspace as eeWorkspaceRouter, - secret as eeSecretRouter, - secretSnapshot as eeSecretSnapshotRouter, - action as eeActionRouter -} from './ee/routes/v1'; + workspace as eeWorkspaceRouter, + secret as eeSecretRouter, + secretSnapshot as eeSecretSnapshotRouter, + action as eeActionRouter, + organizations as eeOrganizationsRouter, + cloudProducts as eeCloudProductsRouter, +} from "./ee/routes/v1"; import { - signup as v1SignupRouter, - auth as v1AuthRouter, - bot as v1BotRouter, - organization as v1OrganizationRouter, - workspace as v1WorkspaceRouter, - membershipOrg as v1MembershipOrgRouter, - membership as v1MembershipRouter, - key as v1KeyRouter, - inviteOrg as v1InviteOrgRouter, - user as v1UserRouter, - userAction as v1UserActionRouter, - secret as v1SecretRouter, - serviceToken as v1ServiceTokenRouter, - password as v1PasswordRouter, - stripe as v1StripeRouter, - integration as v1IntegrationRouter, - integrationAuth as v1IntegrationAuthRouter -} from './routes/v1'; + signup as v1SignupRouter, + auth as v1AuthRouter, + bot as v1BotRouter, + organization as v1OrganizationRouter, + workspace as v1WorkspaceRouter, + membershipOrg as v1MembershipOrgRouter, + membership as v1MembershipRouter, + key as v1KeyRouter, + inviteOrg as v1InviteOrgRouter, + user as v1UserRouter, + userAction as v1UserActionRouter, + secret as v1SecretRouter, + serviceToken as v1ServiceTokenRouter, + password as v1PasswordRouter, + stripe as v1StripeRouter, + integration as v1IntegrationRouter, + integrationAuth as v1IntegrationAuthRouter, + secretsFolder as v1SecretsFolder, +} from "./routes/v1"; import { - signup as v2SignupRouter, - auth as v2AuthRouter, - users as v2UsersRouter, - organizations as v2OrganizationsRouter, - workspace as v2WorkspaceRouter, - secret as v2SecretRouter, // begin to phase out - secrets as v2SecretsRouter, - serviceTokenData as v2ServiceTokenDataRouter, - apiKeyData as v2APIKeyDataRouter, - environment as v2EnvironmentRouter, - tags as v2TagsRouter, -} from './routes/v2'; -import { healthCheck } from './routes/status'; -import { getLogger } from './utils/logger'; -import { RouteNotFoundError } from './utils/errors'; -import { requestErrorHandler } from './middleware/requestErrorHandler'; + signup as v2SignupRouter, + auth as v2AuthRouter, + users as v2UsersRouter, + organizations as v2OrganizationsRouter, + workspace as v2WorkspaceRouter, + secret as v2SecretRouter, // begin to phase out + secrets as v2SecretsRouter, + serviceTokenData as v2ServiceTokenDataRouter, + serviceAccounts as v2ServiceAccountsRouter, + apiKeyData as v2APIKeyDataRouter, + environment as v2EnvironmentRouter, + tags as v2TagsRouter, +} from "./routes/v2"; import { - getMongoURL, - getNodeEnv, - getPort, - getSentryDSN, - getSiteURL -} from './config'; + auth as v3AuthRouter, + secrets as v3SecretsRouter, + signup as v3SignupRouter, + workspaces as v3WorkspacesRouter, +} from "./routes/v3"; +import { healthCheck } from "./routes/status"; +import { getLogger } from "./utils/logger"; +import { RouteNotFoundError } from "./utils/errors"; +import { requestErrorHandler } from "./middleware/requestErrorHandler"; +import { getNodeEnv, getPort, getSiteURL } from "./config"; +import { setup } from "./utils/setup"; const main = async () => { - if (process.env.INFISICAL_TOKEN != "" || process.env.INFISICAL_TOKEN != undefined) { - await infisical.connect({ - token: process.env.INFISICAL_TOKEN! - }); - } + await setup(); - logTelemetryMessage(); - setTransporter(initSmtp()); + await EELicenseService.initGlobalFeatureSet(); - await DatabaseService.initDatabase(getMongoURL()); - if (getNodeEnv() !== 'test') { - Sentry.init({ - dsn: getSentryDSN(), - tracesSampleRate: 1.0, - debug: getNodeEnv() === 'production' ? false : true, - environment: getNodeEnv() - }); - } + const app = express(); + app.enable("trust proxy"); + app.use(express.json()); + app.use(cookieParser()); + app.use( + cors({ + credentials: true, + origin: await getSiteURL(), + }) + ); - patchRouterParam(); - const app = express(); - app.enable('trust proxy'); - app.use(express.json()); - app.use(cookieParser()); - app.use( - cors({ - credentials: true, - origin: getSiteURL() - }) + if ((await getNodeEnv()) === "production") { + // enable app-wide rate-limiting + helmet security + // in production + app.disable("x-powered-by"); + app.use(apiLimiter); + app.use(helmet()); + } + + app.use((req, res, next) => { + // default to IP address provided by Cloudflare + const cfIp = req.headers['cf-connecting-ip']; + req.realIP = Array.isArray(cfIp) ? cfIp[0] : (cfIp as string) || req.ip; + next(); + }); + + // (EE) routes + app.use("/api/v1/secret", eeSecretRouter); + app.use("/api/v1/secret-snapshot", eeSecretSnapshotRouter); + app.use("/api/v1/workspace", eeWorkspaceRouter); + app.use("/api/v1/action", eeActionRouter); + app.use("/api/v1/organizations", eeOrganizationsRouter); + app.use("/api/v1/cloud-products", eeCloudProductsRouter); + + // v1 routes (default) + app.use("/api/v1/signup", v1SignupRouter); + app.use("/api/v1/auth", v1AuthRouter); + app.use("/api/v1/bot", v1BotRouter); + app.use("/api/v1/user", v1UserRouter); + app.use("/api/v1/user-action", v1UserActionRouter); + app.use("/api/v1/organization", v1OrganizationRouter); + app.use("/api/v1/workspace", v1WorkspaceRouter); + app.use("/api/v1/membership-org", v1MembershipOrgRouter); + app.use("/api/v1/membership", v1MembershipRouter); + app.use("/api/v1/key", v1KeyRouter); + app.use("/api/v1/invite-org", v1InviteOrgRouter); + app.use("/api/v1/secret", v1SecretRouter); // deprecate + app.use("/api/v1/service-token", v1ServiceTokenRouter); // deprecate + app.use("/api/v1/password", v1PasswordRouter); + app.use("/api/v1/stripe", v1StripeRouter); + app.use("/api/v1/integration", v1IntegrationRouter); + app.use("/api/v1/integration-auth", v1IntegrationAuthRouter); + app.use("/api/v1/folders", v1SecretsFolder); + + // v2 routes (improvements) + app.use("/api/v2/signup", v2SignupRouter); + app.use("/api/v2/auth", v2AuthRouter); + app.use("/api/v2/users", v2UsersRouter); + app.use("/api/v2/organizations", v2OrganizationsRouter); + app.use("/api/v2/workspace", v2EnvironmentRouter); + app.use("/api/v2/workspace", v2TagsRouter); + app.use("/api/v2/workspace", v2WorkspaceRouter); + app.use("/api/v2/secret", v2SecretRouter); // deprecate + app.use("/api/v2/secrets", v2SecretsRouter); // note: in the process of moving to v3/secrets + app.use("/api/v2/service-token", v2ServiceTokenDataRouter); + app.use("/api/v2/service-accounts", v2ServiceAccountsRouter); // new + app.use("/api/v2/api-key", v2APIKeyDataRouter); + + // v3 routes (experimental) + app.use("/api/v3/auth", v3AuthRouter); + app.use("/api/v3/secrets", v3SecretsRouter); + app.use("/api/v3/workspaces", v3WorkspacesRouter); + app.use("/api/v3/signup", v3SignupRouter); + + // api docs + app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerFile)); + + // server status + app.use("/api", healthCheck); + + //* Handle unrouted requests and respond with proper error message as well as status code + app.use((req, res, next) => { + if (res.headersSent) return next(); + next( + RouteNotFoundError({ + message: `The requested source '(${req.method})${req.url}' was not found`, + }) ); + }); - app.use(requestIp.mw()); + app.use(requestErrorHandler); - if (getNodeEnv() === 'production') { - // enable app-wide rate-limiting + helmet security - // in production - app.disable('x-powered-by'); - app.use(apiLimiter); - app.use(helmet()); - } + const server = app.listen(await getPort(), async () => { + (await getLogger("backend-main")).info( + `Server started listening at port ${await getPort()}` + ); + }); - // (EE) routes - app.use('/api/v1/secret', eeSecretRouter); - app.use('/api/v1/secret-snapshot', eeSecretSnapshotRouter); - app.use('/api/v1/workspace', eeWorkspaceRouter); - app.use('/api/v1/action', eeActionRouter); + // await createTestUserForDevelopment(); + setUpHealthEndpoint(server); - // v1 routes - app.use('/api/v1/signup', v1SignupRouter); - app.use('/api/v1/auth', v1AuthRouter); - app.use('/api/v1/bot', v1BotRouter); - app.use('/api/v1/user', v1UserRouter); - app.use('/api/v1/user-action', v1UserActionRouter); - app.use('/api/v1/organization', v1OrganizationRouter); - app.use('/api/v1/workspace', v1WorkspaceRouter); - app.use('/api/v1/membership-org', v1MembershipOrgRouter); - app.use('/api/v1/membership', v1MembershipRouter); - app.use('/api/v1/key', v1KeyRouter); - app.use('/api/v1/invite-org', v1InviteOrgRouter); - app.use('/api/v1/secret', v1SecretRouter); - app.use('/api/v1/service-token', v1ServiceTokenRouter); // deprecated - app.use('/api/v1/password', v1PasswordRouter); - app.use('/api/v1/stripe', v1StripeRouter); - app.use('/api/v1/integration', v1IntegrationRouter); - app.use('/api/v1/integration-auth', v1IntegrationAuthRouter); + server.on("close", async () => { + await DatabaseService.closeDatabase(); + }); - // v2 routes - app.use('/api/v2/signup', v2SignupRouter); - app.use('/api/v2/auth', v2AuthRouter); - app.use('/api/v2/users', v2UsersRouter); - app.use('/api/v2/organizations', v2OrganizationsRouter); - app.use('/api/v2/workspace', v2EnvironmentRouter); - app.use('/api/v2/workspace', v2TagsRouter); - app.use('/api/v2/workspace', v2WorkspaceRouter); - app.use('/api/v2/secret', v2SecretRouter); // deprecated - app.use('/api/v2/secrets', v2SecretsRouter); - app.use('/api/v2/service-token', v2ServiceTokenDataRouter); // TODO: turn into plural route - app.use('/api/v2/api-key', v2APIKeyDataRouter); + return server; +}; - // api docs - app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerFile)) - - // Server status - app.use('/api', healthCheck) - - //* Handle unrouted requests and respond with proper error message as well as status code - app.use((req, res, next) => { - if (res.headersSent) return next(); - next(RouteNotFoundError({ message: `The requested source '(${req.method})${req.url}' was not found` })) - }) - - app.use(requestErrorHandler) - - const server = app.listen(getPort(), () => { - getLogger("backend-main").info(`Server started listening at port ${getPort()}`) - }); - - createTestUserForDevelopment(); - setUpHealthEndpoint(server); - - server.on('close', async () => { - await DatabaseService.closeDatabase(); - }) - - return server; -} - -export default main(); \ No newline at end of file +export default main(); diff --git a/backend/src/integrations/apps.ts b/backend/src/integrations/apps.ts index f7eef6263..f8ed77277 100644 --- a/backend/src/integrations/apps.ts +++ b/backend/src/integrations/apps.ts @@ -1,7 +1,6 @@ -import * as Sentry from "@sentry/node"; import { Octokit } from "@octokit/rest"; import { IIntegrationAuth } from "../models"; -import request from '../config/request'; +import { standardRequest } from "../config/request"; import { INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_AWS_PARAMETER_STORE, @@ -12,17 +11,23 @@ import { INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_CHECKLY, INTEGRATION_HEROKU_API_URL, INTEGRATION_GITLAB_API_URL, INTEGRATION_VERCEL_API_URL, INTEGRATION_NETLIFY_API_URL, INTEGRATION_RENDER_API_URL, + INTEGRATION_RAILWAY_API_URL, INTEGRATION_FLYIO_API_URL, INTEGRATION_CIRCLECI_API_URL, INTEGRATION_TRAVISCI_API_URL, + INTEGRATION_SUPABASE_API_URL, + INTEGRATION_CHECKLY_API_URL } from "../variables"; interface App { @@ -43,77 +48,85 @@ interface App { const getApps = async ({ integrationAuth, accessToken, - teamId + teamId, }: { integrationAuth: IIntegrationAuth; accessToken: string; teamId?: string; }) => { - let apps: App[] = []; - try { - switch (integrationAuth.integration) { - case INTEGRATION_AZURE_KEY_VAULT: - apps = []; - break; - case INTEGRATION_AWS_PARAMETER_STORE: - apps = []; - break; - case INTEGRATION_AWS_SECRET_MANAGER: - apps = []; - break; - case INTEGRATION_HEROKU: - apps = await getAppsHeroku({ - accessToken, - }); - break; - case INTEGRATION_VERCEL: - apps = await getAppsVercel({ - integrationAuth, - accessToken, - }); - break; - case INTEGRATION_NETLIFY: - apps = await getAppsNetlify({ - accessToken, - }); - break; - case INTEGRATION_GITHUB: - apps = await getAppsGithub({ - accessToken, - }); - break; - case INTEGRATION_GITLAB: - apps = await getAppsGitlab({ - accessToken, - teamId - }); - break; - case INTEGRATION_RENDER: - apps = await getAppsRender({ - accessToken, - }); - break; - case INTEGRATION_FLYIO: - apps = await getAppsFlyio({ - accessToken, - }); - break; - case INTEGRATION_CIRCLECI: - apps = await getAppsCircleCI({ - accessToken, - }); - break; - case INTEGRATION_TRAVISCI: - apps = await getAppsTravisCI({ - accessToken, - }) - break; - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get integration apps"); + switch (integrationAuth.integration) { + case INTEGRATION_AZURE_KEY_VAULT: + apps = []; + break; + case INTEGRATION_AWS_PARAMETER_STORE: + apps = []; + break; + case INTEGRATION_AWS_SECRET_MANAGER: + apps = []; + break; + case INTEGRATION_HEROKU: + apps = await getAppsHeroku({ + accessToken, + }); + break; + case INTEGRATION_VERCEL: + apps = await getAppsVercel({ + integrationAuth, + accessToken, + }); + break; + case INTEGRATION_NETLIFY: + apps = await getAppsNetlify({ + accessToken, + }); + break; + case INTEGRATION_GITHUB: + apps = await getAppsGithub({ + accessToken, + }); + break; + case INTEGRATION_GITLAB: + apps = await getAppsGitlab({ + accessToken, + teamId, + }); + break; + case INTEGRATION_RENDER: + apps = await getAppsRender({ + accessToken, + }); + break; + case INTEGRATION_RAILWAY: + apps = await getAppsRailway({ + accessToken, + }); + break; + case INTEGRATION_FLYIO: + apps = await getAppsFlyio({ + accessToken, + }); + break; + case INTEGRATION_CIRCLECI: + apps = await getAppsCircleCI({ + accessToken, + }); + break; + case INTEGRATION_TRAVISCI: + apps = await getAppsTravisCI({ + accessToken, + }); + break; + case INTEGRATION_SUPABASE: + apps = await getAppsSupabase({ + accessToken, + }); + break; + case INTEGRATION_CHECKLY: + apps = await getAppsCheckly({ + accessToken, + }); + break; } return apps; @@ -127,25 +140,18 @@ const getApps = async ({ * @returns {String} apps.name - name of Heroku app */ const getAppsHeroku = async ({ accessToken }: { accessToken: string }) => { - let apps; - try { - const res = ( - await request.get(`${INTEGRATION_HEROKU_API_URL}/apps`, { - headers: { - Accept: "application/vnd.heroku+json; version=3", - Authorization: `Bearer ${accessToken}`, - }, - }) - ).data; + const res = ( + await standardRequest.get(`${INTEGRATION_HEROKU_API_URL}/apps`, { + headers: { + Accept: "application/vnd.heroku+json; version=3", + Authorization: `Bearer ${accessToken}`, + }, + }) + ).data; - apps = res.map((a: any) => ({ - name: a.name, - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Heroku integration apps"); - } + const apps = res.map((a: any) => ({ + name: a.name, + })); return apps; }; @@ -164,32 +170,26 @@ const getAppsVercel = async ({ integrationAuth: IIntegrationAuth; accessToken: string; }) => { - let apps; - try { - const res = ( - await request.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects`, { - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - ...(integrationAuth?.teamId - ? { - params: { - teamId: integrationAuth.teamId, - }, - } - : {}), - }) - ).data; + const res = ( + await standardRequest.get(`${INTEGRATION_VERCEL_API_URL}/v9/projects`, { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, + ...(integrationAuth?.teamId + ? { + params: { + teamId: integrationAuth.teamId, + }, + } + : {}), + }) + ).data; - apps = res.projects.map((a: any) => ({ - name: a.name, - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Vercel integration apps"); - } + const apps = res.projects.map((a: any) => ({ + name: a.name, + appId: a.id, + })); return apps; }; @@ -203,43 +203,41 @@ const getAppsVercel = async ({ */ const getAppsNetlify = async ({ accessToken }: { accessToken: string }) => { const apps: any = []; - try { - let page = 1; - const perPage = 10; - let hasMorePages = true; - - // paginate through all sites - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage) - }); + let page = 1; + const perPage = 10; + let hasMorePages = true; - const { data } = await request.get(`${INTEGRATION_NETLIFY_API_URL}/api/v1/sites`, { + // paginate through all sites + while (hasMorePages) { + const params = new URLSearchParams({ + page: String(page), + per_page: String(perPage), + filter: 'all' + }); + + const { data } = await standardRequest.get( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/sites`, + { params, headers: { Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - } - }); - - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.site_id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; + "Accept-Encoding": "application/json", + }, } + ); - page++; + data.map((a: any) => { + apps.push({ + name: a.name, + appId: a.site_id, + }); + }); + + if (data.length < perPage) { + hasMorePages = false; } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Netlify integration apps"); + + page++; } return apps; @@ -253,32 +251,58 @@ const getAppsNetlify = async ({ accessToken }: { accessToken: string }) => { * @returns {String} apps.name - name of Github site */ const getAppsGithub = async ({ accessToken }: { accessToken: string }) => { - let apps; - try { - const octokit = new Octokit({ - auth: accessToken, - }); + interface GitHubApp { + id: string; + name: string; + permissions: { + admin: boolean; + }; + owner: { + login: string; + }; + } - const repos = ( - await octokit.request( + const octokit = new Octokit({ + auth: accessToken, + }); + + const getAllRepos = async () => { + let repos: GitHubApp[] = []; + let page = 1; + const per_page = 100; + let hasMore = true; + + while (hasMore) { + const response = await octokit.request( "GET /user/repos{?visibility,affiliation,type,sort,direction,per_page,page,since,before}", { - per_page: 100, + per_page, + page, } - ) - ).data; + ); - apps = repos - .filter((a: any) => a.permissions.admin === true) - .map((a: any) => ({ + if (response.data.length > 0) { + repos = repos.concat(response.data); + page++; + } else { + hasMore = false; + } + } + + return repos; + }; + + const repos = await getAllRepos(); + + const apps = repos + .filter((a: GitHubApp) => a.permissions.admin === true) + .map((a: GitHubApp) => { + return { + appId: a.id, name: a.name, owner: a.owner.login, - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Github repos"); - } + }; + }); return apps; }; @@ -292,29 +316,74 @@ const getAppsGithub = async ({ accessToken }: { accessToken: string }) => { * @returns {String} apps.appId - id of Render service */ const getAppsRender = async ({ accessToken }: { accessToken: string }) => { - let apps: any; - try { - const res = ( - await request.get(`${INTEGRATION_RENDER_API_URL}/v1/services`, { - headers: { - Authorization: `Bearer ${accessToken}`, - Accept: 'application/json', - 'Accept-Encoding': 'application/json', - }, - }) - ).data; - - apps = res - .map((a: any) => ({ - name: a.service.name, - appId: a.service.id - })); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Render services"); - } + const res = ( + await standardRequest.get(`${INTEGRATION_RENDER_API_URL}/v1/services`, { + headers: { + Authorization: `Bearer ${accessToken}`, + Accept: "application/json", + "Accept-Encoding": "application/json", + }, + }) + ).data; + + const apps = res.map((a: any) => ({ + name: a.service.name, + appId: a.service.id, + })); + + return apps; +}; + +/** + * Return list of projects for Railway integration + * @param {Object} obj + * @param {String} obj.accessToken - access token for Railway API + * @returns {Object[]} apps - names and ids of Railway services + * @returns {String} apps.name - name of Railway project + * @returns {String} apps.appId - id of Railway project + * + */ +const getAppsRailway = async ({ accessToken }: { accessToken: string }) => { + const query = ` + query GetProjects($userId: String, $teamId: String) { + projects(userId: $userId, teamId: $teamId) { + edges { + node { + id + name + } + } + } + } + `; + + const variables = {}; + + const { + data: { + data: { + projects: { edges }, + }, + }, + } = await standardRequest.post( + INTEGRATION_RAILWAY_API_URL, + { + query, + variables, + }, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + "Accept-Encoding": "application/json", + }, + } + ); + + const apps = edges.map((e: any) => ({ + name: e.node.name, + appId: e.node.id, + })); return apps; }; @@ -327,41 +396,40 @@ const getAppsRender = async ({ accessToken }: { accessToken: string }) => { * @returns {String} apps.name - name of Fly.io apps */ const getAppsFlyio = async ({ accessToken }: { accessToken: string }) => { - let apps; - try { - const query = ` - query($role: String) { - apps(type: "container", first: 400, role: $role) { - nodes { - id - name - hostname - } + const query = ` + query($role: String) { + apps(type: "container", first: 400, role: $role) { + nodes { + id + name + hostname } } - `; + } + `; - const res = (await request.post(INTEGRATION_FLYIO_API_URL, { - query, - variables: { - role: null, + const res = ( + await standardRequest.post( + INTEGRATION_FLYIO_API_URL, + { + query, + variables: { + role: null, + }, }, - }, { - headers: { - Authorization: "Bearer " + accessToken, - 'Accept': 'application/json', - 'Accept-Encoding': 'application/json', - }, - })).data.data.apps.nodes; + { + headers: { + Authorization: "Bearer " + accessToken, + Accept: "application/json", + "Accept-Encoding": "application/json", + }, + } + ) + ).data.data.apps.nodes; - apps = res.map((a: any) => ({ - name: a.name, - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get Fly.io apps"); - } + const apps = res.map((a: any) => ({ + name: a.name, + })); return apps; }; @@ -374,63 +442,43 @@ const getAppsFlyio = async ({ accessToken }: { accessToken: string }) => { * @returns {String} apps.name - name of CircleCI apps */ const getAppsCircleCI = async ({ accessToken }: { accessToken: string }) => { - let apps: any; - try { - const res = ( - await request.get( - `${INTEGRATION_CIRCLECI_API_URL}/v1.1/projects`, - { - headers: { - "Circle-Token": accessToken, - "Accept-Encoding": "application/json", - }, - } - ) - ).data + const res = ( + await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v1.1/projects`, { + headers: { + "Circle-Token": accessToken, + "Accept-Encoding": "application/json", + }, + }) + ).data; + + const apps = res?.map((a: any) => { + return { + name: a?.reponame, + }; + }); - apps = res?.map((a: any) => { - return { - name: a?.reponame - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get CircleCI projects"); - } - return apps; }; const getAppsTravisCI = async ({ accessToken }: { accessToken: string }) => { - let apps: any; - try { - const res = ( - await request.get( - `${INTEGRATION_TRAVISCI_API_URL}/repos`, - { - headers: { - "Authorization": `token ${accessToken}`, - "Accept-Encoding": "application/json", - }, - } - ) - ).data; + const res = ( + await standardRequest.get(`${INTEGRATION_TRAVISCI_API_URL}/repos`, { + headers: { + Authorization: `token ${accessToken}`, + "Accept-Encoding": "application/json", + }, + }) + ).data; + + const apps = res?.map((a: any) => { + return { + name: a?.slug?.split("/")[1], + appId: a?.id, + }; + }); - apps = res?.map((a: any) => { - return { - name: a?.slug?.split("/")[1], - appId: a?.id, - } - }); - }catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get TravisCI projects"); - } - return apps; -} +}; /** * Return list of repositories for GitLab integration @@ -439,110 +487,153 @@ const getAppsTravisCI = async ({ accessToken }: { accessToken: string }) => { * @returns {Object[]} apps - names of GitLab sites * @returns {String} apps.name - name of GitLab site */ -const getAppsGitlab = async ({ +const getAppsGitlab = async ({ accessToken, - teamId + teamId, }: { accessToken: string; teamId?: string; }) => { const apps: App[] = []; - + let page = 1; const perPage = 10; let hasMorePages = true; - try { - if (teamId) { - // case: fetch projects for group with id [teamId] in GitLab - - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage) - }); + if (teamId) { + // case: fetch projects for group with id [teamId] in GitLab - const { data } = ( - await request.get( - `${INTEGRATION_GITLAB_API_URL}/v4/groups/${teamId}/projects`, - { - params, - headers: { - "Authorization": `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - }, - } - ) - ); + while (hasMorePages) { + const params = new URLSearchParams({ + page: String(page), + per_page: String(perPage), + }); - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; + const { data } = await standardRequest.get( + `${INTEGRATION_GITLAB_API_URL}/v4/groups/${teamId}/projects`, + { + params, + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, } - - page++; - } - } else { - // case: fetch projects for individual in GitLab - - const { id } = ( - await request.get( - `${INTEGRATION_GITLAB_API_URL}/v4/user`, - { - headers: { - "Authorization": `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - }, - } - ) - ).data; - - while (hasMorePages) { - const params = new URLSearchParams({ - page: String(page), - per_page: String(perPage) + ); + + data.map((a: any) => { + apps.push({ + name: a.name, + appId: a.id, }); + }); - const { data } = ( - await request.get( - `${INTEGRATION_GITLAB_API_URL}/v4/users/${id}/projects`, - { - params, - headers: { - "Authorization": `Bearer ${accessToken}`, - "Accept-Encoding": "application/json", - }, - } - ) - ); - - data.map((a: any) => { - apps.push({ - name: a.name, - appId: a.id - }); - }); - - if (data.length < perPage) { - hasMorePages = false; - } - - page++; + if (data.length < perPage) { + hasMorePages = false; } + + page++; + } + } else { + // case: fetch projects for individual in GitLab + + const { id } = ( + await standardRequest.get(`${INTEGRATION_GITLAB_API_URL}/v4/user`, { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, + }) + ).data; + + while (hasMorePages) { + const params = new URLSearchParams({ + page: String(page), + per_page: String(perPage), + }); + + const { data } = await standardRequest.get( + `${INTEGRATION_GITLAB_API_URL}/v4/users/${id}/projects`, + { + params, + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, + } + ); + + data.map((a: any) => { + apps.push({ + name: a.name, + appId: a.id, + }); + }); + + if (data.length < perPage) { + hasMorePages = false; + } + + page++; } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get GitLab projects"); } - + return apps; -} +}; + +/** + * Return list of projects for Supabase integration + * @param {Object} obj + * @param {String} obj.accessToken - access token for Supabase API + * @returns {Object[]} apps - names of Supabase apps + * @returns {String} apps.name - name of Supabase app + */ +const getAppsSupabase = async ({ accessToken }: { accessToken: string }) => { + const { data } = await standardRequest.get( + `${INTEGRATION_SUPABASE_API_URL}/v1/projects`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }, + } + ); + + const apps = data.map((a: any) => { + return { + name: a.name, + appId: a.id, + }; + }); + + return apps; +}; + +/** + * Return list of projects for the Checkly integration + * @param {Object} obj + * @param {String} obj.accessToken - api key for the Checkly API + * @returns {Object[]} apps - Сheckly accounts + * @returns {String} apps.name - name of Checkly account + */ +const getAppsCheckly = async ({ accessToken }: { accessToken: string }) => { + const { data } = await standardRequest.get( + `${INTEGRATION_CHECKLY_API_URL}/v1/accounts`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept": "application/json", + }, + } + ); + + const apps = data.map((a: any) => { + return { + name: a.name, + appId: a.id, + }; + }); + + return apps; +}; export { getApps }; diff --git a/backend/src/integrations/exchange.ts b/backend/src/integrations/exchange.ts index 1dccb03d0..a4d5f5b06 100644 --- a/backend/src/integrations/exchange.ts +++ b/backend/src/integrations/exchange.ts @@ -1,5 +1,4 @@ -import * as Sentry from '@sentry/node'; -import request from '../config/request'; +import { standardRequest } from "../config/request"; import { INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_HEROKU, @@ -12,8 +11,8 @@ import { INTEGRATION_VERCEL_TOKEN_URL, INTEGRATION_NETLIFY_TOKEN_URL, INTEGRATION_GITHUB_TOKEN_URL, - INTEGRATION_GITLAB_TOKEN_URL -} from '../variables'; + INTEGRATION_GITLAB_TOKEN_URL, +} from "../variables"; import { getSiteURL, getClientIdAzure, @@ -26,8 +25,8 @@ import { getClientIdGitHub, getClientSecretGitHub, getClientIdGitLab, - getClientSecretGitLab -} from '../config'; + getClientSecretGitLab, +} from "../config"; interface ExchangeCodeAzureResponse { token_type: string; @@ -93,49 +92,43 @@ interface ExchangeCodeGitlabResponse { */ const exchangeCode = async ({ integration, - code + code, }: { integration: string; code: string; }) => { let obj = {} as any; - try { - switch (integration) { - case INTEGRATION_AZURE_KEY_VAULT: - obj = await exchangeCodeAzure({ - code - }); - break; - case INTEGRATION_HEROKU: - obj = await exchangeCodeHeroku({ - code - }); - break; - case INTEGRATION_VERCEL: - obj = await exchangeCodeVercel({ - code - }); - break; - case INTEGRATION_NETLIFY: - obj = await exchangeCodeNetlify({ - code - }); - break; - case INTEGRATION_GITHUB: - obj = await exchangeCodeGithub({ - code - }); - break; - case INTEGRATION_GITLAB: - obj = await exchangeCodeGitlab({ - code - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange'); + switch (integration) { + case INTEGRATION_AZURE_KEY_VAULT: + obj = await exchangeCodeAzure({ + code, + }); + break; + case INTEGRATION_HEROKU: + obj = await exchangeCodeHeroku({ + code, + }); + break; + case INTEGRATION_VERCEL: + obj = await exchangeCodeVercel({ + code, + }); + break; + case INTEGRATION_NETLIFY: + obj = await exchangeCodeNetlify({ + code, + }); + break; + case INTEGRATION_GITHUB: + obj = await exchangeCodeGithub({ + code, + }); + break; + case INTEGRATION_GITLAB: + obj = await exchangeCodeGitlab({ + code, + }); } return obj; @@ -143,43 +136,33 @@ const exchangeCode = async ({ /** * Return [accessToken] for Azure OAuth2 code-token exchange - * @param param0 + * @param param0 */ -const exchangeCodeAzure = async ({ - code -}: { - code: string; -}) => { +const exchangeCodeAzure = async ({ code }: { code: string }) => { const accessExpiresAt = new Date(); - let res: ExchangeCodeAzureResponse; - try { - res = (await request.post( + + const res: ExchangeCodeAzureResponse = ( + await standardRequest.post( INTEGRATION_AZURE_TOKEN_URL, new URLSearchParams({ - grant_type: 'authorization_code', + grant_type: "authorization_code", code: code, - scope: 'https://vault.azure.net/.default openid offline_access', - client_id: getClientIdAzure(), - client_secret: getClientSecretAzure(), - redirect_uri: `${getSiteURL()}/integrations/azure-key-vault/oauth2/callback` + scope: "https://vault.azure.net/.default openid offline_access", + client_id: await getClientIdAzure(), + client_secret: await getClientSecretAzure(), + redirect_uri: `${await getSiteURL()}/integrations/azure-key-vault/oauth2/callback`, } as any) - )).data; + ) + ).data; - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + res.expires_in - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange with Azure'); - } + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - return ({ + return { accessToken: res.access_token, refreshToken: res.refresh_token, - accessExpiresAt - }); -} + accessExpiresAt, + }; +}; /** * Return [accessToken], [accessExpiresAt], and [refreshToken] for Heroku @@ -191,38 +174,28 @@ const exchangeCodeAzure = async ({ * @returns {String} obj2.refreshToken - refresh token for Heroku API * @returns {Date} obj2.accessExpiresAt - date of expiration for access token */ -const exchangeCodeHeroku = async ({ - code -}: { - code: string; -}) => { - let res: ExchangeCodeHerokuResponse; +const exchangeCodeHeroku = async ({ code }: { code: string }) => { const accessExpiresAt = new Date(); - try { - res = (await request.post( + + const res: ExchangeCodeHerokuResponse = ( + await standardRequest.post( INTEGRATION_HEROKU_TOKEN_URL, new URLSearchParams({ - grant_type: 'authorization_code', + grant_type: "authorization_code", code: code, - client_secret: getClientSecretHeroku() + client_secret: await getClientSecretHeroku(), } as any) - )).data; + ) + ).data; - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + res.expires_in - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange with Heroku'); - } + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + res.expires_in); - return ({ + return { accessToken: res.access_token, refreshToken: res.refresh_token, - accessExpiresAt - }); -} + accessExpiresAt, + }; +}; /** * Return [accessToken], [accessExpiresAt], and [refreshToken] for Vercel @@ -235,30 +208,23 @@ const exchangeCodeHeroku = async ({ * @returns {Date} obj2.accessExpiresAt - date of expiration for access token */ const exchangeCodeVercel = async ({ code }: { code: string }) => { - let res: ExchangeCodeVercelResponse; - try { - res = ( - await request.post( - INTEGRATION_VERCEL_TOKEN_URL, - new URLSearchParams({ - code: code, - client_id: getClientIdVercel(), - client_secret: getClientSecretVercel(), - redirect_uri: `${getSiteURL()}/integrations/vercel/oauth2/callback` - } as any) - ) - ).data; - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error(`Failed OAuth2 code-token exchange with Vercel [err=${err}]`); - } + const res: ExchangeCodeVercelResponse = ( + await standardRequest.post( + INTEGRATION_VERCEL_TOKEN_URL, + new URLSearchParams({ + code: code, + client_id: await getClientIdVercel(), + client_secret: await getClientSecretVercel(), + redirect_uri: `${await getSiteURL()}/integrations/vercel/oauth2/callback`, + } as any) + ) + ).data; return { accessToken: res.access_token, refreshToken: null, accessExpiresAt: null, - teamId: res.team_id + teamId: res.team_id, }; }; @@ -273,47 +239,39 @@ const exchangeCodeVercel = async ({ code }: { code: string }) => { * @returns {Date} obj2.accessExpiresAt - date of expiration for access token */ const exchangeCodeNetlify = async ({ code }: { code: string }) => { - let res: ExchangeCodeNetlifyResponse; - let accountId; - try { - res = ( - await request.post( - INTEGRATION_NETLIFY_TOKEN_URL, - new URLSearchParams({ - grant_type: 'authorization_code', - code: code, - client_id: getClientIdNetlify(), - client_secret: getClientSecretNetlify(), - redirect_uri: `${getSiteURL()}/integrations/netlify/oauth2/callback` - } as any) - ) - ).data; + const res: ExchangeCodeNetlifyResponse = ( + await standardRequest.post( + INTEGRATION_NETLIFY_TOKEN_URL, + new URLSearchParams({ + grant_type: "authorization_code", + code: code, + client_id: await getClientIdNetlify(), + client_secret: await getClientSecretNetlify(), + redirect_uri: `${await getSiteURL()}/integrations/netlify/oauth2/callback`, + } as any) + ) + ).data; - const res2 = await request.get('https://api.netlify.com/api/v1/sites', { + const res2 = await standardRequest.get("https://api.netlify.com/api/v1/sites", { + headers: { + Authorization: `Bearer ${res.access_token}`, + }, + }); + + const res3 = ( + await standardRequest.get("https://api.netlify.com/api/v1/accounts", { headers: { - Authorization: `Bearer ${res.access_token}` - } - }); + Authorization: `Bearer ${res.access_token}`, + }, + }) + ).data; - const res3 = ( - await request.get('https://api.netlify.com/api/v1/accounts', { - headers: { - Authorization: `Bearer ${res.access_token}` - } - }) - ).data; - - accountId = res3[0].id; - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange with Netlify'); - } + const accountId = res3[0].id; return { accessToken: res.access_token, refreshToken: res.refresh_token, - accountId + accountId, }; }; @@ -328,33 +286,25 @@ const exchangeCodeNetlify = async ({ code }: { code: string }) => { * @returns {Date} obj2.accessExpiresAt - date of expiration for access token */ const exchangeCodeGithub = async ({ code }: { code: string }) => { - let res: ExchangeCodeGithubResponse; - try { - res = ( - await request.get(INTEGRATION_GITHUB_TOKEN_URL, { - params: { - client_id: getClientIdGitHub(), - client_secret: getClientSecretGitHub(), - code: code, - redirect_uri: `${getSiteURL()}/integrations/github/oauth2/callback` - }, - headers: { - 'Accept': 'application/json', - 'Accept-Encoding': 'application/json' - } - }) - ).data; - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange with Github'); - } + const res: ExchangeCodeGithubResponse = ( + await standardRequest.get(INTEGRATION_GITHUB_TOKEN_URL, { + params: { + client_id: await getClientIdGitHub(), + client_secret: await getClientSecretGitHub(), + code: code, + redirect_uri: `${await getSiteURL()}/integrations/github/oauth2/callback`, + }, + headers: { + Accept: "application/json", + "Accept-Encoding": "application/json", + }, + }) + ).data; return { accessToken: res.access_token, refreshToken: null, - accessExpiresAt: null + accessExpiresAt: null, }; }; @@ -369,42 +319,32 @@ const exchangeCodeGithub = async ({ code }: { code: string }) => { * @returns {Date} obj2.accessExpiresAt - date of expiration for access token */ const exchangeCodeGitlab = async ({ code }: { code: string }) => { - let res: ExchangeCodeGitlabResponse; const accessExpiresAt = new Date(); - - try { - res = ( - await request.post( - INTEGRATION_GITLAB_TOKEN_URL, - new URLSearchParams({ - grant_type: 'authorization_code', - code: code, - client_id: getClientIdGitLab(), - client_secret: getClientSecretGitLab(), - redirect_uri: `${getSiteURL()}/integrations/gitlab/oauth2/callback` - } as any), - { - headers: { - "Accept-Encoding": "application/json", - } - } - ) - ).data; - - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + res.expires_in - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed OAuth2 code-token exchange with Gitlab'); - } + const res: ExchangeCodeGitlabResponse = ( + await standardRequest.post( + INTEGRATION_GITLAB_TOKEN_URL, + new URLSearchParams({ + grant_type: "authorization_code", + code: code, + client_id: await getClientIdGitLab(), + client_secret: await getClientSecretGitLab(), + redirect_uri: `${await getSiteURL()}/integrations/gitlab/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 + accessExpiresAt, }; -} +}; export { exchangeCode }; diff --git a/backend/src/integrations/refresh.ts b/backend/src/integrations/refresh.ts index a0aea080e..0c401bf15 100644 --- a/backend/src/integrations/refresh.ts +++ b/backend/src/integrations/refresh.ts @@ -1,29 +1,24 @@ -import * as Sentry from '@sentry/node'; -import request from '../config/request'; +import { standardRequest } from "../config/request"; +import { IIntegrationAuth } from "../models"; import { - IIntegrationAuth -} from '../models'; -import { - INTEGRATION_AZURE_KEY_VAULT, + INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_HEROKU, INTEGRATION_GITLAB, -} from '../variables'; +} from "../variables"; import { INTEGRATION_AZURE_TOKEN_URL, INTEGRATION_HEROKU_TOKEN_URL, - INTEGRATION_GITLAB_TOKEN_URL -} from '../variables'; -import { - IntegrationService -} from '../services'; + INTEGRATION_GITLAB_TOKEN_URL, +} from "../variables"; +import { IntegrationService } from "../services"; import { getSiteURL, getClientIdAzure, getClientSecretAzure, getClientSecretHeroku, getClientIdGitLab, - getClientSecretGitLab -} from '../config'; + getClientSecretGitLab, +} from "../config"; interface RefreshTokenAzureResponse { token_type: string; @@ -60,60 +55,57 @@ interface RefreshTokenGitLabResponse { */ const exchangeRefresh = async ({ integrationAuth, - refreshToken + refreshToken, }: { integrationAuth: IIntegrationAuth; refreshToken: string; }) => { - interface TokenDetails { accessToken: string; refreshToken: string; accessExpiresAt: Date; } - + let tokenDetails: TokenDetails; - try { - switch (integrationAuth.integration) { - case INTEGRATION_AZURE_KEY_VAULT: - tokenDetails = await exchangeRefreshAzure({ - refreshToken - }); - break; - case INTEGRATION_HEROKU: - tokenDetails = await exchangeRefreshHeroku({ - refreshToken - }); - break; - case INTEGRATION_GITLAB: - tokenDetails = await exchangeRefreshGitLab({ - refreshToken - }); - break; - default: - throw new Error('Failed to exchange token for incompatible integration'); - } - - if (tokenDetails?.accessToken && tokenDetails?.refreshToken && tokenDetails?.accessExpiresAt) { - await IntegrationService.setIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString(), - accessId: null, - accessToken: tokenDetails.accessToken, - accessExpiresAt: tokenDetails.accessExpiresAt + switch (integrationAuth.integration) { + case INTEGRATION_AZURE_KEY_VAULT: + tokenDetails = await exchangeRefreshAzure({ + refreshToken, }); - - await IntegrationService.setIntegrationAuthRefresh({ - integrationAuthId: integrationAuth._id.toString(), - refreshToken: tokenDetails.refreshToken + break; + case INTEGRATION_HEROKU: + tokenDetails = await exchangeRefreshHeroku({ + refreshToken, }); - } - - return tokenDetails.accessToken; - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get new OAuth2 access token'); + break; + case INTEGRATION_GITLAB: + tokenDetails = await exchangeRefreshGitLab({ + refreshToken, + }); + break; + default: + throw new Error("Failed to exchange token for incompatible integration"); } + + if ( + tokenDetails?.accessToken && + tokenDetails?.refreshToken && + tokenDetails?.accessExpiresAt + ) { + await IntegrationService.setIntegrationAuthAccess({ + integrationAuthId: integrationAuth._id.toString(), + accessId: null, + accessToken: tokenDetails.accessToken, + accessExpiresAt: tokenDetails.accessExpiresAt, + }); + + await IntegrationService.setIntegrationAuthRefresh({ + integrationAuthId: integrationAuth._id.toString(), + refreshToken: tokenDetails.refreshToken, + }); + } + + return tokenDetails.accessToken; }; /** @@ -124,38 +116,30 @@ const exchangeRefresh = async ({ * @returns */ const exchangeRefreshAzure = async ({ - refreshToken + refreshToken, }: { refreshToken: string; }) => { - try { - const accessExpiresAt = new Date(); - const { data }: { data: RefreshTokenAzureResponse } = await request.post( - INTEGRATION_AZURE_TOKEN_URL, - new URLSearchParams({ - client_id: getClientIdAzure(), - scope: 'openid offline_access', - refresh_token: refreshToken, - grant_type: 'refresh_token', - client_secret: getClientSecretAzure() - } as any) - ); - - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + data.expires_in - ); + const accessExpiresAt = new Date(); + const { data }: { data: RefreshTokenAzureResponse } = await standardRequest.post( + INTEGRATION_AZURE_TOKEN_URL, + new URLSearchParams({ + client_id: await getClientIdAzure(), + scope: "openid offline_access", + refresh_token: refreshToken, + grant_type: "refresh_token", + client_secret: await getClientSecretAzure(), + } as any) + ); - return ({ - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get refresh OAuth2 access token for Azure'); - } -} + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); + + return { + accessToken: data.access_token, + refreshToken: data.refresh_token, + accessExpiresAt, + }; +}; /** * Return new access token by exchanging refresh token [refreshToken] for the @@ -165,39 +149,31 @@ const exchangeRefreshAzure = async ({ * @returns */ const exchangeRefreshHeroku = async ({ - refreshToken + refreshToken, }: { refreshToken: string; }) => { - try { - const accessExpiresAt = new Date(); - const { - data - }: { - data: RefreshTokenHerokuResponse - } = await request.post( - INTEGRATION_HEROKU_TOKEN_URL, - new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: refreshToken, - client_secret: getClientSecretHeroku() - } as any) - ); + const accessExpiresAt = new Date(); + const { + data, + }: { + data: RefreshTokenHerokuResponse; + } = await standardRequest.post( + INTEGRATION_HEROKU_TOKEN_URL, + new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: refreshToken, + client_secret: await getClientSecretHeroku(), + } as any) + ); - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + data.expires_in - ); + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - return ({ - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to refresh OAuth2 access token for Heroku'); - } + return { + accessToken: data.access_token, + refreshToken: data.refresh_token, + accessExpiresAt, + }; }; /** @@ -208,45 +184,38 @@ const exchangeRefreshHeroku = async ({ * @returns */ const exchangeRefreshGitLab = async ({ - refreshToken + refreshToken, }: { refreshToken: string; }) => { - try { - const accessExpiresAt = new Date(); - const { - data - }: { - data: RefreshTokenGitLabResponse - } = await request.post( - INTEGRATION_GITLAB_TOKEN_URL, - new URLSearchParams({ - grant_type: 'refresh_token', - refresh_token: refreshToken, - client_id: getClientIdGitLab, - client_secret: getClientSecretGitLab(), - redirect_uri: `${getSiteURL()}/integrations/gitlab/oauth2/callback` - } as any), - { - headers: { - "Accept-Encoding": "application/json", - } - }); + const accessExpiresAt = new Date(); + const { + data, + }: { + data: RefreshTokenGitLabResponse; + } = await standardRequest.post( + INTEGRATION_GITLAB_TOKEN_URL, + new URLSearchParams({ + grant_type: "refresh_token", + refresh_token: refreshToken, + client_id: await getClientIdGitLab(), + client_secret: await getClientSecretGitLab(), + redirect_uri: `${await getSiteURL()}/integrations/gitlab/oauth2/callback`, + } as any), + { + headers: { + "Accept-Encoding": "application/json", + }, + } + ); - accessExpiresAt.setSeconds( - accessExpiresAt.getSeconds() + data.expires_in - ); + accessExpiresAt.setSeconds(accessExpiresAt.getSeconds() + data.expires_in); - return ({ - accessToken: data.access_token, - refreshToken: data.refresh_token, - accessExpiresAt - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to refresh OAuth2 access token for GitLab'); - } + 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 188b166a7..46c93017d 100644 --- a/backend/src/integrations/revoke.ts +++ b/backend/src/integrations/revoke.ts @@ -1,4 +1,3 @@ -import * as Sentry from '@sentry/node'; import { IIntegrationAuth, IntegrationAuth, @@ -22,34 +21,28 @@ const revokeAccess = async ({ accessToken: string; }) => { let deletedIntegrationAuth; - try { - // add any integration-specific revocation logic - switch (integrationAuth.integration) { - case INTEGRATION_HEROKU: - break; - case INTEGRATION_VERCEL: - break; - case INTEGRATION_NETLIFY: - break; - case INTEGRATION_GITHUB: - break; - case INTEGRATION_GITLAB: - break; - } + // add any integration-specific revocation logic + switch (integrationAuth.integration) { + case INTEGRATION_HEROKU: + break; + case INTEGRATION_VERCEL: + break; + case INTEGRATION_NETLIFY: + break; + case INTEGRATION_GITHUB: + break; + case INTEGRATION_GITLAB: + break; + } - deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ - _id: integrationAuth._id + deletedIntegrationAuth = await IntegrationAuth.findOneAndDelete({ + _id: integrationAuth._id + }); + + if (deletedIntegrationAuth) { + await Integration.deleteMany({ + integrationAuth: deletedIntegrationAuth._id }); - - if (deletedIntegrationAuth) { - await Integration.deleteMany({ - integrationAuth: deletedIntegrationAuth._id - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to delete integration authorization'); } return deletedIntegrationAuth; diff --git a/backend/src/integrations/sync.ts b/backend/src/integrations/sync.ts index 829b50531..76d009944 100644 --- a/backend/src/integrations/sync.ts +++ b/backend/src/integrations/sync.ts @@ -1,4 +1,3 @@ -import * as Sentry from "@sentry/node"; import _ from 'lodash'; import AWS from 'aws-sdk'; import { @@ -21,19 +20,26 @@ import { INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, INTEGRATION_HEROKU_API_URL, INTEGRATION_GITLAB_API_URL, INTEGRATION_VERCEL_API_URL, INTEGRATION_NETLIFY_API_URL, INTEGRATION_RENDER_API_URL, + INTEGRATION_RAILWAY_API_URL, INTEGRATION_FLYIO_API_URL, INTEGRATION_CIRCLECI_API_URL, INTEGRATION_TRAVISCI_API_URL, + INTEGRATION_SUPABASE_API_URL, + INTEGRATION_CHECKLY, + INTEGRATION_CHECKLY_API_URL, + INTEGRATION_HASHICORP_VAULT } from "../variables"; -import request from '../config/request'; +import { standardRequest} from '../config/request'; /** * Sync/push [secrets] to [app] in integration named [integration] @@ -57,75 +63,109 @@ const syncSecrets = async ({ accessId: string | null; accessToken: string; }) => { - try { - switch (integration.integration) { - case INTEGRATION_AZURE_KEY_VAULT: - await syncSecretsAzureKeyVault({ + switch (integration.integration) { + case INTEGRATION_AZURE_KEY_VAULT: + await syncSecretsAzureKeyVault({ + integration, + secrets, + accessToken + }); + break; + case INTEGRATION_AWS_PARAMETER_STORE: + await syncSecretsAWSParameterStore({ + integration, + secrets, + accessId, + accessToken + }); + break; + case INTEGRATION_AWS_SECRET_MANAGER: + await syncSecretsAWSSecretManager({ + integration, + secrets, + accessId, + accessToken + }); + break; + case INTEGRATION_HEROKU: + await syncSecretsHeroku({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_VERCEL: + await syncSecretsVercel({ + integration, + integrationAuth, + secrets, + accessToken, + }); + break; + case INTEGRATION_NETLIFY: + await syncSecretsNetlify({ + integration, + integrationAuth, + secrets, + accessToken, + }); + break; + case INTEGRATION_GITHUB: + await syncSecretsGitHub({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_GITLAB: + await syncSecretsGitLab({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_RENDER: + await syncSecretsRender({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_RAILWAY: + await syncSecretsRailway({ + integration, + secrets, + 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_AWS_PARAMETER_STORE: - await syncSecretsAWSParameterStore({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_AWS_SECRET_MANAGER: - await syncSecretsAWSSecretManager({ - integration, - secrets, - accessId, - accessToken - }); - break; - case INTEGRATION_HEROKU: - await syncSecretsHeroku({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_VERCEL: - await syncSecretsVercel({ - integration, - integrationAuth, - secrets, - accessToken, - }); - break; - case INTEGRATION_NETLIFY: - await syncSecretsNetlify({ - integration, - integrationAuth, - secrets, - accessToken, - }); - break; - case INTEGRATION_GITHUB: - await syncSecretsGitHub({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_GITLAB: - await syncSecretsGitLab({ - integration, - secrets, - accessToken, - }); - break; - case INTEGRATION_RENDER: - await syncSecretsRender({ - integration, - secrets, - accessToken, - }); - break; case INTEGRATION_FLYIO: await syncSecretsFlyio({ integration, @@ -147,12 +187,30 @@ const syncSecrets = async ({ accessToken, }); break; + case INTEGRATION_SUPABASE: + await syncSecretsSupabase({ + integration, + secrets, + accessToken + }); + break; + case INTEGRATION_CHECKLY: + await syncSecretsCheckly({ + integration, + secrets, + accessToken, + }); + break; + case INTEGRATION_HASHICORP_VAULT: + await syncSecretsHashiCorpVault({ + integration, + integrationAuth, + secrets, + accessId, + accessToken + }); + break; } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to sync secrets to integration'); - } }; /** @@ -171,181 +229,169 @@ const syncSecretsAzureKeyVault = async ({ secrets: any; accessToken: string; }) => { - try { - interface GetAzureKeyVaultSecret { - id: string; // secret URI - attributes: { - enabled: true, - created: number; - updated: number; - recoveryLevel: string; - recoverableDays: number; - } + interface GetAzureKeyVaultSecret { + id: string; // secret URI + attributes: { + enabled: true, + created: number; + updated: number; + recoveryLevel: string; + recoverableDays: number; } - - interface AzureKeyVaultSecret extends GetAzureKeyVaultSecret { - key: string; - } - - /** - * Return all secrets from Azure Key Vault by paginating through URL [url] - * @param {String} url - pagination URL to get next set of secrets from Azure Key Vault - * @returns - */ - const paginateAzureKeyVaultSecrets = async (url: string) => { - let result: GetAzureKeyVaultSecret[] = []; - try { - while (url) { - const res = await request.get(url, { - headers: { - Authorization: `Bearer ${accessToken}` - } - }); - - result = result.concat(res.data.value); - - url = res.data.nextLink; - } - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - } - - return result; - } - - const getAzureKeyVaultSecrets = await paginateAzureKeyVaultSecrets(`${integration.app}/secrets?api-version=7.3`); - - let lastSlashIndex: number; - const res = (await Promise.all(getAzureKeyVaultSecrets.map(async (getAzureKeyVaultSecret) => { - if (!lastSlashIndex) { - lastSlashIndex = getAzureKeyVaultSecret.id.lastIndexOf('/'); - } - - const azureKeyVaultSecret = await request.get(`${getAzureKeyVaultSecret.id}?api-version=7.3`, { + } + + interface AzureKeyVaultSecret extends GetAzureKeyVaultSecret { + key: string; + } + + /** + * Return all secrets from Azure Key Vault by paginating through URL [url] + * @param {String} url - pagination URL to get next set of secrets from Azure Key Vault + * @returns + */ + const paginateAzureKeyVaultSecrets = async (url: string) => { + let result: GetAzureKeyVaultSecret[] = []; + while (url) { + const res = await standardRequest.get(url, { headers: { - 'Authorization': `Bearer ${accessToken}` + Authorization: `Bearer ${accessToken}` } }); - - return ({ - ...azureKeyVaultSecret.data, - key: getAzureKeyVaultSecret.id.substring(lastSlashIndex + 1), - }); - }))) - .reduce((obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret - }), {}); + + result = result.concat(res.data.value); + + url = res.data.nextLink; + } - const setSecrets: { - key: string; - value: string; - }[] = []; + return result; + } + + const getAzureKeyVaultSecrets = await paginateAzureKeyVaultSecrets(`${integration.app}/secrets?api-version=7.3`); + + let lastSlashIndex: number; + const res = (await Promise.all(getAzureKeyVaultSecrets.map(async (getAzureKeyVaultSecret) => { + if (!lastSlashIndex) { + lastSlashIndex = getAzureKeyVaultSecret.id.lastIndexOf('/'); + } + + const azureKeyVaultSecret = await standardRequest.get(`${getAzureKeyVaultSecret.id}?api-version=7.3`, { + headers: { + 'Authorization': `Bearer ${accessToken}` + } + }); - Object.keys(secrets).forEach((key) => { - const hyphenatedKey = key.replace(/_/g, '-'); - if (!(hyphenatedKey in res)) { - // case: secret has been created + return ({ + ...azureKeyVaultSecret.data, + key: getAzureKeyVaultSecret.id.substring(lastSlashIndex + 1), + }); + }))) + .reduce((obj: any, secret: any) => ({ + ...obj, + [secret.key]: secret + }), {}); + + const setSecrets: { + key: string; + value: string; + }[] = []; + + Object.keys(secrets).forEach((key) => { + const hyphenatedKey = key.replace(/_/g, '-'); + if (!(hyphenatedKey in res)) { + // case: secret has been created + setSecrets.push({ + key: hyphenatedKey, + value: secrets[key] + }); + } else { + if (secrets[key] !== res[hyphenatedKey].value) { + // case: secret has been updated setSecrets.push({ key: hyphenatedKey, value: secrets[key] }); - } else { - if (secrets[key] !== res[hyphenatedKey].value) { - // case: secret has been updated - setSecrets.push({ - key: hyphenatedKey, - value: secrets[key] - }); - } } - }); - - const deleteSecrets: AzureKeyVaultSecret[] = []; - - Object.keys(res).forEach((key) => { - const underscoredKey = key.replace(/-/g, '_'); - if (!(underscoredKey in secrets)) { - deleteSecrets.push(res[key]); - } - }); + } + }); + + const deleteSecrets: AzureKeyVaultSecret[] = []; + + Object.keys(res).forEach((key) => { + const underscoredKey = key.replace(/-/g, '_'); + if (!(underscoredKey in secrets)) { + deleteSecrets.push(res[key]); + } + }); - const setSecretAzureKeyVault = async ({ - key, - value, - integration, - accessToken - }: { - key: string; - value: string; - integration: IIntegration; - accessToken: string; - }) => { - let isSecretSet = false; - let maxTries = 6; + const setSecretAzureKeyVault = async ({ + key, + value, + integration, + accessToken + }: { + key: string; + value: string; + integration: IIntegration; + accessToken: string; + }) => { + let isSecretSet = false; + let maxTries = 6; + + while (!isSecretSet && maxTries > 0) { + // try to set secret + try { + await standardRequest.put( + `${integration.app}/secrets/${key}?api-version=7.3`, + { + value + }, + { + headers: { + Authorization: `Bearer ${accessToken}` + } + } + ); + + isSecretSet = true; - while (!isSecretSet && maxTries > 0) { - // try to set secret - try { - await request.put( - `${integration.app}/secrets/${key}?api-version=7.3`, - { - value - }, + } catch (err) { + const error: any = err; + if (error?.response?.data?.error?.innererror?.code === 'ObjectIsDeletedButRecoverable') { + await standardRequest.post( + `${integration.app}/deletedsecrets/${key}/recover?api-version=7.3`, {}, { headers: { Authorization: `Bearer ${accessToken}` } } ); - - isSecretSet = true; - - } catch (err) { - const error: any = err; - if (error?.response?.data?.error?.innererror?.code === 'ObjectIsDeletedButRecoverable') { - await request.post( - `${integration.app}/deletedsecrets/${key}/recover?api-version=7.3`, {}, - { - headers: { - Authorization: `Bearer ${accessToken}` - } - } - ); - await new Promise(resolve => setTimeout(resolve, 10000)); - } else { - await new Promise(resolve => setTimeout(resolve, 10000)); - maxTries--; - } + await new Promise(resolve => setTimeout(resolve, 10000)); + } else { + await new Promise(resolve => setTimeout(resolve, 10000)); + maxTries--; } } } - - // Sync/push set secrets - for await (const setSecret of setSecrets) { - const { key, value } = setSecret; - setSecretAzureKeyVault({ - key, - value, - integration, - accessToken - }); - } - - for await (const deleteSecret of deleteSecrets) { - const { key } = deleteSecret; - await request.delete(`${integration.app}/secrets/${key}?api-version=7.3`, { - headers: { - 'Authorization': `Bearer ${accessToken}` - } - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to sync secrets to Azure Key Vault'); + } + + // Sync/push set secrets + for await (const setSecret of setSecrets) { + const { key, value } = setSecret; + setSecretAzureKeyVault({ + key, + value, + integration, + accessToken + }); + } + + for await (const deleteSecret of deleteSecrets) { + const { key } = deleteSecret; + await standardRequest.delete(`${integration.app}/secrets/${key}?api-version=7.3`, { + headers: { + 'Authorization': `Bearer ${accessToken}` + } + }); } }; @@ -368,87 +414,81 @@ const syncSecretsAWSParameterStore = async ({ accessId: string | null; accessToken: string; }) => { - try { - if (!accessId) return; + if (!accessId) return; - AWS.config.update({ - region: integration.region, - accessKeyId: accessId, - secretAccessKey: accessToken - }); + AWS.config.update({ + region: integration.region, + accessKeyId: accessId, + secretAccessKey: accessToken + }); - const ssm = new AWS.SSM({ - apiVersion: '2014-11-06', - region: integration.region - }); - - const params = { - Path: integration.path, - Recursive: true, - WithDecryption: true - }; + const ssm = new AWS.SSM({ + apiVersion: '2014-11-06', + region: integration.region + }); + + const params = { + Path: integration.path, + Recursive: true, + WithDecryption: true + }; - const parameterList = (await ssm.getParametersByPath(params).promise()).Parameters - - let awsParameterStoreSecretsObj: { - [key: string]: any // TODO: fix type - } = {}; + const parameterList = (await ssm.getParametersByPath(params).promise()).Parameters + + let awsParameterStoreSecretsObj: { + [key: string]: any // TODO: fix type + } = {}; - if (parameterList) { - awsParameterStoreSecretsObj = parameterList.reduce((obj: any, secret: any) => ({ - ...obj, - [secret.Name.split("/").pop()]: secret - }), {}); - } + if (parameterList) { + awsParameterStoreSecretsObj = parameterList.reduce((obj: any, secret: any) => ({ + ...obj, + [secret.Name.split("/").pop()]: secret + }), {}); + } - // Identify secrets to create - Object.keys(secrets).map(async (key) => { - if (!(key in awsParameterStoreSecretsObj)) { - // case: secret does not exist in AWS parameter store - // -> create secret + // Identify secrets to create + Object.keys(secrets).map(async (key) => { + if (!(key in awsParameterStoreSecretsObj)) { + // case: secret does not exist in AWS parameter store + // -> create secret + await ssm.putParameter({ + Name: `${integration.path}${key}`, + Type: 'SecureString', + Value: secrets[key], + Overwrite: true + }).promise(); + } else { + // case: secret exists in AWS parameter store + + if (awsParameterStoreSecretsObj[key].Value !== secrets[key]) { + // case: secret value doesn't match one in AWS parameter store + // -> update secret await ssm.putParameter({ Name: `${integration.path}${key}`, Type: 'SecureString', Value: secrets[key], Overwrite: true }).promise(); - } else { - // case: secret exists in AWS parameter store - - if (awsParameterStoreSecretsObj[key].Value !== secrets[key]) { - // case: secret value doesn't match one in AWS parameter store - // -> update secret - await ssm.putParameter({ - Name: `${integration.path}${key}`, - Type: 'SecureString', - Value: secrets[key], - Overwrite: true - }).promise(); - } } - }); + } + }); - // Identify secrets to delete - Object.keys(awsParameterStoreSecretsObj).map(async (key) => { - if (!(key in secrets)) { - // case: - // -> delete secret - await ssm.deleteParameter({ - Name: awsParameterStoreSecretsObj[key].Name - }).promise(); - } - }); + // Identify secrets to delete + Object.keys(awsParameterStoreSecretsObj).map(async (key) => { + if (!(key in secrets)) { + // case: + // -> delete secret + await ssm.deleteParameter({ + Name: awsParameterStoreSecretsObj[key].Name + }).promise(); + } + }); - AWS.config.update({ - region: undefined, - accessKeyId: undefined, - secretAccessKey: undefined - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to sync secrets to AWS Parameter Store'); - } + AWS.config.update({ + region: undefined, + accessKeyId: undefined, + secretAccessKey: undefined + }); } /** @@ -518,11 +558,7 @@ const syncSecretsAWSSecretManager = async ({ Name: integration.app, SecretString: JSON.stringify(secrets) })); - } else { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to sync secrets to AWS Secret Manager'); - } + } AWS.config.update({ region: undefined, accessKeyId: undefined, @@ -547,29 +583,9 @@ const syncSecretsHeroku = async ({ secrets: any; accessToken: string; }) => { - try { - const herokuSecrets = ( - await request.get( - `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, - { - headers: { - Accept: "application/vnd.heroku+json; version=3", - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ) - ).data; - - Object.keys(herokuSecrets).forEach((key) => { - if (!(key in secrets)) { - secrets[key] = null; - } - }); - - await request.patch( + const herokuSecrets = ( + await standardRequest.get( `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, - secrets, { headers: { Accept: "application/vnd.heroku+json; version=3", @@ -577,12 +593,26 @@ const syncSecretsHeroku = async ({ 'Accept-Encoding': 'application/json' }, } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to Heroku"); - } + ) + ).data; + + Object.keys(herokuSecrets).forEach((key) => { + if (!(key in secrets)) { + secrets[key] = null; + } + }); + + await standardRequest.patch( + `${INTEGRATION_HEROKU_API_URL}/apps/${integration.app}/config-vars`, + secrets, + { + headers: { + Accept: "application/vnd.heroku+json; version=3", + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ); }; /** @@ -608,144 +638,143 @@ const syncSecretsVercel = async ({ key: string; value: string; target: string[]; + gitBranch?: string; + } + // Get all (decrypted) secrets back from Vercel in + // decrypted format + const params: { [key: string]: string } = { + decrypt: "true", + ...(integrationAuth?.teamId + ? { + teamId: integrationAuth.teamId, + } + : {}), + }; + + const vercelSecrets: VercelSecret[] = (await standardRequest.get( + `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`, + { + params, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + } + } + )) + .data + .envs + .filter((secret: VercelSecret) => { + if (!secret.target.includes(integration.targetEnvironment)) { + // case: secret does not have the same target environment + return false; + } + + if (integration.targetEnvironment === 'preview' && integration.path && integration.path !== secret.gitBranch) { + // case: secret on preview environment does not have same target git branch + return false; + } + + return true; + }); + + // return secret.target.includes(integration.targetEnvironment); + + const res: { [key: string]: VercelSecret } = {}; + + for await (const vercelSecret of vercelSecrets) { + if (vercelSecret.type === 'encrypted') { + // case: secret is encrypted -> need to decrypt + const decryptedSecret = (await standardRequest.get( + `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${vercelSecret.id}`, + { + params, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + } + } + )).data; + + res[vercelSecret.key] = decryptedSecret; + } else { + res[vercelSecret.key] = vercelSecret; + } } - try { - // Get all (decrypted) secrets back from Vercel in - // decrypted format - const params: { [key: string]: string } = { - decrypt: "true", - ...(integrationAuth?.teamId - ? { - teamId: integrationAuth.teamId, - } - : {}), - }; - - // const res = ( - // await Promise.all( - // ( - // await request.get( - // `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`, - // { - // params, - // headers: { - // Authorization: `Bearer ${accessToken}`, - // 'Accept-Encoding': 'application/json' - // } - // } - // )) - // .data - // .envs - // .filter((secret: VercelSecret) => secret.target.includes(integration.targetEnvironment)) - // .map(async (secret: VercelSecret) => { - // if (secret.type === 'encrypted') { - // // case: secret is encrypted -> need to decrypt - // const decryptedSecret = (await request.get( - // `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, - // { - // params, - // headers: { - // Authorization: `Bearer ${accessToken}`, - // 'Accept-Encoding': 'application/json' - // } - // } - // )).data; + const updateSecrets: VercelSecret[] = []; + const deleteSecrets: VercelSecret[] = []; + const newSecrets: VercelSecret[] = []; - // return decryptedSecret; - // } + // Identify secrets to create + Object.keys(secrets).map((key) => { + if (!(key in res)) { + // case: secret has been created + newSecrets.push({ + key: key, + value: secrets[key], + type: "encrypted", + target: [integration.targetEnvironment], + ...(integration.path ? { + gitBranch: integration.path + } : {}) + }); + } + }); - // return secret; - // }))).reduce((obj: any, secret: any) => ({ - // ...obj, - // [secret.key]: secret - // }), {}); - - const vercelSecrets: VercelSecret[] = (await request.get( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env`, + // Identify secrets to update and delete + Object.keys(res).map((key) => { + if (key in secrets) { + if (res[key].value !== secrets[key]) { + // case: secret value has changed + updateSecrets.push({ + id: res[key].id, + key: key, + value: secrets[key], + type: res[key].type, + target: res[key].target.includes(integration.targetEnvironment) + ? [...res[key].target] + : [...res[key].target, integration.targetEnvironment], + ...(integration.path ? { + gitBranch: integration.path + } : {}) + }); + } + } else { + // case: secret has been deleted + deleteSecrets.push({ + id: res[key].id, + key: key, + value: res[key].value, + type: "encrypted", // value doesn't matter + target: [integration.targetEnvironment], + ...(integration.path ? { + gitBranch: integration.path + } : {}) + }); + } + }); + + // Sync/push new secrets + if (newSecrets.length > 0) { + await standardRequest.post( + `${INTEGRATION_VERCEL_API_URL}/v10/projects/${integration.app}/env`, + newSecrets, { params, headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - } + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, } - )) - .data - .envs - .filter((secret: VercelSecret) => secret.target.includes(integration.targetEnvironment)); + ); + } - const res: { [key: string]: VercelSecret } = {}; - - for await (const vercelSecret of vercelSecrets) { - if (vercelSecret.type === 'encrypted') { - // case: secret is encrypted -> need to decrypt - const decryptedSecret = (await request.get( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${vercelSecret.id}`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - } - } - )).data; - - res[vercelSecret.key] = decryptedSecret; - } else { - res[vercelSecret.key] = vercelSecret; - } - } - - const updateSecrets: VercelSecret[] = []; - const deleteSecrets: VercelSecret[] = []; - const newSecrets: VercelSecret[] = []; - - // Identify secrets to create - Object.keys(secrets).map((key) => { - if (!(key in res)) { - // case: secret has been created - newSecrets.push({ - key: key, - value: secrets[key], - type: "encrypted", - target: [integration.targetEnvironment], - }); - } - }); - - // Identify secrets to update and delete - Object.keys(res).map((key) => { - if (key in secrets) { - if (res[key].value !== secrets[key]) { - // case: secret value has changed - updateSecrets.push({ - id: res[key].id, - key: key, - value: secrets[key], - type: res[key].type, - target: res[key].target.includes(integration.targetEnvironment) - ? [...res[key].target] - : [...res[key].target, integration.targetEnvironment] - }); - } - } else { - // case: secret has been deleted - deleteSecrets.push({ - id: res[key].id, - key: key, - value: res[key].value, - type: "encrypted", // value doesn't matter - target: [integration.targetEnvironment], - }); - } - }); - - // Sync/push new secrets - if (newSecrets.length > 0) { - await request.post( - `${INTEGRATION_VERCEL_API_URL}/v10/projects/${integration.app}/env`, - newSecrets, + for await (const secret of updateSecrets) { + if (secret.type !== 'sensitive') { + const { id, ...updatedSecret } = secret; + await standardRequest.patch( + `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, + updatedSecret, { params, headers: { @@ -754,41 +783,20 @@ const syncSecretsVercel = async ({ }, } ); - } - - for await (const secret of updateSecrets) { - if (secret.type !== 'sensitive') { - const { id, ...updatedSecret } = secret; - await request.patch( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, - updatedSecret, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - } - } + } + } - for await (const secret of deleteSecrets) { - await request.delete( - `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, - { - params, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to Vercel"); + for await (const secret of deleteSecrets) { + await standardRequest.delete( + `${INTEGRATION_VERCEL_API_URL}/v9/projects/${integration.app}/env/${secret.id}`, + { + params, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ); } }; @@ -811,92 +819,78 @@ const syncSecretsNetlify = async ({ secrets: any; accessToken: string; }) => { - try { - interface NetlifyValue { - id?: string; - context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production', - value: string; - } + interface NetlifyValue { + id?: string; + context: string; // 'dev' | 'branch-deploy' | 'deploy-preview' | 'production', + value: string; + } - interface NetlifySecret { - key: string; - values: NetlifyValue[]; - } + interface NetlifySecret { + key: string; + values: NetlifyValue[]; + } - interface NetlifySecretsRes { - [index: string]: NetlifySecret; - } + interface NetlifySecretsRes { + [index: string]: NetlifySecret; + } - const getParams = new URLSearchParams({ - context_name: "all", // integration.context or all - site_id: integration.appId, - }); + const getParams = new URLSearchParams({ + context_name: "all", // integration.context or all + site_id: integration.appId, + }); - const res = ( - await request.get( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, - { - params: getParams, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' + const res = ( + await standardRequest.get( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, + { + params: getParams, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ) + ).data.reduce( + (obj: any, secret: any) => ({ + ...obj, + [secret.key]: secret, + }), + {} + ); + + const newSecrets: NetlifySecret[] = []; // createEnvVars + const deleteSecrets: string[] = []; // deleteEnvVar + const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue + const updateSecrets: NetlifySecret[] = []; // setEnvVarValue + + // identify secrets to create and update + Object.keys(secrets).map((key) => { + if (!(key in res)) { + // case: Infisical secret does not exist in Netlify -> create secret + newSecrets.push({ + key, + values: [ + { + value: secrets[key], + context: integration.targetEnvironment, }, - } - ) - ).data.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.key]: secret, - }), - {} - ); + ], + }); + } else { + // case: Infisical secret exists in Netlify + const contexts = res[key].values.reduce( + (obj: any, value: NetlifyValue) => ({ + ...obj, + [value.context]: value, + }), + {} + ); - const newSecrets: NetlifySecret[] = []; // createEnvVars - const deleteSecrets: string[] = []; // deleteEnvVar - const deleteSecretValues: NetlifySecret[] = []; // deleteEnvVarValue - const updateSecrets: NetlifySecret[] = []; // setEnvVarValue - - // identify secrets to create and update - Object.keys(secrets).map((key) => { - if (!(key in res)) { - // case: Infisical secret does not exist in Netlify -> create secret - newSecrets.push({ - key, - values: [ - { - value: secrets[key], - context: integration.targetEnvironment, - }, - ], - }); - } else { - // case: Infisical secret exists in Netlify - const contexts = res[key].values.reduce( - (obj: any, value: NetlifyValue) => ({ - ...obj, - [value.context]: value, - }), - {} - ); - - if (integration.targetEnvironment in contexts) { - // case: Netlify secret value exists in integration context - if (secrets[key] !== contexts[integration.targetEnvironment].value) { - // case: Infisical and Netlify secret values are different - // -> update Netlify secret context and value - updateSecrets.push({ - key, - values: [ - { - context: integration.targetEnvironment, - value: secrets[key], - }, - ], - }); - } - } else { - // case: Netlify secret value does not exist in integration context - // -> add the new Netlify secret context and value + if (integration.targetEnvironment in contexts) { + // case: Netlify secret value exists in integration context + if (secrets[key] !== contexts[integration.targetEnvironment].value) { + // case: Infisical and Netlify secret values are different + // -> update Netlify secret context and value updateSecrets.push({ key, values: [ @@ -907,49 +901,80 @@ const syncSecretsNetlify = async ({ ], }); } - } - }); - - // identify secrets to delete - // TODO: revise (patch case where 1 context was deleted but others still there - Object.keys(res).map((key) => { - // loop through each key's context - if (!(key in secrets)) { - // case: Netlify secret does not exist in Infisical - - const numberOfValues = res[key].values.length; - - res[key].values.forEach((value: NetlifyValue) => { - if (value.context === integration.targetEnvironment) { - if (numberOfValues <= 1) { - // case: Netlify secret value has less than 1 context -> delete secret - deleteSecrets.push(key); - } else { - // case: Netlify secret value has more than 1 context -> delete secret value context - deleteSecretValues.push({ - key, - values: [ - { - id: value.id, - context: integration.targetEnvironment, - value: value.value, - }, - ], - }); - } - } + } else { + // case: Netlify secret value does not exist in integration context + // -> add the new Netlify secret context and value + updateSecrets.push({ + key, + values: [ + { + context: integration.targetEnvironment, + value: secrets[key], + }, + ], }); } - }); + } + }); - const syncParams = new URLSearchParams({ - site_id: integration.appId, - }); + // identify secrets to delete + // TODO: revise (patch case where 1 context was deleted but others still there + Object.keys(res).map((key) => { + // loop through each key's context + if (!(key in secrets)) { + // case: Netlify secret does not exist in Infisical - if (newSecrets.length > 0) { - await request.post( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, - newSecrets, + const numberOfValues = res[key].values.length; + + res[key].values.forEach((value: NetlifyValue) => { + if (value.context === integration.targetEnvironment) { + if (numberOfValues <= 1) { + // case: Netlify secret value has less than 1 context -> delete secret + deleteSecrets.push(key); + } else { + // case: Netlify secret value has more than 1 context -> delete secret value context + deleteSecretValues.push({ + key, + values: [ + { + id: value.id, + context: integration.targetEnvironment, + value: value.value, + }, + ], + }); + } + } + }); + } + }); + + const syncParams = new URLSearchParams({ + site_id: integration.appId, + }); + + if (newSecrets.length > 0) { + await standardRequest.post( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env`, + newSecrets, + { + params: syncParams, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ); + } + + if (updateSecrets.length > 0) { + updateSecrets.forEach(async (secret: NetlifySecret) => { + await standardRequest.patch( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`, + { + context: secret.values[0].context, + value: secret.values[0].value, + }, { params: syncParams, headers: { @@ -958,60 +983,37 @@ const syncSecretsNetlify = async ({ }, } ); - } + }); + } - if (updateSecrets.length > 0) { - updateSecrets.forEach(async (secret: NetlifySecret) => { - await request.patch( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}`, - { - context: secret.values[0].context, - value: secret.values[0].value, + if (deleteSecrets.length > 0) { + deleteSecrets.forEach(async (key: string) => { + await standardRequest.delete( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`, + { + params: syncParams, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' }, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - }); - } + } + ); + }); + } - if (deleteSecrets.length > 0) { - deleteSecrets.forEach(async (key: string) => { - await request.delete( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${key}`, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - }); - } - - if (deleteSecretValues.length > 0) { - deleteSecretValues.forEach(async (secret: NetlifySecret) => { - await request.delete( - `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`, - { - params: syncParams, - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - }); - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to Heroku"); + if (deleteSecretValues.length > 0) { + deleteSecretValues.forEach(async (secret: NetlifySecret) => { + await standardRequest.delete( + `${INTEGRATION_NETLIFY_API_URL}/api/v1/accounts/${integrationAuth.accountId}/env/${secret.key}/value/${secret.values[0].id}`, + { + params: syncParams, + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ); + }); } }; @@ -1032,102 +1034,96 @@ const syncSecretsGitHub = async ({ secrets: any; accessToken: string; }) => { - try { - interface GitHubRepoKey { - key_id: string; - key: string; - } + interface GitHubRepoKey { + key_id: string; + key: string; + } - interface GitHubSecret { - name: string; - created_at: string; - updated_at: string; - } + interface GitHubSecret { + name: string; + created_at: string; + updated_at: string; + } - interface GitHubSecretRes { - [index: string]: GitHubSecret; - } + interface GitHubSecretRes { + [index: string]: GitHubSecret; + } - const deleteSecrets: GitHubSecret[] = []; + const deleteSecrets: GitHubSecret[] = []; - const octokit = new Octokit({ - auth: accessToken, - }); + const octokit = new Octokit({ + auth: accessToken, + }); - // const user = (await octokit.request('GET /user', {})).data; - const repoPublicKey: GitHubRepoKey = ( + // const user = (await octokit.request('GET /user', {})).data; + const repoPublicKey: GitHubRepoKey = ( + await octokit.request( + "GET /repos/{owner}/{repo}/actions/secrets/public-key", + { + owner: integration.owner, + repo: integration.app + } + ) + ).data; + + // Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key + const encryptedSecrets: GitHubSecretRes = ( + await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", { + owner: integration.owner, + repo: integration.app, + }) + ).data.secrets.reduce( + (obj: any, secret: any) => ({ + ...obj, + [secret.name]: secret, + }), + {} + ); + + Object.keys(encryptedSecrets).map(async (key) => { + if (!(key in secrets)) { await octokit.request( - "GET /repos/{owner}/{repo}/actions/secrets/public-key", + "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", { owner: integration.owner, repo: integration.app, + secret_name: key, } - ) - ).data; + ); + } + }); - // Get local copy of decrypted secrets. We cannot decrypt them as we dont have access to GH private key - const encryptedSecrets: GitHubSecretRes = ( - await octokit.request("GET /repos/{owner}/{repo}/actions/secrets", { - owner: integration.owner, - repo: integration.app, - }) - ).data.secrets.reduce( - (obj: any, secret: any) => ({ - ...obj, - [secret.name]: secret, - }), - {} - ); + Object.keys(secrets).map((key) => { + // let encryptedSecret; + sodium.ready.then(async () => { + // convert secret & base64 key to Uint8Array. + const binkey = sodium.from_base64( + repoPublicKey.key, + sodium.base64_variants.ORIGINAL + ); + const binsec = sodium.from_string(secrets[key]); - Object.keys(encryptedSecrets).map(async (key) => { - if (!(key in secrets)) { - await octokit.request( - "DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name}", - { - owner: integration.owner, - repo: integration.app, - secret_name: key, - } - ); - } + // encrypt secret using libsodium + const encBytes = sodium.crypto_box_seal(binsec, binkey); + + // convert encrypted Uint8Array to base64 + const encryptedSecret = sodium.to_base64( + encBytes, + sodium.base64_variants.ORIGINAL + ); + + await octokit.request( + "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", + { + owner: integration.owner, + repo: integration.app, + secret_name: key, + encrypted_value: encryptedSecret, + key_id: repoPublicKey.key_id, + } + ); }); - - Object.keys(secrets).map((key) => { - // let encryptedSecret; - sodium.ready.then(async () => { - // convert secret & base64 key to Uint8Array. - const binkey = sodium.from_base64( - repoPublicKey.key, - sodium.base64_variants.ORIGINAL - ); - const binsec = sodium.from_string(secrets[key]); - - // encrypt secret using libsodium - const encBytes = sodium.crypto_box_seal(binsec, binkey); - - // convert encrypted Uint8Array to base64 - const encryptedSecret = sodium.to_base64( - encBytes, - sodium.base64_variants.ORIGINAL - ); - - await octokit.request( - "PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}", - { - owner: integration.owner, - repo: integration.app, - secret_name: key, - encrypted_value: encryptedSecret, - key_id: repoPublicKey.key_id, - } - ); - }); - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to GitHub"); - } + }); }; /** @@ -1146,27 +1142,65 @@ const syncSecretsRender = async ({ secrets: any; accessToken: string; }) => { - try { - await request.put( - `${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`, - Object.keys(secrets).map((key) => ({ - key, - value: secrets[key], - })), - { - headers: { - Authorization: `Bearer ${accessToken}`, - 'Accept-Encoding': 'application/json' - }, - } - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to Render"); - } + await standardRequest.put( + `${INTEGRATION_RENDER_API_URL}/v1/services/${integration.appId}/env-vars`, + Object.keys(secrets).map((key) => ({ + key, + value: secrets[key], + })), + { + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + }, + } + ); }; +/** + * Sync/push [secrets] to Railway 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 Railway integration + */ +const syncSecretsRailway = async ({ + integration, + secrets, + accessToken +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + const query = ` + mutation UpsertVariables($input: VariableCollectionUpsertInput!) { + variableCollectionUpsert(input: $input) + } + `; + + const input = { + projectId: integration.appId, + environmentId: integration.targetEnvironmentId, + ...(integration.targetServiceId ? { serviceId: integration.targetServiceId } : {}), + replace: true, + variables: secrets + }; + + await standardRequest.post(INTEGRATION_RAILWAY_API_URL, { + query, + variables: { + input, + }, + }, { + headers: { + 'Authorization': `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + 'Accept-Encoding': 'application/json' + }, + }); +} + /** * Sync/push [secrets] to Fly.io app * @param {Object} obj @@ -1183,120 +1217,113 @@ const syncSecretsFlyio = async ({ secrets: any; accessToken: string; }) => { - try { - // set secrets - const SetSecrets = ` - mutation($input: SetSecretsInput!) { - setSecrets(input: $input) { - release { + // set secrets + const SetSecrets = ` + mutation($input: SetSecretsInput!) { + setSecrets(input: $input) { + release { + id + version + reason + description + user { id - version - reason - description - user { - id - email - name - } - evaluationId - createdAt + email + name } + evaluationId + createdAt } } - `; - - await request.post(INTEGRATION_FLYIO_API_URL, { - query: SetSecrets, - variables: { - input: { - appId: integration.app, - secrets: Object.entries(secrets).map(([key, value]) => ({ - key, - value, - })), - }, - }, - }, { - headers: { - Authorization: "Bearer " + accessToken, - 'Accept-Encoding': 'application/json', - }, - }); - - // get secrets - interface FlyioSecret { - name: string; - digest: string; - createdAt: string; } + `; - const GetSecrets = `query ($appName: String!) { - app(name: $appName) { - secrets { - name - digest - createdAt - } - } - }`; - - const getSecretsRes = (await request.post(INTEGRATION_FLYIO_API_URL, { - query: GetSecrets, - variables: { - appName: integration.app, + await standardRequest.post(INTEGRATION_FLYIO_API_URL, { + query: SetSecrets, + variables: { + input: { + appId: integration.app, + secrets: Object.entries(secrets).map(([key, value]) => ({ + key, + value, + })), }, - }, { - headers: { - Authorization: "Bearer " + accessToken, - 'Content-Type': 'application/json', - 'Accept-Encoding': 'application/json', - }, - })).data.data.app.secrets; + }, + }, { + headers: { + Authorization: "Bearer " + accessToken, + 'Accept-Encoding': 'application/json', + }, + }); - const deleteSecretsKeys = getSecretsRes - .filter((secret: FlyioSecret) => !(secret.name in secrets)) - .map((secret: FlyioSecret) => secret.name); - - // unset (delete) secrets - const DeleteSecrets = `mutation($input: UnsetSecretsInput!) { - unsetSecrets(input: $input) { - release { - id - version - reason - description - user { - id - email - name - } - evaluationId - createdAt - } - } - }`; - - await request.post(INTEGRATION_FLYIO_API_URL, { - query: DeleteSecrets, - variables: { - input: { - appId: integration.app, - keys: deleteSecretsKeys, - }, - }, - }, { - headers: { - Authorization: "Bearer " + accessToken, - "Content-Type": "application/json", - 'Accept-Encoding': 'application/json', - }, - }); - - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to Fly.io"); + // get secrets + interface FlyioSecret { + name: string; + digest: string; + createdAt: string; } + + const GetSecrets = `query ($appName: String!) { + app(name: $appName) { + secrets { + name + digest + createdAt + } + } + }`; + + const getSecretsRes = (await standardRequest.post(INTEGRATION_FLYIO_API_URL, { + query: GetSecrets, + variables: { + appName: integration.app, + }, + }, { + headers: { + Authorization: "Bearer " + accessToken, + 'Content-Type': 'application/json', + 'Accept-Encoding': 'application/json', + }, + })).data.data.app.secrets; + + const deleteSecretsKeys = getSecretsRes + .filter((secret: FlyioSecret) => !(secret.name in secrets)) + .map((secret: FlyioSecret) => secret.name); + + // unset (delete) secrets + const DeleteSecrets = `mutation($input: UnsetSecretsInput!) { + unsetSecrets(input: $input) { + release { + id + version + reason + description + user { + id + email + name + } + evaluationId + createdAt + } + } + }`; + + await standardRequest.post(INTEGRATION_FLYIO_API_URL, { + query: DeleteSecrets, + variables: { + input: { + appId: integration.app, + keys: deleteSecretsKeys, + }, + }, + }, { + headers: { + Authorization: "Bearer " + accessToken, + "Content-Type": "application/json", + 'Accept-Encoding': 'application/json', + }, + }); }; /** @@ -1315,68 +1342,62 @@ const syncSecretsCircleCI = async ({ secrets: any; accessToken: string; }) => { - try { - const circleciOrganizationDetail = ( - await request.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, { + const circleciOrganizationDetail = ( + await standardRequest.get(`${INTEGRATION_CIRCLECI_API_URL}/v2/me/collaborations`, { + headers: { + "Circle-Token": accessToken, + "Accept-Encoding": "application/json", + }, + }) + ).data[0]; + + const { slug } = circleciOrganizationDetail; + + // sync secrets to CircleCI + Object.keys(secrets).forEach( + async (key) => + await standardRequest.post( + `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, + { + name: key, + value: secrets[key], + }, + { + headers: { + "Circle-Token": accessToken, + "Content-Type": "application/json", + }, + } + ) + ); + + // get secrets from CircleCI + const getSecretsRes = ( + await standardRequest.get( + `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, + { headers: { "Circle-Token": accessToken, "Accept-Encoding": "application/json", }, - }) - ).data[0]; + } + ) + ).data?.items; - const { slug } = circleciOrganizationDetail; - - // sync secrets to CircleCI - Object.keys(secrets).forEach( - async (key) => - await request.post( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, - { - name: key, - value: secrets[key], - }, - { - headers: { - "Circle-Token": accessToken, - "Content-Type": "application/json", - }, - } - ) - ); - - // get secrets from CircleCI - const getSecretsRes = ( - await request.get( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar`, + // delete secrets from CircleCI + getSecretsRes.forEach(async (sec: any) => { + if (!(sec.name in secrets)) { + await standardRequest.delete( + `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar/${sec.name}`, { headers: { "Circle-Token": accessToken, - "Accept-Encoding": "application/json", + "Content-Type": "application/json", }, } - ) - ).data?.items; - - // delete secrets from CircleCI - getSecretsRes.forEach(async (sec: any) => { - if (!(sec.name in secrets)) { - await request.delete( - `${INTEGRATION_CIRCLECI_API_URL}/v2/project/${slug}/${integration.app}/envvar/${sec.name}`, - { - headers: { - "Circle-Token": accessToken, - "Content-Type": "application/json", - }, - } - ); - } - }); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to CircleCI"); - } + ); + } + }); }; /** @@ -1395,88 +1416,82 @@ const syncSecretsTravisCI = async ({ secrets: any; accessToken: string; }) => { - try { - // get secrets from travis-ci - const getSecretsRes = ( - await request.get( + // get secrets from travis-ci + const getSecretsRes = ( + await standardRequest.get( + `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars?repository_id=${integration.appId}`, + { + headers: { + "Authorization": `token ${accessToken}`, + "Accept-Encoding": "application/json", + }, + } + ) + ) + .data + ?.env_vars + .reduce((obj: any, secret: any) => ({ + ...obj, + [secret.name]: secret + }), {}); + + // add secrets + for await (const key of Object.keys(secrets)) { + if (!(key in getSecretsRes)) { + // case: secret does not exist in travis ci + // -> add secret + await standardRequest.post( `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars?repository_id=${integration.appId}`, + { + env_var: { + name: key, + value: secrets[key] + } + }, { headers: { "Authorization": `token ${accessToken}`, + "Content-Type": "application/json", "Accept-Encoding": "application/json", }, } - ) - ) - .data - ?.env_vars - .reduce((obj: any, secret: any) => ({ - ...obj, - [secret.name]: secret - }), {}); - - // add secrets - for await (const key of Object.keys(secrets)) { - if (!(key in getSecretsRes)) { - // case: secret does not exist in travis ci - // -> add secret - await request.post( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars?repository_id=${integration.appId}`, - { - env_var: { - name: key, - value: secrets[key] - } - }, - { - headers: { - "Authorization": `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json", - }, + ); + } else { + // case: secret exists in travis ci + // -> update/set secret + await standardRequest.patch( + `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, + { + env_var: { + name: key, + value: secrets[key], } - ); - } else { - // case: secret exists in travis ci - // -> update/set secret - await request.patch( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, - { - env_var: { - name: key, - value: secrets[key], - } + }, + { + headers: { + "Authorization": `token ${accessToken}`, + "Content-Type": "application/json", + "Accept-Encoding": "application/json", }, - { - headers: { - "Authorization": `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json", - }, - } - ); - } + } + ); } + } - for await (const key of Object.keys(getSecretsRes)) { - if (!(key in secrets)){ - // delete secret - await request.delete( - `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, - { - headers: { - "Authorization": `token ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json", - }, - } - ); - } + for await (const key of Object.keys(getSecretsRes)) { + if (!(key in secrets)){ + // delete secret + await standardRequest.delete( + `${INTEGRATION_TRAVISCI_API_URL}/settings/env_vars/${getSecretsRes[key].id}?repository_id=${getSecretsRes[key].repository_id}`, + { + headers: { + "Authorization": `token ${accessToken}`, + "Content-Type": "application/json", + "Accept-Encoding": "application/json", + }, + } + ); } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to GitLab"); } } @@ -1497,45 +1512,70 @@ const syncSecretsGitLab = async ({ secrets: any; accessToken: string; }) => { - try { - // get secrets from gitlab - const getSecretsRes = ( - await request.get( + interface GitLabSecret { + key: string; + value: string; + environment_scope: string; + } + + const getAllEnvVariables = async (integrationAppId: string, accessToken: string) => { + const gitLabApiUrl = `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integrationAppId}/variables`; + const headers = { + "Authorization": `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + }; + + let allEnvVariables: GitLabSecret[] = []; + let url: string | null = `${gitLabApiUrl}?per_page=100`; + + while (url) { + const response: any = await standardRequest.get(url, { headers }); + allEnvVariables = [...allEnvVariables, ...response.data]; + + const linkHeader = response.headers.link; + const nextLink = linkHeader?.split(',').find((part: string) => part.includes('rel="next"')); + + if (nextLink) { + url = nextLink.trim().split(';')[0].slice(1, -1); + } else { + url = null; + } + } + + return allEnvVariables; + }; + + const allEnvVariables = await getAllEnvVariables(integration?.appId, accessToken); + const getSecretsRes: GitLabSecret[] = allEnvVariables.filter((secret: GitLabSecret) => + secret.environment_scope === integration.targetEnvironment + ); + + for await (const key of Object.keys(secrets)) { + const existingSecret = getSecretsRes.find((s: any) => s.key == key); + if (!existingSecret) { + await standardRequest.post( `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables`, - { + { + key: key, + value: secrets[key], + protected: false, + masked: false, + raw: false, + environment_scope: integration.targetEnvironment + }, + { headers: { "Authorization": `Bearer ${accessToken}`, + "Content-Type": "application/json", "Accept-Encoding": "application/json", }, } ) - ).data; - - for await (const key of Object.keys(secrets)) { - const existingSecret = getSecretsRes.find((s: any) => s.key == key); - if (!existingSecret) { - await request.post( - `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables`, - { - key: key, - value: secrets[key], - protected: false, - masked: false, - raw: false, - environment_scope:'*' - }, - { - headers: { - "Authorization": `Bearer ${accessToken}`, - "Content-Type": "application/json", - "Accept-Encoding": "application/json", - }, - } - ) - } else { - // udpate secret - await request.put( - `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables/${existingSecret.key}`, + } else { + // update secret + if (secrets[key] !== existingSecret.value) { + await standardRequest.put( + `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables/${existingSecret.key}?filter[environment_scope]=${integration.targetEnvironment}`, { ...existingSecret, value: secrets[existingSecret.key] @@ -1547,28 +1587,250 @@ const syncSecretsGitLab = async ({ "Accept-Encoding": "application/json", }, } - ) + ); } } + } - // delete secrets - for await (const sec of getSecretsRes) { - if (!(sec.key in secrets)) { - await request.delete( - `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables/${sec.key}`, + // delete secrets + for await (const sec of getSecretsRes) { + if (!(sec.key in secrets)) { + await standardRequest.delete( + `${INTEGRATION_GITLAB_API_URL}/v4/projects/${integration?.appId}/variables/${sec.key}?filter[environment_scope]=${integration.targetEnvironment}`, + { + headers: { + "Authorization": `Bearer ${accessToken}`, + }, + } + ); + } + } +} + +/** + * Sync/push [secrets] to Supabase 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 Supabase integration + */ +const syncSecretsSupabase = async ({ + integration, + secrets, + accessToken +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + const { data: getSecretsRes } = await standardRequest.get( + `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + } + } + ); + + // convert the secrets to [{}] format + const modifiedFormatForSecretInjection = Object.keys(secrets).map( + (key) => { + return { + name: key, + value: secrets[key] + }; + } + ); + + await standardRequest.post( + `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, + modifiedFormatForSecretInjection, + { + headers: { + Authorization: `Bearer ${accessToken}`, + 'Accept-Encoding': 'application/json' + } + } + ); + + const secretsToDelete: any = []; + getSecretsRes?.forEach((secretObj: any) => { + if (!(secretObj.name in secrets)) { + secretsToDelete.push(secretObj.name); + } + }); + + await standardRequest.delete( + `${INTEGRATION_SUPABASE_API_URL}/v1/projects/${integration.appId}/secrets`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + 'Content-Type': 'application/json', + 'Accept-Encoding': 'application/json' + }, + data: secretsToDelete + } + ); +}; + + +/** + * Sync/push [secrets] to Checkly app + * @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 Checkly integration + */ +const syncSecretsCheckly = async ({ + integration, + secrets, + accessToken, +}: { + integration: IIntegration; + secrets: any; + accessToken: string; +}) => { + // get secrets from travis-ci + const getSecretsRes = ( + await standardRequest.get( + `${INTEGRATION_CHECKLY_API_URL}/v1/variables`, + { + headers: { + "Authorization": `Bearer ${accessToken}`, + "Accept-Encoding": "application/json", + "X-Checkly-Account": integration.appId + }, + } + ) + ) + .data + .reduce((obj: any, secret: any) => ({ + ...obj, + [secret.key]: secret.value + }), {}); + + // add secrets + for await (const key of Object.keys(secrets)) { + if (!(key in getSecretsRes)) { + // case: secret does not exist in checkly + // -> add secret + + await standardRequest.post( + `${INTEGRATION_CHECKLY_API_URL}/v1/variables`, + { + key, + value: secrets[key] + }, + { + headers: { + "Authorization": `Bearer ${accessToken}`, + "Accept": "application/json", + "Content-Type": "application/json", + "X-Checkly-Account": integration.appId + }, + } + ); + } else { + // case: secret exists in checkly + // -> update/set secret + + if (secrets[key] !== getSecretsRes[key]) { + await standardRequest.put( + `${INTEGRATION_CHECKLY_API_URL}/v1/variables/${key}`, + { + value: secrets[key] + }, { headers: { "Authorization": `Bearer ${accessToken}`, + "Content-Type": "application/json", + "Accept": "application/json", + "X-Checkly-Account": integration.appId }, } ); } } - }catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to sync secrets to GitLab"); } -} + + for await (const key of Object.keys(getSecretsRes)) { + if (!(key in secrets)){ + // delete secret + await standardRequest.delete( + `${INTEGRATION_CHECKLY_API_URL}/v1/variables/${key}`, + { + headers: { + "Authorization": `Bearer ${accessToken}`, + "Accept": "application/json", + "X-Checkly-Account": integration.appId + }, + } + ); + } + } +}; + +/** + * Sync/push [secrets] to HashiCorp Vault path + * @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 HashiCorp Vault integration + */ +const syncSecretsHashiCorpVault = async ({ + integration, + integrationAuth, + secrets, + accessId, + accessToken, +}: { + integration: IIntegration; + integrationAuth: IIntegrationAuth; + secrets: any; + accessId: string | null; + accessToken: string; +}) => { + if (!accessId) return; + + interface LoginAppRoleRes { + auth: { + client_token: string; + } + } + + // get Vault client token (could be optimized) + const { data }: { data: LoginAppRoleRes } = await standardRequest.post( + `${integrationAuth.url}/v1/auth/approle/login`, + { + "role_id": accessId, + "secret_id": accessToken + }, + { + headers: { + "X-Vault-Namespace": integrationAuth.namespace + } + } + ); + + const clientToken = data.auth.client_token; + + await standardRequest.post( + `${integrationAuth.url}/v1/${integration.app}/data/${integration.path}`, + { + data: secrets + }, + { + headers: { + "Authorization": `Bearer ${accessToken}`, + "Accept": "application/json", + "Content-Type": "application/json", + "X-Vault-Token": clientToken, + "X-Vault-Namespace": integrationAuth.namespace + }, + } + ); +}; export { syncSecrets }; diff --git a/backend/src/integrations/teams.ts b/backend/src/integrations/teams.ts index 9943c531e..74fc0ca86 100644 --- a/backend/src/integrations/teams.ts +++ b/backend/src/integrations/teams.ts @@ -1,4 +1,3 @@ -import * as Sentry from "@sentry/node"; import { IIntegrationAuth } from '../models'; @@ -6,7 +5,7 @@ import { INTEGRATION_GITLAB, INTEGRATION_GITLAB_API_URL } from '../variables'; -import request from '../config/request'; +import { standardRequest } from '../config/request'; interface Team { name: string; @@ -31,21 +30,15 @@ const getTeams = async ({ }) => { let teams: Team[] = []; - try { - switch (integrationAuth.integration) { - case INTEGRATION_GITLAB: - teams = await getTeamsGitLab({ - accessToken - }); - break; - } - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to get integration teams'); + + switch (integrationAuth.integration) { + case INTEGRATION_GITLAB: + teams = await getTeamsGitLab({ + accessToken + }); + break; } - return teams; } @@ -63,30 +56,24 @@ const getTeamsGitLab = async ({ accessToken: string; }) => { let teams: Team[] = []; - try { - const res = (await request.get( - `${INTEGRATION_GITLAB_API_URL}/v4/groups`, - { - headers: { - Authorization: `Bearer ${accessToken}`, - "Accept-Encoding": "application/json" - } + const res = (await standardRequest.get( + `${INTEGRATION_GITLAB_API_URL}/v4/groups`, + { + headers: { + Authorization: `Bearer ${accessToken}`, + "Accept-Encoding": "application/json" } - )).data; - - teams = res.map((t: any) => ({ - name: t.name, - teamId: t.id - })); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error("Failed to get GitLab integration teams"); - } + } + )).data; + + teams = res.map((t: any) => ({ + name: t.name, + teamId: t.id + })); return teams; } export { getTeams -} \ No newline at end of file +} diff --git a/backend/src/interfaces/middleware/index.ts b/backend/src/interfaces/middleware/index.ts new file mode 100644 index 000000000..a368a3be1 --- /dev/null +++ b/backend/src/interfaces/middleware/index.ts @@ -0,0 +1,15 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData +} from '../../models'; + +export interface AuthData { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + authChannel: string; + authIP: string; + authUserAgent: string; + tokenVersionId?: Types.ObjectId; +} \ No newline at end of file diff --git a/backend/src/interfaces/serviceAccounts/dto/AddServiceAccountPermissionDto.ts b/backend/src/interfaces/serviceAccounts/dto/AddServiceAccountPermissionDto.ts new file mode 100644 index 000000000..6d0954c00 --- /dev/null +++ b/backend/src/interfaces/serviceAccounts/dto/AddServiceAccountPermissionDto.ts @@ -0,0 +1,7 @@ +interface AddServiceAccountPermissionDto { + name: string; + workspaceId?: string; + environment?: string; +} + +export default AddServiceAccountPermissionDto; \ No newline at end of file diff --git a/backend/src/interfaces/serviceAccounts/dto/CreateServiceAccountDto.ts b/backend/src/interfaces/serviceAccounts/dto/CreateServiceAccountDto.ts new file mode 100644 index 000000000..dcab0f302 --- /dev/null +++ b/backend/src/interfaces/serviceAccounts/dto/CreateServiceAccountDto.ts @@ -0,0 +1,8 @@ +interface CreateServiceAccountDto { + organizationId: string; + name: string; + publicKey: string; + expiresIn: number; +} + +export default CreateServiceAccountDto; \ No newline at end of file diff --git a/backend/src/interfaces/serviceAccounts/dto/index.ts b/backend/src/interfaces/serviceAccounts/dto/index.ts new file mode 100644 index 000000000..52d8d8342 --- /dev/null +++ b/backend/src/interfaces/serviceAccounts/dto/index.ts @@ -0,0 +1,7 @@ +import CreateServiceAccountDto from './CreateServiceAccountDto'; +import AddServiceAccountPermissionDto from './AddServiceAccountPermissionDto'; + +export { + CreateServiceAccountDto, + AddServiceAccountPermissionDto +} \ No newline at end of file diff --git a/backend/src/helpers/integrationAuth.ts b/backend/src/interfaces/services/BotService/index.ts similarity index 100% rename from backend/src/helpers/integrationAuth.ts rename to backend/src/interfaces/services/BotService/index.ts diff --git a/backend/src/interfaces/services/SecretService/index.ts b/backend/src/interfaces/services/SecretService/index.ts new file mode 100644 index 000000000..678c67711 --- /dev/null +++ b/backend/src/interfaces/services/SecretService/index.ts @@ -0,0 +1,57 @@ +import { Types } from "mongoose"; +import { AuthData } from "../../middleware"; + +export interface CreateSecretParams { + secretName: string; + workspaceId: Types.ObjectId; + environment: string; + type: "shared" | "personal"; + authData: AuthData; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretCommentCiphertext?: string; + secretCommentIV?: string; + secretCommentTag?: string; + secretPath: string; +} + +export interface GetSecretsParams { + workspaceId: Types.ObjectId; + environment: string; + secretPath: string; + authData: AuthData; +} + +export interface GetSecretParams { + secretName: string; + workspaceId: Types.ObjectId; + secretPath: string; + environment: string; + type?: "shared" | "personal"; + authData: AuthData; +} + +export interface UpdateSecretParams { + secretName: string; + workspaceId: Types.ObjectId; + environment: string; + type: "shared" | "personal"; + authData: AuthData; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretPath: string; +} + +export interface DeleteSecretParams { + secretName: string; + workspaceId: Types.ObjectId; + environment: string; + type: "shared" | "personal"; + authData: AuthData; + secretPath: string; +} diff --git a/backend/src/interfaces/utils/crypto.ts b/backend/src/interfaces/utils/crypto.ts new file mode 100644 index 000000000..cc2c54e3b --- /dev/null +++ b/backend/src/interfaces/utils/crypto.ts @@ -0,0 +1,41 @@ +export interface IGenerateKeyPairOutput { + publicKey: string; + privateKey: string +} + +export interface IEncryptAsymmetricInput { + plaintext: string; + publicKey: string; + privateKey: string; +} + +export interface IEncryptAsymmetricOutput { + ciphertext: string; + nonce: string; +} + +export interface IDecryptAsymmetricInput { + ciphertext: string; + nonce: string; + publicKey: string; + privateKey: string; +} + +export interface IEncryptSymmetricInput { + plaintext: string; + key: string; +} + +export interface IEncryptSymmetricOutput { + ciphertext: string; + iv: string; + tag: string; +} + +export interface IDecryptSymmetricInput { + ciphertext: string; + iv: string; + tag: string; + key: string; +} + diff --git a/backend/src/interfaces/utils/index.ts b/backend/src/interfaces/utils/index.ts new file mode 100644 index 000000000..7d27c9105 --- /dev/null +++ b/backend/src/interfaces/utils/index.ts @@ -0,0 +1 @@ +export * from './crypto'; \ No newline at end of file diff --git a/backend/src/middleware/index.ts b/backend/src/middleware/index.ts index 7e014103c..039b8612d 100644 --- a/backend/src/middleware/index.ts +++ b/backend/src/middleware/index.ts @@ -10,6 +10,8 @@ import requireIntegrationAuth from './requireIntegrationAuth'; import requireIntegrationAuthorizationAuth from './requireIntegrationAuthorizationAuth'; import requireServiceTokenAuth from './requireServiceTokenAuth'; import requireServiceTokenDataAuth from './requireServiceTokenDataAuth'; +import requireServiceAccountAuth from './requireServiceAccountAuth'; +import requireServiceAccountWorkspacePermissionAuth from './requireServiceAccountWorkspacePermissionAuth'; import requireSecretAuth from './requireSecretAuth'; import requireSecretsAuth from './requireSecretsAuth'; import validateRequest from './validateRequest'; @@ -27,6 +29,8 @@ export { requireIntegrationAuthorizationAuth, requireServiceTokenAuth, requireServiceTokenDataAuth, + requireServiceAccountAuth, + requireServiceAccountWorkspacePermissionAuth, requireSecretAuth, requireSecretsAuth, validateRequest diff --git a/backend/src/middleware/requestErrorHandler.ts b/backend/src/middleware/requestErrorHandler.ts index 202a38e83..6aa73954b 100644 --- a/backend/src/middleware/requestErrorHandler.ts +++ b/backend/src/middleware/requestErrorHandler.ts @@ -1,34 +1,51 @@ import * as Sentry from '@sentry/node'; -import { ErrorRequestHandler } from "express"; -import { InternalServerError } from "../utils/errors"; -import { getLogger } from "../utils/logger"; -import RequestError, { LogLevel } from "../utils/requestError"; +import { ErrorRequestHandler } from 'express'; +import { InternalServerError } from '../utils/errors'; +import { getLogger } from '../utils/logger'; +import RequestError, { LogLevel } from '../utils/requestError'; import { getNodeEnv } from '../config'; -export const requestErrorHandler: ErrorRequestHandler = (error: RequestError | Error, req, res, next) => { - if (res.headersSent) return next(); - if (getNodeEnv() !== "production") { - /* eslint-disable no-console */ - console.log(error) - /* eslint-enable no-console */ - } +export const requestErrorHandler: ErrorRequestHandler = async ( + error: RequestError | Error, + req, + res, + next +) => { + if (res.headersSent) return next(); - //TODO: Find better way to type check for error. In current setting you need to cast type to get the functions and variables from RequestError - if (!(error instanceof RequestError)) { - error = InternalServerError({ context: { exception: error.message }, stack: error.stack }) - getLogger('backend-main').log((error).levelName.toLowerCase(), (error).message) - } + if (await getNodeEnv() !== "production") { + /* eslint-disable no-console */ + console.error(error); + } - //* Set Sentry user identification if req.user is populated - if (req.user !== undefined && req.user !== null) { - Sentry.setUser({ email: req.user.email }) - } - //* Only sent error to Sentry if LogLevel is one of the following level 'ERROR', 'EMERGENCY' or 'CRITICAL' - //* with this we will eliminate false-positive errors like 'BadRequestError', 'UnauthorizedRequestError' and so on - if ([LogLevel.ERROR, LogLevel.EMERGENCY, LogLevel.CRITICAL].includes((error).level)) { - Sentry.captureException(error) - } + //TODO: Find better way to type check for error. In current setting you need to cast type to get the functions and variables from RequestError + if (!(error instanceof RequestError)) { + error = InternalServerError({ + context: { exception: error.message }, + stack: error.stack, + }); + (await getLogger('backend-main')).log( + (error).levelName.toLowerCase(), + (error).message + ); + } - res.status((error).statusCode).json((error).format(req)) - next() -} \ No newline at end of file + //* Set Sentry user identification if req.user is populated + if (req.user !== undefined && req.user !== null) { + Sentry.setUser({ email: (req.user as any).email }); + } + //* Only sent error to Sentry if LogLevel is one of the following level 'ERROR', 'EMERGENCY' or 'CRITICAL' + //* with this we will eliminate false-positive errors like 'BadRequestError', 'UnauthorizedRequestError' and so on + if ( + [LogLevel.ERROR, LogLevel.EMERGENCY, LogLevel.CRITICAL].includes( + (error).level + ) + ) { + Sentry.captureException(error); + } + + res + .status((error).statusCode) + .json((error).format(req)); + next(); +}; diff --git a/backend/src/middleware/requireAuth.ts b/backend/src/middleware/requireAuth.ts index f4921398a..22de05f68 100644 --- a/backend/src/middleware/requireAuth.ts +++ b/backend/src/middleware/requireAuth.ts @@ -4,11 +4,21 @@ import { validateAuthMode, getAuthUserPayload, getAuthSTDPayload, - getAuthAPIKeyPayload + getAuthAPIKeyPayload, + getAuthSAAKPayload } from '../helpers/auth'; -import { - UnauthorizedRequestError -} from '../utils/errors'; +import { + IUser, + IServiceAccount, + IServiceTokenData +} from '../models'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; +import { getChannelFromUserAgent } from '../utils/posthog'; declare module 'jsonwebtoken' { export interface UserIDJwtPayload extends jwt.JwtPayload { @@ -27,50 +37,64 @@ declare module 'jsonwebtoken' { * @returns */ const requireAuth = ({ - acceptedAuthModes = ['jwt'], - requiredServiceTokenPermissions = [] + acceptedAuthModes = [AUTH_MODE_JWT], }: { acceptedAuthModes: string[]; - requiredServiceTokenPermissions?: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { + // validate auth token against accepted auth modes [acceptedAuthModes] // and return token type [authTokenType] and value [authTokenValue] - const { authTokenType, authTokenValue } = validateAuthMode({ + const { authMode, authTokenValue } = validateAuthMode({ headers: req.headers, acceptedAuthModes }); - // attach auth payloads - let serviceTokenData: any; - switch (authTokenType) { - case 'serviceToken': - serviceTokenData = await getAuthSTDPayload({ + let authPayload: IUser | IServiceAccount | IServiceTokenData; + switch (authMode) { + case AUTH_MODE_SERVICE_ACCOUNT: + authPayload = await getAuthSAAKPayload({ authTokenValue }); - - requiredServiceTokenPermissions.forEach((requiredServiceTokenPermission) => { - if (!serviceTokenData.permissions.includes(requiredServiceTokenPermission)) { - return next(UnauthorizedRequestError({ message: 'Failed to authorize service token for endpoint' })); - } - }); - - req.serviceTokenData = serviceTokenData; - req.user = serviceTokenData?.user; - + req.serviceAccount = authPayload; break; - case 'apiKey': - req.user = await getAuthAPIKeyPayload({ + case AUTH_MODE_SERVICE_TOKEN: + authPayload = await getAuthSTDPayload({ authTokenValue }); + req.serviceTokenData = authPayload; + break; + case AUTH_MODE_API_KEY: + authPayload = await getAuthAPIKeyPayload({ + authTokenValue + }); + req.user = authPayload; break; default: - req.user = await getAuthUserPayload({ + const { user, tokenVersionId } = await getAuthUserPayload({ authTokenValue }); + authPayload = user; + req.user = user; + req.tokenVersionId = tokenVersionId; break; } + req.requestData = { + ...req.params, + ...req.query, + ...req.body, + } + + req.authData = { + authMode, + authPayload, // User, ServiceAccount, ServiceTokenData + authChannel: getChannelFromUserAgent(req.headers['user-agent']), + authIP: req.realIP, + authUserAgent: req.headers['user-agent'] ?? 'other', + tokenVersionId: req.tokenVersionId + } + return next(); } } diff --git a/backend/src/middleware/requireBotAuth.ts b/backend/src/middleware/requireBotAuth.ts index 435b06a59..2de8217da 100644 --- a/backend/src/middleware/requireBotAuth.ts +++ b/backend/src/middleware/requireBotAuth.ts @@ -1,32 +1,25 @@ import { Request, Response, NextFunction } from 'express'; -import { Bot } from '../models'; -import { validateMembership } from '../helpers/membership'; -import { AccountNotFoundError } from '../utils/errors'; +import { Types } from 'mongoose'; +import { validateClientForBot } from '../validation'; type req = 'params' | 'body' | 'query'; const requireBotAuth = ({ acceptedRoles, - location = 'params' + locationBotId = 'params' }: { - acceptedRoles: string[]; - location?: req; + acceptedRoles: Array<'admin' | 'member'>; + locationBotId?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { - const bot = await Bot.findById(req[location].botId); + const { botId } = req[locationBotId]; - if (!bot) { - return next(AccountNotFoundError({message: 'Failed to locate Bot account'})) - } - - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: bot.workspace.toString(), + req.bot = await validateClientForBot({ + authData: req.authData, + botId: new Types.ObjectId(botId), acceptedRoles }); - req.bot = bot; - next(); } } diff --git a/backend/src/middleware/requireIntegrationAuth.ts b/backend/src/middleware/requireIntegrationAuth.ts index b185b922b..94d39a6c1 100644 --- a/backend/src/middleware/requireIntegrationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuth.ts @@ -1,8 +1,6 @@ import { Request, Response, NextFunction } from 'express'; -import { Integration, IntegrationAuth } from '../models'; -import { IntegrationService } from '../services'; -import { validateMembership } from '../helpers/membership'; -import { IntegrationNotFoundError, UnauthorizedRequestError } from '../utils/errors'; +import { Types } from 'mongoose'; +import { validateClientForIntegration } from '../validation'; /** * Validate if user on request is a member of workspace with proper roles associated @@ -13,42 +11,24 @@ import { IntegrationNotFoundError, UnauthorizedRequestError } from '../utils/err const requireIntegrationAuth = ({ acceptedRoles }: { - acceptedRoles: string[]; + acceptedRoles: Array<'admin' | 'member'>; }) => { return async (req: Request, res: Response, next: NextFunction) => { - // integration authorization middleware - const { integrationId } = req.params; - // validate integration accessibility - const integration = await Integration.findOne({ - _id: integrationId - }); - - if (!integration) { - return next(IntegrationNotFoundError({message: 'Failed to locate Integration'})) - } - - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: integration.workspace.toString(), + const { integration, accessToken } = await validateClientForIntegration({ + authData: req.authData, + integrationId: new Types.ObjectId(integrationId), acceptedRoles }); - const integrationAuth = await IntegrationAuth.findOne({ - _id: integration.integrationAuth - }).select( - '+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt' - ); - - if (!integrationAuth) { - return next(UnauthorizedRequestError({message: 'Failed to locate Integration Authentication credentials'})) + if (integration) { + req.integration = integration; + } + + if (accessToken) { + req.accessToken = accessToken; } - - req.integration = integration; - req.accessToken = await IntegrationService.getIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString() - }); return next(); }; diff --git a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts index c712f4cca..2ffa7e230 100644 --- a/backend/src/middleware/requireIntegrationAuthorizationAuth.ts +++ b/backend/src/middleware/requireIntegrationAuthorizationAuth.ts @@ -1,9 +1,6 @@ -import * as Sentry from '@sentry/node'; +import { Types } from 'mongoose'; import { Request, Response, NextFunction } from 'express'; -import { IntegrationAuth, IWorkspace } from '../models'; -import { IntegrationService } from '../services'; -import { validateMembership } from '../helpers/membership'; -import { UnauthorizedRequestError } from '../utils/errors'; +import { validateClientForIntegrationAuth } from '../validation'; type req = 'params' | 'body' | 'query'; @@ -19,36 +16,26 @@ const requireIntegrationAuthorizationAuth = ({ attachAccessToken = true, location = 'params' }: { - acceptedRoles: string[]; + acceptedRoles: Array<'admin' | 'member'>; attachAccessToken?: boolean; location?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { const { integrationAuthId } = req[location]; - const integrationAuth = await IntegrationAuth.findOne({ - _id: integrationAuthId - }) - .populate<{ workspace: IWorkspace }>('workspace') - .select( - '+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt' - ); - if (!integrationAuth) { - return next(UnauthorizedRequestError({message: 'Failed to locate Integration Authorization credentials'})) - } - - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: integrationAuth.workspace._id.toString(), - acceptedRoles + const { integrationAuth, accessToken } = await validateClientForIntegrationAuth({ + authData: req.authData, + integrationAuthId: new Types.ObjectId(integrationAuthId), + acceptedRoles, + attachAccessToken }); + + if (integrationAuth) { + req.integrationAuth = integrationAuth; + } - req.integrationAuth = integrationAuth; - if (attachAccessToken) { - const access = await IntegrationService.getIntegrationAuthAccess({ - integrationAuthId: integrationAuth._id.toString() - }); - req.accessToken = access.accessToken; + if (accessToken) { + req.accessToken = accessToken; } return next(); diff --git a/backend/src/middleware/requireMembershipAuth.ts b/backend/src/middleware/requireMembershipAuth.ts index f5e4fe8b1..e03a6ea12 100644 --- a/backend/src/middleware/requireMembershipAuth.ts +++ b/backend/src/middleware/requireMembershipAuth.ts @@ -1,9 +1,6 @@ +import { Types } from 'mongoose'; import { Request, Response, NextFunction } from 'express'; -import { UnauthorizedRequestError } from '../utils/errors'; -import { - Membership, -} from '../models'; -import { validateMembership } from '../helpers/membership'; +import { validateClientForMembership } from '../validation'; type req = 'params' | 'body' | 'query'; @@ -16,43 +13,25 @@ type req = 'params' | 'body' | 'query'; */ const requireMembershipAuth = ({ acceptedRoles, - location = 'params' + locationMembershipId = 'params' }: { - acceptedRoles: string[]; - location?: req; + acceptedRoles: Array<'admin' | 'member'>; + locationMembershipId: req }) => { return async ( req: Request, res: Response, next: NextFunction ) => { - try { - const { membershipId } = req[location]; - - const membership = await Membership.findById(membershipId); - - if (!membership) throw new Error('Failed to find target membership'); - - const userMembership = await Membership.findOne({ - workspace: membership.workspace - }); - - if (!userMembership) throw new Error('Failed to validate own membership') - - const targetMembership = await validateMembership({ - userId: req.user._id.toString(), - workspaceId: membership.workspace.toString(), - acceptedRoles - }); - - req.targetMembership = targetMembership; - - return next(); - } catch (err) { - return next(UnauthorizedRequestError({ - message: 'Unable to validate workspace membership' - })); - } + const { membershipId } = req[locationMembershipId]; + + req.targetMembership = await validateClientForMembership({ + authData: req.authData, + membershipId: new Types.ObjectId(membershipId), + acceptedRoles + }); + + return next(); } } diff --git a/backend/src/middleware/requireMembershipOrgAuth.ts b/backend/src/middleware/requireMembershipOrgAuth.ts index ec1a4d4f1..dda90cae8 100644 --- a/backend/src/middleware/requireMembershipOrgAuth.ts +++ b/backend/src/middleware/requireMembershipOrgAuth.ts @@ -1,10 +1,6 @@ +import { Types } from 'mongoose'; import { Request, Response, NextFunction } from 'express'; -import { UnauthorizedRequestError } from '../utils/errors'; -import { - MembershipOrg -} from '../models'; -import { validateMembership } from '../helpers/membershipOrg'; - +import { validateClientForMembershipOrg } from '../validation'; type req = 'params' | 'body' | 'query'; @@ -17,32 +13,24 @@ type req = 'params' | 'body' | 'query'; */ const requireMembershipOrgAuth = ({ acceptedRoles, - location = 'params' + acceptedStatuses, + locationMembershipOrgId = 'params' }: { - acceptedRoles: string[]; - location?: req; + acceptedRoles: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses: Array<'invited' | 'accepted'>; + locationMembershipOrgId?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { - try { - const { membershipId } = req[location]; - const membershipOrg = await MembershipOrg.findById(membershipId); - - if (!membershipOrg) throw new Error('Failed to find target organization membership'); - - const targetMembership = await validateMembership({ - userId: req.user._id.toString(), - organizationId: membershipOrg.organization.toString(), - acceptedRoles - }); - - req.targetMembership = targetMembership; - - return next(); - } catch (err) { - return next(UnauthorizedRequestError({ - message: 'Unable to validate organization membership' - })); - } + const { membershipId } = req[locationMembershipOrgId]; + + req.membershipOrg = await validateClientForMembershipOrg({ + authData: req.authData, + membershipOrgId: new Types.ObjectId(membershipId), + acceptedRoles, + acceptedStatuses + }); + + return next(); } } diff --git a/backend/src/middleware/requireMfaAuth.ts b/backend/src/middleware/requireMfaAuth.ts index 7fb38ca25..ca0b3434e 100644 --- a/backend/src/middleware/requireMfaAuth.ts +++ b/backend/src/middleware/requireMfaAuth.ts @@ -26,7 +26,7 @@ const requireMfaAuth = async ( if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: 'Missing Authorization Body in the request header'})) const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, getJwtMfaSecret()) + jwt.verify(AUTH_TOKEN_VALUE, await getJwtMfaSecret()) ); const user = await User.findOne({ diff --git a/backend/src/middleware/requireOrganizationAuth.ts b/backend/src/middleware/requireOrganizationAuth.ts index 04542b429..5f7ef151d 100644 --- a/backend/src/middleware/requireOrganizationAuth.ts +++ b/backend/src/middleware/requireOrganizationAuth.ts @@ -1,45 +1,43 @@ import { Request, Response, NextFunction } from 'express'; -import { IOrganization, MembershipOrg } from '../models'; -import { UnauthorizedRequestError, ValidationError } from '../utils/errors'; +import { Types } from 'mongoose'; +import { validateClientForOrganization } from '../validation'; + +type req = 'params' | 'body' | 'query'; /** * Validate if user on request is a member with proper roles for organization * on request params. * @param {Object} obj * @param {String[]} obj.acceptedRoles - accepted organization roles - * @param {String[]} obj.acceptedStatuses - accepted organization statuses + * @param {String[]} obj.accepteStatuses - accepted organization statuses */ const requireOrganizationAuth = ({ acceptedRoles, - acceptedStatuses + acceptedStatuses, + locationOrganizationId = 'params' }: { - acceptedRoles: string[]; - acceptedStatuses: string[]; + acceptedRoles: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses: Array<'invited' | 'accepted'>; + locationOrganizationId?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { - // organization authorization middleware - - // validate organization membership - const membershipOrg = await MembershipOrg.findOne({ - user: req.user._id, - organization: req.params.organizationId - }).populate<{ organization: IOrganization }>('organization'); - - - if (!membershipOrg) { - return next(UnauthorizedRequestError({message: "You're not a member of this Organization."})) - } - //TODO is this important to validate? I mean is it possible to save wrong role to database or get wrong role from databse? - Zamion101 - if (!acceptedRoles.includes(membershipOrg.role)) { - return next(ValidationError({message: 'Failed to validate Organization Membership Role'})) + const { organizationId } = req[locationOrganizationId]; + + const { organization, membershipOrg } = await validateClientForOrganization({ + authData: req.authData, + organizationId: new Types.ObjectId(organizationId), + acceptedRoles, + acceptedStatuses + }); + + if (organization) { + req.organization = organization; } - if (!acceptedStatuses.includes(membershipOrg.status)) { - return next(ValidationError({message: 'Failed to validate Organization Membership Status'})) + if (membershipOrg) { + req.membershipOrg = membershipOrg; } - req.membershipOrg = membershipOrg; - return next(); }; }; diff --git a/backend/src/middleware/requireSecretAuth.ts b/backend/src/middleware/requireSecretAuth.ts index 36e47247e..4fda73a23 100644 --- a/backend/src/middleware/requireSecretAuth.ts +++ b/backend/src/middleware/requireSecretAuth.ts @@ -1,12 +1,10 @@ import { Request, Response, NextFunction } from 'express'; -import { UnauthorizedRequestError, SecretNotFoundError } from '../utils/errors'; -import { Secret } from '../models'; -import { - validateMembership -} from '../helpers/membership'; +import { Types } from 'mongoose'; +import { validateClientForSecret } from '../validation'; // note: used for old /v1/secret and /v2/secret routes. -// newer /v2/secrets routes use [requireSecretsAuth] middleware +// newer /v2/secrets routes use [requireSecretsAuth] middleware with the exception +// of some /ee endpoints /** * Validate if user on request has proper membership to modify secret. @@ -15,34 +13,25 @@ import { * @param {String[]} obj.location - location of [workspaceId] on request (e.g. params, body) for parsing */ const requireSecretAuth = ({ - acceptedRoles + acceptedRoles, + requiredPermissions }: { - acceptedRoles: string[]; + acceptedRoles: Array<'admin' | 'member'>; + requiredPermissions: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { - try { - const { secretId } = req.params; - - const secret = await Secret.findById(secretId); - - if (!secret) { - return next(SecretNotFoundError({ - message: 'Failed to find secret' - })); - } - - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: secret.workspace.toString(), - acceptedRoles - }); - - req._secret = secret; + const { secretId } = req.params; + + const secret = await validateClientForSecret({ + authData: req.authData, + secretId: new Types.ObjectId(secretId), + acceptedRoles, + requiredPermissions + }); + + req._secret = secret; - next(); - } catch (err) { - return next(UnauthorizedRequestError({ message: 'Unable to authenticate secret' })); - } + next(); } } diff --git a/backend/src/middleware/requireSecretsAuth.ts b/backend/src/middleware/requireSecretsAuth.ts index 2a6c36056..f25487b97 100644 --- a/backend/src/middleware/requireSecretsAuth.ts +++ b/backend/src/middleware/requireSecretsAuth.ts @@ -1,48 +1,33 @@ import { Request, Response, NextFunction } from 'express'; -import { UnauthorizedRequestError } from '../utils/errors'; -import { Secret, Membership } from '../models'; -import { validateSecrets } from '../helpers/secret'; - -// TODO: make this work for delete route +import { Types } from 'mongoose'; +import { validateClientForSecrets } from '../validation'; const requireSecretsAuth = ({ - acceptedRoles + acceptedRoles, + requiredPermissions = [] }: { acceptedRoles: string[]; + requiredPermissions?: string[]; }) => { return async (req: Request, res: Response, next: NextFunction) => { - let secrets; - try { - if (Array.isArray(req.body.secrets)) { - // case: validate multiple secrets - secrets = await validateSecrets({ - userId: req.user._id.toString(), - secretIds: req.body.secrets.map((s: any) => s.id) - }); - } else if (typeof req.body.secrets === 'object') { // change this to check for object - // case: validate 1 secret - secrets = await validateSecrets({ - userId: req.user._id.toString(), - secretIds: [req.body.secrets.id] - }); - } else if (Array.isArray(req.body.secretIds)) { - secrets = await validateSecrets({ - userId: req.user._id.toString(), - secretIds: req.body.secretIds - }); - } else if (typeof req.body.secretIds === 'string') { - // case: validate secretIds - secrets = await validateSecrets({ - userId: req.user._id.toString(), - secretIds: [req.body.secretIds] - }); - } - - req.secrets = secrets; - return next(); - } catch (err) { - return next(UnauthorizedRequestError({ message: 'Unable to authenticate secret(s)' })); + let secretIds = []; + if (Array.isArray(req.body.secrets)) { + secretIds = req.body.secrets.map((s: any) => s.id); + } else if (typeof req.body.secrets === 'object') { + secretIds = [req.body.secrets.id]; + } else if (Array.isArray(req.body.secretIds)) { + secretIds = req.body.secretIds; + } else if (typeof req.body.secretIds === 'string') { + secretIds = [req.body.secretIds]; } + + req.secrets = await validateClientForSecrets({ + authData: req.authData, + secretIds: secretIds.map((secretId: string) => new Types.ObjectId(secretId)), + requiredPermissions + }); + + return next(); } } diff --git a/backend/src/middleware/requireServiceAccountAuth.ts b/backend/src/middleware/requireServiceAccountAuth.ts new file mode 100644 index 000000000..da690c7bb --- /dev/null +++ b/backend/src/middleware/requireServiceAccountAuth.ts @@ -0,0 +1,31 @@ +import { Request, Response, NextFunction } from 'express'; +import { Types } from 'mongoose'; +import { validateClientForServiceAccount } from '../validation'; + +type req = 'params' | 'body' | 'query'; + +const requireServiceAccountAuth = ({ + acceptedRoles, + acceptedStatuses, + locationServiceAccountId = 'params', + requiredPermissions = [] +}: { + acceptedRoles: string[]; + acceptedStatuses: string[]; + locationServiceAccountId?: req; + requiredPermissions?: string[]; +}) => { + return async (req: Request, res: Response, next: NextFunction) => { + const serviceAccountId = req[locationServiceAccountId].serviceAccountId; + + req.serviceAccount = await validateClientForServiceAccount({ + authData: req.authData, + serviceAccountId: new Types.ObjectId(serviceAccountId), + requiredPermissions + }); + + next(); + } +} + +export default requireServiceAccountAuth; \ No newline at end of file diff --git a/backend/src/middleware/requireServiceAccountWorkspacePermissionAuth.ts b/backend/src/middleware/requireServiceAccountWorkspacePermissionAuth.ts new file mode 100644 index 000000000..0ceb4f598 --- /dev/null +++ b/backend/src/middleware/requireServiceAccountWorkspacePermissionAuth.ts @@ -0,0 +1,52 @@ +import { Request, Response, NextFunction } from 'express'; +import { ServiceAccount, ServiceAccountWorkspacePermission } from '../models'; +import { + ServiceAccountNotFoundError +} from '../utils/errors'; +import { + validateMembershipOrg +} from '../helpers/membershipOrg'; + +type req = 'params' | 'body' | 'query'; + +const requireServiceAccountWorkspacePermissionAuth = ({ + acceptedRoles, + acceptedStatuses, + location = 'params' +}: { + acceptedRoles: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses: Array<'invited' | 'accepted'>; + location?: req; +}) => { + return async (req: Request, res: Response, next: NextFunction) => { + const serviceAccountWorkspacePermissionId = req[location].serviceAccountWorkspacePermissionId; + const serviceAccountWorkspacePermission = await ServiceAccountWorkspacePermission.findById(serviceAccountWorkspacePermissionId); + + if (!serviceAccountWorkspacePermission) { + return next(ServiceAccountNotFoundError({ message: 'Failed to locate Service Account workspace permission' })); + } + + const serviceAccount = await ServiceAccount.findById(serviceAccountWorkspacePermission.serviceAccount); + + if (!serviceAccount) { + return next(ServiceAccountNotFoundError({ message: 'Failed to locate Service Account' })); + } + + if (serviceAccount.user.toString() !== req.user.id.toString()) { + // case: creator of the service account is different from + // the user on the request -> apply middleware role/status validation + await validateMembershipOrg({ + userId: req.user._id, + organizationId: serviceAccount.organization, + acceptedRoles, + acceptedStatuses + }); + } + + req.serviceAccount = serviceAccount; + + next(); + } +} + +export default requireServiceAccountWorkspacePermissionAuth; \ No newline at end of file diff --git a/backend/src/middleware/requireServiceTokenAuth.ts b/backend/src/middleware/requireServiceTokenAuth.ts index 106ca9bbb..5db0dcda5 100644 --- a/backend/src/middleware/requireServiceTokenAuth.ts +++ b/backend/src/middleware/requireServiceTokenAuth.ts @@ -33,7 +33,7 @@ const requireServiceTokenAuth = async ( if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: 'Missing Authorization Body in the request header'})) const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, getJwtServiceSecret()) + jwt.verify(AUTH_TOKEN_VALUE, await getJwtServiceSecret()) ); const serviceToken = await ServiceToken.findOne({ diff --git a/backend/src/middleware/requireServiceTokenDataAuth.ts b/backend/src/middleware/requireServiceTokenDataAuth.ts index 7c5ab4669..be93fd799 100644 --- a/backend/src/middleware/requireServiceTokenDataAuth.ts +++ b/backend/src/middleware/requireServiceTokenDataAuth.ts @@ -1,7 +1,6 @@ import { Request, Response, NextFunction } from 'express'; -import { ServiceToken, ServiceTokenData } from '../models'; -import { validateMembership } from '../helpers/membership'; -import { AccountNotFoundError, UnauthorizedRequestError } from '../utils/errors'; +import { Types } from 'mongoose'; +import { validateClientForServiceTokenData } from '../validation'; type req = 'params' | 'body' | 'query'; @@ -9,30 +8,17 @@ const requireServiceTokenDataAuth = ({ acceptedRoles, location = 'params' }: { - acceptedRoles: string[]; + acceptedRoles: Array<'admin' | 'member'>; location?: req; }) => { return async (req: Request, res: Response, next: NextFunction) => { const { serviceTokenDataId } = req[location]; - - const serviceTokenData = await ServiceTokenData - .findById(req[location].serviceTokenDataId) - .select('+encryptedKey +iv +tag').populate('user'); - - if (!serviceTokenData) { - return next(AccountNotFoundError({ message: 'Failed to locate service token data' })); - } - - if (req.user) { - // case: jwt auth - await validateMembership({ - userId: req.user._id.toString(), - workspaceId: serviceTokenData.workspace.toString(), - acceptedRoles - }); - } - - req.serviceTokenData = serviceTokenData; + + req.serviceTokenData = await validateClientForServiceTokenData({ + authData: req.authData, + serviceTokenDataId: new Types.ObjectId(serviceTokenDataId), + acceptedRoles + }); next(); } diff --git a/backend/src/middleware/requireSignupAuth.ts b/backend/src/middleware/requireSignupAuth.ts index 19e6b3146..6a0fd0b6e 100644 --- a/backend/src/middleware/requireSignupAuth.ts +++ b/backend/src/middleware/requireSignupAuth.ts @@ -27,7 +27,7 @@ const requireSignupAuth = async ( if(AUTH_TOKEN_VALUE === null) return next(BadRequestError({message: 'Missing Authorization Body in the request header'})) const decodedToken = ( - jwt.verify(AUTH_TOKEN_VALUE, getJwtSignupSecret()) + jwt.verify(AUTH_TOKEN_VALUE, await getJwtSignupSecret()) ); const user = await User.findOne({ diff --git a/backend/src/middleware/requireWorkspaceAuth.ts b/backend/src/middleware/requireWorkspaceAuth.ts index 56c24528c..9833e6e56 100644 --- a/backend/src/middleware/requireWorkspaceAuth.ts +++ b/backend/src/middleware/requireWorkspaceAuth.ts @@ -1,6 +1,6 @@ import { Request, Response, NextFunction } from 'express'; -import { validateMembership } from '../helpers/membership'; -import { UnauthorizedRequestError } from '../utils/errors'; +import { Types } from 'mongoose'; +import { validateClientForWorkspace } from '../validation'; type req = 'params' | 'body' | 'query'; @@ -13,38 +13,43 @@ type req = 'params' | 'body' | 'query'; */ const requireWorkspaceAuth = ({ acceptedRoles, - location = 'params' + locationWorkspaceId, + locationEnvironment = undefined, + requiredPermissions = [], + requireBlindIndicesEnabled = false, + requireE2EEOff = false }: { - acceptedRoles: string[]; - location?: req; + acceptedRoles: Array<'admin' | 'member'>; + locationWorkspaceId: req; + locationEnvironment?: req | undefined; + requiredPermissions?: string[]; + requireBlindIndicesEnabled?: boolean; + requireE2EEOff?: boolean; }) => { return async (req: Request, res: Response, next: NextFunction) => { - try { - const { workspaceId } = req[location]; - - if (req.user) { - // case: jwt auth - const membership = await validateMembership({ - userId: req.user._id.toString(), - workspaceId, - acceptedRoles - }); - - req.membership = membership; - } - - if ( - req.serviceTokenData - && req.serviceTokenData.workspace.toString() !== workspaceId - && req.serviceTokenData.environment !== req.body.environment - ) { - next(UnauthorizedRequestError({message: 'Unable to authenticate workspace'})) - } - - return next(); - } catch (err) { - return next(UnauthorizedRequestError({message: 'Unable to authenticate workspace'})) + const workspaceId = req[locationWorkspaceId]?.workspaceId; + const environment = locationEnvironment ? req[locationEnvironment]?.environment : undefined; + + // validate clients + const { membership, workspace } = await validateClientForWorkspace({ + authData: req.authData, + workspaceId: new Types.ObjectId(workspaceId), + environment, + acceptedRoles, + requiredPermissions, + requireBlindIndicesEnabled, + requireE2EEOff + }); + + if (membership) { + req.membership = membership; } + + if (workspace) { + req.workspace = workspace; + } + + return next(); }; }; diff --git a/backend/src/models/apiKeyData.ts b/backend/src/models/apiKeyData.ts index af73b5f69..1b6831730 100644 --- a/backend/src/models/apiKeyData.ts +++ b/backend/src/models/apiKeyData.ts @@ -3,6 +3,7 @@ import { Schema, model, Types } from 'mongoose'; export interface IAPIKeyData { name: string; user: Types.ObjectId; + lastUsed: Date; expiresAt: Date; secretHash: string; } @@ -18,6 +19,9 @@ const apiKeyDataSchema = new Schema( ref: 'User', required: true }, + lastUsed: { + type: Date + }, expiresAt: { type: Date }, diff --git a/backend/src/models/backupPrivateKey.ts b/backend/src/models/backupPrivateKey.ts index 70dcd6475..09bcbb588 100644 --- a/backend/src/models/backupPrivateKey.ts +++ b/backend/src/models/backupPrivateKey.ts @@ -1,4 +1,9 @@ import { Schema, model, Types } from 'mongoose'; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 +} from '../variables'; export interface IBackupPrivateKey { _id: Types.ObjectId; @@ -7,6 +12,8 @@ export interface IBackupPrivateKey { iv: string; tag: string; salt: string; + algorithm: string; + keyEncoding: 'base64' | 'utf8'; verifier: string; } @@ -32,6 +39,19 @@ const backupPrivateKeySchema = new Schema( select: false, required: true }, + algorithm: { // the encryption algorithm used + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true + }, + keyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 + ], + required: true + }, salt: { type: String, select: false, diff --git a/backend/src/models/bot.ts b/backend/src/models/bot.ts index c7e5a9abe..5755bfd8e 100644 --- a/backend/src/models/bot.ts +++ b/backend/src/models/bot.ts @@ -1,4 +1,10 @@ import { Schema, model, Types } from 'mongoose'; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_HEX, + ENCODING_SCHEME_BASE64 +} from '../variables'; export interface IBot { _id: Types.ObjectId; @@ -9,6 +15,8 @@ export interface IBot { encryptedPrivateKey: string; iv: string; tag: string; + algorithm: 'aes-256-gcm'; + keyEncoding: 'base64' | 'utf8'; } const botSchema = new Schema( @@ -45,6 +53,21 @@ const botSchema = new Schema( type: String, required: true, select: false + }, + algorithm: { // the encryption algorithm used + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true, + select: false + }, + keyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 + ], + required: true, + select: false } }, { diff --git a/backend/src/models/folder.ts b/backend/src/models/folder.ts new file mode 100644 index 000000000..ac0358287 --- /dev/null +++ b/backend/src/models/folder.ts @@ -0,0 +1,56 @@ +import { Schema, model, Types } from "mongoose"; + +export type TFolderRootSchema = { + _id: Types.ObjectId; + workspace: Types.ObjectId; + environment: string; + nodes: TFolderSchema; +}; + +export type TFolderSchema = { + id: string; + name: string; + version: number; + children: TFolderSchema[]; +}; + +const folderSchema = new Schema({ + id: { + required: true, + type: String, + }, + version: { + required: true, + type: Number, + default: 1, + }, + name: { + required: true, + type: String, + default: "root", + }, +}); + +folderSchema.add({ children: [folderSchema] }); + +const folderRootSchema = new Schema( + { + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, + }, + environment: { + type: String, + required: true, + }, + nodes: folderSchema, + }, + { + timestamps: true, + } +); + +const Folder = model("Folder", folderRootSchema); + +export default Folder; diff --git a/backend/src/models/index.ts b/backend/src/models/index.ts index ead32aae4..cb4ee672a 100644 --- a/backend/src/models/index.ts +++ b/backend/src/models/index.ts @@ -9,16 +9,23 @@ import Membership, { IMembership } from './membership'; import MembershipOrg, { IMembershipOrg } from './membershipOrg'; import Organization, { IOrganization } from './organization'; import Secret, { ISecret } from './secret'; +import SecretBlindIndexData, { ISecretBlindIndexData } from './secretBlindIndexData'; import ServiceToken, { IServiceToken } from './serviceToken'; +import ServiceAccount, { IServiceAccount } from './serviceAccount'; // new +import ServiceAccountKey, { IServiceAccountKey } from './serviceAccountKey'; // new +import ServiceAccountOrganizationPermission, { IServiceAccountOrganizationPermission } from './serviceAccountOrganizationPermission'; // new +import ServiceAccountWorkspacePermission, { IServiceAccountWorkspacePermission } from './serviceAccountWorkspacePermission'; // new import TokenData, { ITokenData } from './tokenData'; -import User, { IUser } from './user'; +import User,{ AuthProvider, IUser } from './user'; import UserAction, { IUserAction } from './userAction'; import Workspace, { IWorkspace } from './workspace'; import ServiceTokenData, { IServiceTokenData } from './serviceTokenData'; import APIKeyData, { IAPIKeyData } from './apiKeyData'; import LoginSRPDetail, { ILoginSRPDetail } from './loginSRPDetail'; +import TokenVersion, { ITokenVersion } from './tokenVersion'; export { + AuthProvider, BackupPrivateKey, IBackupPrivateKey, Bot, @@ -41,8 +48,18 @@ export { IOrganization, Secret, ISecret, + SecretBlindIndexData, + ISecretBlindIndexData, ServiceToken, IServiceToken, + ServiceAccount, + IServiceAccount, + ServiceAccountKey, + IServiceAccountKey, + ServiceAccountOrganizationPermission, + IServiceAccountOrganizationPermission, + ServiceAccountWorkspacePermission, + IServiceAccountWorkspacePermission, TokenData, ITokenData, User, @@ -56,5 +73,7 @@ export { APIKeyData, IAPIKeyData, LoginSRPDetail, - ILoginSRPDetail + ILoginSRPDetail, + TokenVersion, + ITokenVersion }; diff --git a/backend/src/models/integration.ts b/backend/src/models/integration.ts index 698846ea7..d4fbae807 100644 --- a/backend/src/models/integration.ts +++ b/backend/src/models/integration.ts @@ -9,9 +9,13 @@ import { INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_CHECKLY, + INTEGRATION_HASHICORP_VAULT } from "../variables"; export interface IIntegration { @@ -19,10 +23,14 @@ export interface IIntegration { workspace: Types.ObjectId; environment: string; isActive: boolean; + url: string; app: string; + appId: string; owner: string; targetEnvironment: string; - appId: string; + targetEnvironmentId: string; + targetService: string; + targetServiceId: string; path: string; region: string; integration: @@ -35,9 +43,13 @@ export interface IIntegration { | 'github' | 'gitlab' | 'render' + | 'railway' | 'flyio' | 'circleci' - | 'travisci'; + | 'travisci' + | 'supabase' + | 'checkly' + | 'hashicorp-vault'; integrationAuth: Types.ObjectId; } @@ -56,6 +68,11 @@ const integrationSchema = new Schema( type: Boolean, required: true, }, + url: { + // for custom self-hosted integrations (e.g. self-hosted GitHub enterprise) + type: String, + default: null + }, app: { // name of app in provider type: String, @@ -71,6 +88,20 @@ const integrationSchema = new Schema( type: String, default: null, }, + targetEnvironmentId: { + type: String, + default: null + }, + targetService: { + // railway-specific service + type: String, + default: null + }, + targetServiceId: { + // railway-specific service + type: String, + default: null + }, owner: { // github-specific repo owner-login type: String, @@ -78,6 +109,7 @@ const integrationSchema = new Schema( }, path: { // aws-parameter-store-specific path + // (also) vercel preview-branch type: String, default: null }, @@ -98,9 +130,13 @@ const integrationSchema = new Schema( INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_CHECKLY, + INTEGRATION_HASHICORP_VAULT ], required: true, }, diff --git a/backend/src/models/integrationAuth.ts b/backend/src/models/integrationAuth.ts index 43bef63ad..cc28c9fd6 100644 --- a/backend/src/models/integrationAuth.ts +++ b/backend/src/models/integrationAuth.ts @@ -1,4 +1,4 @@ -import { Schema, model, Types } from "mongoose"; +import { Schema, model, Types, Document } from "mongoose"; import { INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_AWS_PARAMETER_STORE, @@ -9,17 +9,25 @@ import { INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_HASHICORP_VAULT, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 } from "../variables"; -export interface IIntegrationAuth { +export interface IIntegrationAuth extends Document { _id: Types.ObjectId; workspace: Types.ObjectId; - integration: 'heroku' | 'vercel' | 'netlify' | 'github' | 'gitlab' | 'render' | 'flyio' | 'azure-key-vault' | 'circleci' | 'travisci' | 'aws-parameter-store' | 'aws-secret-manager'; + integration: 'heroku' | 'vercel' | 'netlify' | 'github' | 'gitlab' | 'render' | 'railway' | 'flyio' | 'azure-key-vault' | 'circleci' | 'travisci' | 'supabase' | 'aws-parameter-store' | 'aws-secret-manager' | 'checkly'; teamId: string; accountId: string; + url: string; + namespace: string; refreshCiphertext?: string; refreshIV?: string; refreshTag?: string; @@ -29,6 +37,8 @@ export interface IIntegrationAuth { accessCiphertext?: string; accessIV?: string; accessTag?: string; + algorithm?: 'aes-256-gcm'; + keyEncoding?: 'utf8' | 'base64'; accessExpiresAt?: Date; } @@ -51,9 +61,12 @@ const integrationAuthSchema = new Schema( INTEGRATION_GITHUB, INTEGRATION_GITLAB, INTEGRATION_RENDER, + INTEGRATION_RAILWAY, INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_HASHICORP_VAULT ], required: true, }, @@ -61,6 +74,14 @@ const integrationAuthSchema = new Schema( // vercel-specific integration param type: String, }, + url: { + // for any self-hosted integrations (e.g. self-hosted hashicorp-vault) + type: String + }, + namespace: { + // hashicorp-vault-specific integration param + type: String + }, accountId: { // netlify-specific integration param type: String, @@ -105,6 +126,19 @@ const integrationAuthSchema = new Schema( type: Date, select: false, }, + algorithm: { // the encryption algorithm used + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true + }, + keyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 + ], + required: true + } }, { timestamps: true, diff --git a/backend/src/models/loginSRPDetail.ts b/backend/src/models/loginSRPDetail.ts index 6f3b579bd..dde59233d 100644 --- a/backend/src/models/loginSRPDetail.ts +++ b/backend/src/models/loginSRPDetail.ts @@ -5,6 +5,7 @@ export interface ILoginSRPDetail { clientPublicKey: string; email: string; serverBInt: mongoose.Schema.Types.Buffer; + userId: string; expireAt: Date; } @@ -16,7 +17,6 @@ const loginSRPDetailSchema = new Schema( }, email: { type: String, - required: true, unique: true }, serverBInt: { type: mongoose.Schema.Types.Buffer }, diff --git a/backend/src/models/membershipOrg.ts b/backend/src/models/membershipOrg.ts index b5013acbb..540a4451b 100644 --- a/backend/src/models/membershipOrg.ts +++ b/backend/src/models/membershipOrg.ts @@ -1,7 +1,7 @@ -import { Schema, model, Types } from 'mongoose'; +import { Schema, model, Types, Document } from 'mongoose'; import { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED } from '../variables'; -export interface IMembershipOrg { +export interface IMembershipOrg extends Document { _id: Types.ObjectId; user: Types.ObjectId; inviteEmail: string; diff --git a/backend/src/models/secret.ts b/backend/src/models/secret.ts index 463ed50fd..ff34d99b1 100644 --- a/backend/src/models/secret.ts +++ b/backend/src/models/secret.ts @@ -1,117 +1,144 @@ -import { Schema, model, Types } from 'mongoose'; +import { Schema, model, Types } from "mongoose"; import { - SECRET_SHARED, - SECRET_PERSONAL, -} from '../variables'; + SECRET_SHARED, + SECRET_PERSONAL, + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, +} from "../variables"; export interface ISecret { - _id: Types.ObjectId; - version: number; - workspace: Types.ObjectId; - type: string; - user: Types.ObjectId; - environment: string; - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretKeyHash: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretValueHash: string; - secretCommentCiphertext?: string; - secretCommentIV?: string; - secretCommentTag?: string; - secretCommentHash?: string; - tags?: string[]; + _id: Types.ObjectId; + version: number; + workspace: Types.ObjectId; + type: string; + user: Types.ObjectId; + environment: string; + secretBlindIndex?: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretKeyHash: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretValueHash: string; + secretCommentCiphertext?: string; + secretCommentIV?: string; + secretCommentTag?: string; + secretCommentHash?: string; + algorithm: "aes-256-gcm"; + keyEncoding: "utf8" | "base64"; + tags?: string[]; + folder?: string; } const secretSchema = new Schema( - { - version: { - type: Number, - required: true, - default: 1 - }, - workspace: { - type: Schema.Types.ObjectId, - ref: 'Workspace', - required: true - }, - type: { - type: String, - enum: [SECRET_SHARED, SECRET_PERSONAL], - required: true - }, - user: { - // user associated with the personal secret - type: Schema.Types.ObjectId, - ref: 'User' - }, - tags: { - ref: 'Tag', - type: [Schema.Types.ObjectId], - default: [] - }, - environment: { - type: String, - required: true - }, - secretKeyCiphertext: { - type: String, - required: true - }, - secretKeyIV: { - type: String, // symmetric - required: true - }, - secretKeyTag: { - type: String, // symmetric - required: true - }, - secretKeyHash: { - type: String - }, - secretValueCiphertext: { - type: String, - required: true - }, - secretValueIV: { - type: String, // symmetric - required: true - }, - secretValueTag: { - type: String, // symmetric - required: true - }, - secretValueHash: { - type: String - }, - secretCommentCiphertext: { - type: String, - required: false - }, - secretCommentIV: { - type: String, // symmetric - required: false - }, - secretCommentTag: { - type: String, // symmetric - required: false - }, - secretCommentHash: { - type: String, - required: false - } - }, - { - timestamps: true - } + { + version: { + type: Number, + required: true, + default: 1, + }, + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, + }, + type: { + type: String, + enum: [SECRET_SHARED, SECRET_PERSONAL], + required: true, + }, + user: { + // user associated with the personal secret + type: Schema.Types.ObjectId, + ref: "User", + }, + tags: { + ref: "Tag", + type: [Schema.Types.ObjectId], + default: [], + }, + environment: { + type: String, + required: true, + }, + secretBlindIndex: { + type: String, + select: false, + }, + secretKeyCiphertext: { + type: String, + required: true, + }, + secretKeyIV: { + type: String, // symmetric + required: true, + }, + secretKeyTag: { + type: String, // symmetric + required: true, + }, + secretKeyHash: { + type: String, + }, + secretValueCiphertext: { + type: String, + required: true, + }, + secretValueIV: { + type: String, // symmetric + required: true, + }, + secretValueTag: { + type: String, // symmetric + required: true, + }, + secretValueHash: { + type: String, + }, + secretCommentCiphertext: { + type: String, + required: false, + }, + secretCommentIV: { + type: String, // symmetric + required: false, + }, + secretCommentTag: { + type: String, // symmetric + required: false, + }, + secretCommentHash: { + type: String, + required: false, + }, + algorithm: { + // the encryption algorithm used + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true, + default: ALGORITHM_AES_256_GCM, + }, + keyEncoding: { + type: String, + enum: [ENCODING_SCHEME_UTF8, ENCODING_SCHEME_BASE64], + required: true, + default: ENCODING_SCHEME_UTF8, + }, + folder: { + type: String, + default: "root", + }, + }, + { + timestamps: true, + } ); +secretSchema.index({ tags: 1 }, { background: true }); -secretSchema.index({ tags: 1 }, { background: true }) - -const Secret = model('Secret', secretSchema); +const Secret = model("Secret", secretSchema); export default Secret; diff --git a/backend/src/models/secretBlindIndexData.ts b/backend/src/models/secretBlindIndexData.ts new file mode 100644 index 000000000..885faaff6 --- /dev/null +++ b/backend/src/models/secretBlindIndexData.ts @@ -0,0 +1,58 @@ +import { Schema, model, Types, Document } from 'mongoose'; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 +} from '../variables'; + +export interface ISecretBlindIndexData extends Document { + _id: Types.ObjectId; + workspace: Types.ObjectId; + encryptedSaltCiphertext: string; + saltIV: string; + saltTag: string; + algorithm: 'aes-256-gcm'; + keyEncoding: 'base64' | 'utf8' +} + +const secretBlindIndexDataSchema = new Schema( + { + workspace: { + type: Schema.Types.ObjectId, + ref: 'Workspace', + required: true + }, + encryptedSaltCiphertext: { // TODO: make these select: false + type: String, + required: true + }, + saltIV: { + type: String, + required: true + }, + saltTag: { + type: String, + required: true + }, + algorithm: { + type: String, + enum: [ALGORITHM_AES_256_GCM], + required: true, + select: false + }, + keyEncoding: { + type: String, + enum: [ + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 + ], + required: true, + select: false + } + + } +); + +const SecretBlindIndexData = model('SecretBlindIndexData', secretBlindIndexDataSchema); + +export default SecretBlindIndexData; \ No newline at end of file diff --git a/backend/src/models/serviceAccount.ts b/backend/src/models/serviceAccount.ts new file mode 100644 index 000000000..9ff9dcb03 --- /dev/null +++ b/backend/src/models/serviceAccount.ts @@ -0,0 +1,53 @@ +import { Schema, model, Types, Document } from 'mongoose'; + +export interface IServiceAccount extends Document { + _id: Types.ObjectId; + name: string; + organization: Types.ObjectId; + user: Types.ObjectId; + publicKey: string; + lastUsed: Date; + expiresAt: Date; + secretHash: string; +} + +const serviceAccountSchema = new Schema( + { + name: { + type: String, + required: true + }, + organization: { + type: Schema.Types.ObjectId, + ref: 'Organization', + required: true + }, + user: { // user who created the service account + type: Schema.Types.ObjectId, + ref: 'User', + required: true + }, + publicKey: { + type: String, + required: true + }, + lastUsed: { + type: Date + }, + expiresAt: { + type: Date + }, + secretHash: { + type: String, + required: true, + select: false + } + }, + { + timestamps: true + } +); + +const ServiceAccount = model('ServiceAccount', serviceAccountSchema); + +export default ServiceAccount; \ No newline at end of file diff --git a/backend/src/models/serviceAccountKey.ts b/backend/src/models/serviceAccountKey.ts new file mode 100644 index 000000000..637ac188b --- /dev/null +++ b/backend/src/models/serviceAccountKey.ts @@ -0,0 +1,44 @@ +import { Schema, model, Types } from 'mongoose'; + +export interface IServiceAccountKey { + _id: Types.ObjectId; + encryptedKey: string; + nonce: string; + sender: Types.ObjectId; + serviceAccount: Types.ObjectId; + workspace: Types.ObjectId; +} + +const serviceAccountKeySchema = new Schema( + { + encryptedKey: { + type: String, + required: true + }, + nonce: { + type: String, + required: true + }, + sender: { + type: Schema.Types.ObjectId, + required: true + }, + serviceAccount: { + type: Schema.Types.ObjectId, + ref: 'ServiceAccount', + required: true + }, + workspace: { + type: Schema.Types.ObjectId, + ref: 'Workspace', + required: true + } + }, + { + timestamps: true + } +); + +const ServiceAccountKey = model('ServiceAccountKey', serviceAccountKeySchema); + +export default ServiceAccountKey; diff --git a/backend/src/models/serviceAccountOrganizationPermission.ts b/backend/src/models/serviceAccountOrganizationPermission.ts new file mode 100644 index 000000000..6454bc6a0 --- /dev/null +++ b/backend/src/models/serviceAccountOrganizationPermission.ts @@ -0,0 +1,23 @@ +import { Schema, model, Types, Document } from 'mongoose'; + +export interface IServiceAccountOrganizationPermission extends Document { + _id: Types.ObjectId; + serviceAccount: Types.ObjectId; +} + +const serviceAccountOrganizationPermissionSchema = new Schema( + { + serviceAccount: { + type: Schema.Types.ObjectId, + ref: 'ServiceAccount', + required: true + } + }, + { + timestamps: true + } +); + +const ServiceAccountOrganizationPermission = model('ServiceAccountOrganizationPermission', serviceAccountOrganizationPermissionSchema); + +export default ServiceAccountOrganizationPermission; \ No newline at end of file diff --git a/backend/src/models/serviceAccountWorkspacePermission.ts b/backend/src/models/serviceAccountWorkspacePermission.ts new file mode 100644 index 000000000..01e4c4ba6 --- /dev/null +++ b/backend/src/models/serviceAccountWorkspacePermission.ts @@ -0,0 +1,44 @@ +import { Schema, model, Types, Document } from 'mongoose'; + +export interface IServiceAccountWorkspacePermission extends Document { + _id: Types.ObjectId; + serviceAccount: Types.ObjectId; + workspace: Types.ObjectId; + environment: string; + read: boolean; + write: boolean; +} + +const serviceAccountWorkspacePermissionSchema = new Schema( + { + serviceAccount: { + type: Schema.Types.ObjectId, + ref: 'ServiceAccount', + required: true + }, + workspace:{ + type: Schema.Types.ObjectId, + ref: 'Workspace', + required: true + }, + environment: { + type: String, + required: true + }, + read: { + type: Boolean, + default: false + }, + write: { + type: Boolean, + default: false + } + }, + { + timestamps: true + } +); + +const ServiceAccountWorkspacePermission = model('ServiceAccountWorkspacePermission', serviceAccountWorkspacePermissionSchema); + +export default ServiceAccountWorkspacePermission; \ No newline at end of file diff --git a/backend/src/models/serviceTokenData.ts b/backend/src/models/serviceTokenData.ts index 2467b0b82..3587a7ff4 100644 --- a/backend/src/models/serviceTokenData.ts +++ b/backend/src/models/serviceTokenData.ts @@ -1,69 +1,88 @@ -import { Schema, model, Types } from 'mongoose'; +import { Schema, model, Types, Document } from "mongoose"; -export interface IServiceTokenData { - name: string; - workspace: Types.ObjectId; - environment: string; - user: Types.ObjectId; - expiresAt: Date; - secretHash: string; - encryptedKey: string; - iv: string; - tag: string; - permissions: string[]; +export interface IServiceTokenData extends Document { + _id: Types.ObjectId; + name: string; + workspace: Types.ObjectId; + environment: string; + user: Types.ObjectId; + serviceAccount: Types.ObjectId; + lastUsed: Date; + expiresAt: Date; + secretHash: string; + encryptedKey: string; + iv: string; + tag: string; + secretPath: string; + permissions: string[]; } const serviceTokenDataSchema = new Schema( - { - name: { - type: String, - required: true - }, - workspace: { - type: Schema.Types.ObjectId, - ref: 'Workspace', - required: true - }, - environment: { // TODO: adapt to upcoming environment id - type: String, - required: true - }, - user: { - type: Schema.Types.ObjectId, - ref: 'User', - required: true - }, - expiresAt: { - type: Date - }, - secretHash: { - type: String, - required: true, - select: false - }, - encryptedKey: { - type: String, - select: false - }, - iv: { - type: String, - select: false - }, - tag: { - type: String, - select: false - }, - permissions: { - type: [String], - enum: ['read', 'write'], - default: ['read'] - } - }, - { - timestamps: true - } + { + name: { + type: String, + required: true, + }, + workspace: { + type: Schema.Types.ObjectId, + ref: "Workspace", + required: true, + }, + environment: { + type: String, + required: true, + }, + user: { + type: Schema.Types.ObjectId, + ref: "User", + required: true, + }, + serviceAccount: { + type: Schema.Types.ObjectId, + ref: "ServiceAccount", + }, + lastUsed: { + type: Date, + }, + expiresAt: { + type: Date, + }, + secretHash: { + type: String, + required: true, + select: false, + }, + encryptedKey: { + type: String, + select: false, + }, + iv: { + type: String, + select: false, + }, + tag: { + type: String, + select: false, + }, + permissions: { + type: [String], + enum: ["read", "write"], + default: ["read"], + }, + secretPath: { + type: String, + default: "/", + required: true, + }, + }, + { + timestamps: true, + } +); + +const ServiceTokenData = model( + "ServiceTokenData", + serviceTokenDataSchema ); -const ServiceTokenData = model('ServiceTokenData', serviceTokenDataSchema); - export default ServiceTokenData; diff --git a/backend/src/models/tokenVersion.ts b/backend/src/models/tokenVersion.ts new file mode 100644 index 000000000..890c0a272 --- /dev/null +++ b/backend/src/models/tokenVersion.ts @@ -0,0 +1,47 @@ +import { Schema, model, Types, Document } from 'mongoose'; + +export interface ITokenVersion extends Document { + user: Types.ObjectId; + ip: string; + userAgent: string; + refreshVersion: number; + accessVersion: number; + lastUsed: Date; +} + +const tokenVersionSchema = new Schema( + { + user: { + type: Schema.Types.ObjectId, + ref: 'User', + required: true + }, + ip: { + type: String, + required: true + }, + userAgent: { + type: String, + required: true + }, + refreshVersion: { + type: Number, + required: true + }, + accessVersion: { + type: Number, + required: true + }, + lastUsed: { + type: Date, + required: true + } + }, + { + timestamps: true + } +); + +const TokenVersion = model('TokenVersion', tokenVersionSchema); + +export default TokenVersion; \ No newline at end of file diff --git a/backend/src/models/user.ts b/backend/src/models/user.ts index 545c5256d..1c12720f8 100644 --- a/backend/src/models/user.ts +++ b/backend/src/models/user.ts @@ -1,7 +1,13 @@ import { Schema, model, Types, Document } from 'mongoose'; +export enum AuthProvider { + GOOGLE = 'google', +} + export interface IUser extends Document { _id: Types.ObjectId; + authId?: string; + authProvider?: AuthProvider; email: string; firstName?: string; lastName?: string; @@ -15,7 +21,6 @@ export interface IUser extends Document { tag?: string; salt?: string; verifier?: string; - refreshVersion?: number; isMfaEnabled: boolean; mfaMethods: boolean; devices: { @@ -26,9 +31,17 @@ export interface IUser extends Document { const userSchema = new Schema( { + authId: { + type: String, + }, + authProvider: { + type: String, + enum: AuthProvider, + }, email: { type: String, - required: true + required: true, + unique: true, }, firstName: { type: String @@ -77,11 +90,6 @@ const userSchema = new Schema( type: String, select: false }, - refreshVersion: { - type: Number, - default: 0, - select: false - }, isMfaEnabled: { type: Boolean, default: false @@ -94,7 +102,8 @@ const userSchema = new Schema( ip: String, userAgent: String }], - default: [] + default: [], + select: false } }, { diff --git a/backend/src/models/workspace.ts b/backend/src/models/workspace.ts index d68ae9416..ebd55d802 100644 --- a/backend/src/models/workspace.ts +++ b/backend/src/models/workspace.ts @@ -37,10 +37,6 @@ const workspaceSchema = new Schema({ name: "Development", slug: "dev" }, - { - name: "Test", - slug: "test" - }, { name: "Staging", slug: "staging" @@ -55,4 +51,4 @@ const workspaceSchema = new Schema({ const Workspace = model('Workspace', workspaceSchema); -export default Workspace; +export default Workspace; \ No newline at end of file diff --git a/backend/src/routes/status/status.ts b/backend/src/routes/status/status.ts index f793128be..91d0c9e85 100644 --- a/backend/src/routes/status/status.ts +++ b/backend/src/routes/status/status.ts @@ -5,11 +5,11 @@ const router = express.Router(); router.get( '/status', - (req: Request, res: Response) => { + async (req: Request, res: Response) => { res.status(200).json({ date: new Date(), message: 'Ok', - emailConfigured: getSmtpConfigured() + emailConfigured: await getSmtpConfigured() }) } ); diff --git a/backend/src/routes/v1/auth.ts b/backend/src/routes/v1/auth.ts index 638e4501b..ed86a236d 100644 --- a/backend/src/routes/v1/auth.ts +++ b/backend/src/routes/v1/auth.ts @@ -1,9 +1,11 @@ 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'; +import { AUTH_MODE_JWT } from '../../variables'; router.post('/token', validateRequest, authController.getNewToken); @@ -26,20 +28,50 @@ router.post( // deprecated (moved to api/v2/auth/login2) ); router.post( - '/logout', + '/logout', authLimiter, requireAuth({ - acceptedAuthModes: ['jwt'] - }), + acceptedAuthModes: [AUTH_MODE_JWT] + }), authController.logout ); router.post( - '/checkAuth', + '/checkAuth', requireAuth({ - acceptedAuthModes: ['jwt'] - }), + acceptedAuthModes: [AUTH_MODE_JWT] + }), 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, + authController.getCommonPasswords +); + +router.delete( + '/sessions', + authLimiter, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + authController.revokeAllSessions +); + export default router; diff --git a/backend/src/routes/v1/bot.ts b/backend/src/routes/v1/bot.ts index 4d3865562..83e126dc4 100644 --- a/backend/src/routes/v1/bot.ts +++ b/backend/src/routes/v1/bot.ts @@ -8,15 +8,16 @@ import { validateRequest } from '../../middleware'; import { botController } from '../../controllers/v1'; -import { ADMIN, MEMBER } from '../../variables'; +import { ADMIN, MEMBER, AUTH_MODE_JWT } from '../../variables'; router.get( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim().notEmpty(), validateRequest, @@ -26,7 +27,7 @@ router.get( router.patch( '/:botId/active', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireBotAuth({ acceptedRoles: [ADMIN, MEMBER] diff --git a/backend/src/routes/v1/index.ts b/backend/src/routes/v1/index.ts index 2dfe58baa..62ff08b14 100644 --- a/backend/src/routes/v1/index.ts +++ b/backend/src/routes/v1/index.ts @@ -15,6 +15,7 @@ import password from './password'; import stripe from './stripe'; import integration from './integration'; import integrationAuth from './integrationAuth'; +import secretsFolder from './secretsFolder'; export { signup, @@ -33,5 +34,6 @@ export { password, stripe, integration, - integrationAuth + integrationAuth, + secretsFolder }; diff --git a/backend/src/routes/v1/integration.ts b/backend/src/routes/v1/integration.ts index 72d818b61..b8e0b38bd 100644 --- a/backend/src/routes/v1/integration.ts +++ b/backend/src/routes/v1/integration.ts @@ -6,14 +6,19 @@ import { requireIntegrationAuthorizationAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT, + AUTH_MODE_API_KEY +} from '../../variables'; import { body, param } from 'express-validator'; import { integrationController } from '../../controllers/v1'; -router.post( // new: add new integration for integration auth +router.post( '/', requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER], @@ -25,6 +30,9 @@ router.post( // new: add new integration for integration auth body('appId').trim(), body('sourceEnvironment').trim(), body('targetEnvironment').trim(), + body('targetEnvironmentId').trim(), + body('targetService').trim(), + body('targetServiceId').trim(), body('owner').trim(), body('path').trim(), body('region').trim(), @@ -35,7 +43,7 @@ router.post( // new: add new integration for integration auth router.patch( '/:integrationId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuth({ acceptedRoles: [ADMIN, MEMBER] @@ -54,7 +62,7 @@ router.patch( router.delete( '/:integrationId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuth({ acceptedRoles: [ADMIN, MEMBER] diff --git a/backend/src/routes/v1/integrationAuth.ts b/backend/src/routes/v1/integrationAuth.ts index 2c1f5f045..f8fe15a4b 100644 --- a/backend/src/routes/v1/integrationAuth.ts +++ b/backend/src/routes/v1/integrationAuth.ts @@ -7,13 +7,18 @@ import { requireIntegrationAuthorizationAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT, + AUTH_MODE_API_KEY +} from '../../variables'; import { integrationAuthController } from '../../controllers/v1'; router.get( '/integration-options', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), integrationAuthController.getIntegrationOptions ); @@ -21,7 +26,7 @@ router.get( router.get( '/:integrationAuthId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER] @@ -34,11 +39,11 @@ router.get( router.post( '/oauth-token', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('workspaceId').exists().trim().notEmpty(), body('code').exists().trim().notEmpty(), @@ -49,25 +54,27 @@ router.post( router.post( '/access-token', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'body' - }), body('workspaceId').exists().trim().notEmpty(), body('accessId').trim(), body('accessToken').exists().trim().notEmpty(), + body('url').trim(), + body('namespace').trim(), body('integration').exists().trim().notEmpty(), validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'body' + }), integrationAuthController.saveIntegrationAccessToken ); router.get( '/:integrationAuthId/apps', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER] @@ -81,7 +88,7 @@ router.get( router.get( '/:integrationAuthId/teams', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER] @@ -91,10 +98,53 @@ router.get( integrationAuthController.getIntegrationAuthTeams ); +router.get( + '/:integrationAuthId/vercel/branches', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + requireIntegrationAuthorizationAuth({ + acceptedRoles: [ADMIN, MEMBER] + }), + param('integrationAuthId').exists().isString(), + query('appId').exists().isString(), + query('teamId').optional().isString(), + validateRequest, + integrationAuthController.getIntegrationAuthVercelBranches +); + +router.get( + '/:integrationAuthId/railway/environments', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + requireIntegrationAuthorizationAuth({ + acceptedRoles: [ADMIN, MEMBER] + }), + param('integrationAuthId').exists().isString(), + query('appId').exists().isString(), + validateRequest, + integrationAuthController.getIntegrationAuthRailwayEnvironments +); + +router.get( + '/:integrationAuthId/railway/services', + requireAuth({ + acceptedAuthModes: ['jwt'] + }), + requireIntegrationAuthorizationAuth({ + acceptedRoles: [ADMIN, MEMBER] + }), + param('integrationAuthId').exists().isString(), + query('appId').exists().isString(), + validateRequest, + integrationAuthController.getIntegrationAuthRailwayServices +); + router.delete( '/:integrationAuthId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireIntegrationAuthorizationAuth({ acceptedRoles: [ADMIN, MEMBER], diff --git a/backend/src/routes/v1/inviteOrg.ts b/backend/src/routes/v1/inviteOrg.ts index d8e2d67cc..9b4889bc9 100644 --- a/backend/src/routes/v1/inviteOrg.ts +++ b/backend/src/routes/v1/inviteOrg.ts @@ -3,11 +3,12 @@ const router = express.Router(); import { body } from 'express-validator'; import { requireAuth, validateRequest } from '../../middleware'; import { membershipOrgController } from '../../controllers/v1'; +import { AUTH_MODE_JWT } from '../../variables'; router.post( '/signup', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('inviteeEmail').exists().trim().notEmpty().isEmail(), body('organizationId').exists().trim().notEmpty(), @@ -18,6 +19,7 @@ router.post( router.post( '/verify', body('email').exists().trim().notEmpty(), + body('organizationId').exists().trim().notEmpty(), body('code').exists().trim().notEmpty(), validateRequest, membershipOrgController.verifyUserToOrganization diff --git a/backend/src/routes/v1/key.ts b/backend/src/routes/v1/key.ts index b66bd1276..be99c9c17 100644 --- a/backend/src/routes/v1/key.ts +++ b/backend/src/routes/v1/key.ts @@ -6,16 +6,17 @@ import { validateRequest } from '../../middleware'; import { body, param } from 'express-validator'; -import { ADMIN, MEMBER } from '../../variables'; +import { ADMIN, MEMBER, AUTH_MODE_JWT } from '../../variables'; import { keyController } from '../../controllers/v1'; router.post( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('key').exists(), @@ -26,10 +27,11 @@ router.post( router.get( '/:workspaceId/latest', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId'), validateRequest, diff --git a/backend/src/routes/v1/membership.ts b/backend/src/routes/v1/membership.ts index aaacada74..e830bd06d 100644 --- a/backend/src/routes/v1/membership.ts +++ b/backend/src/routes/v1/membership.ts @@ -4,13 +4,14 @@ import { body, param } from 'express-validator'; import { requireAuth, validateRequest } from '../../middleware'; import { membershipController } from '../../controllers/v1'; import { membershipController as EEMembershipControllers } from '../../ee/controllers/v1'; +import { AUTH_MODE_JWT } from '../../variables'; // note: ALL DEPRECIATED (moved to api/v2/workspace/:workspaceId/memberships/:membershipId) router.get( // used for old CLI (deprecate) '/:workspaceId/connect', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('workspaceId').exists().trim(), validateRequest, @@ -20,7 +21,7 @@ router.get( // used for old CLI (deprecate) router.delete( '/:membershipId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('membershipId').exists().trim(), validateRequest, @@ -30,7 +31,7 @@ router.delete( router.post( '/:membershipId/change-role', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('role').exists().trim(), validateRequest, @@ -40,7 +41,7 @@ router.post( router.post( '/:membershipId/deny-permissions', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('membershipId').isMongoId().exists().trim(), body('permissions').isArray().exists(), diff --git a/backend/src/routes/v1/membershipOrg.ts b/backend/src/routes/v1/membershipOrg.ts index 255b836aa..2863c53fb 100644 --- a/backend/src/routes/v1/membershipOrg.ts +++ b/backend/src/routes/v1/membershipOrg.ts @@ -3,12 +3,13 @@ const router = express.Router(); import { param } from 'express-validator'; import { requireAuth, validateRequest } from '../../middleware'; import { membershipOrgController } from '../../controllers/v1'; +import { AUTH_MODE_JWT } from '../../variables'; router.post( // TODO '/membershipOrg/:membershipOrgId/change-role', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('membershipOrgId'), validateRequest, @@ -18,7 +19,7 @@ router.post( router.delete( '/:membershipOrgId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('membershipOrgId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v1/organization.ts b/backend/src/routes/v1/organization.ts index 314f684ad..dded53f3a 100644 --- a/backend/src/routes/v1/organization.ts +++ b/backend/src/routes/v1/organization.ts @@ -6,13 +6,19 @@ import { requireOrganizationAuth, validateRequest } from '../../middleware'; -import { OWNER, ADMIN, MEMBER, ACCEPTED } from '../../variables'; +import { + OWNER, + ADMIN, + MEMBER, + ACCEPTED, + AUTH_MODE_JWT +} from '../../variables'; import { organizationController } from '../../controllers/v1'; router.get( // deprecated (moved to api/v2/users/me/organizations) '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), organizationController.getOrganizations ); @@ -20,7 +26,7 @@ router.get( // deprecated (moved to api/v2/users/me/organizations) router.post( // not used on frontend '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('organizationName').exists().trim().notEmpty(), validateRequest, @@ -30,7 +36,7 @@ router.post( // not used on frontend router.get( '/:organizationId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -44,7 +50,7 @@ router.get( router.get( // deprecated (moved to api/v2/organizations/:organizationId/memberships) '/:organizationId/users', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -58,7 +64,7 @@ router.get( // deprecated (moved to api/v2/organizations/:organizationId/members router.get( '/:organizationId/my-workspaces', // deprecated (moved to api/v2/organizations/:organizationId/workspaces) requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -72,7 +78,7 @@ router.get( router.patch( '/:organizationId/name', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -87,7 +93,7 @@ router.patch( router.get( '/:organizationId/incidentContactOrg', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -101,7 +107,7 @@ router.get( router.post( '/:organizationId/incidentContactOrg', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -116,7 +122,7 @@ router.post( router.delete( '/:organizationId/incidentContactOrg', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -131,7 +137,7 @@ router.delete( router.post( '/:organizationId/customer-portal-session', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -145,7 +151,7 @@ router.post( router.get( '/:organizationId/subscriptions', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -159,7 +165,7 @@ router.get( router.get( '/:organizationId/workspace-memberships', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], diff --git a/backend/src/routes/v1/password.ts b/backend/src/routes/v1/password.ts index bc353cf08..b04fa36af 100644 --- a/backend/src/routes/v1/password.ts +++ b/backend/src/routes/v1/password.ts @@ -4,11 +4,14 @@ import { body } from 'express-validator'; import { requireAuth, requireSignupAuth, validateRequest } from '../../middleware'; import { passwordController } from '../../controllers/v1'; import { passwordLimiter } from '../../helpers/rateLimiter'; +import { + AUTH_MODE_JWT +} from '../../variables'; router.post( '/srp1', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('clientPublicKey').exists().isString().trim().notEmpty(), validateRequest, @@ -19,7 +22,7 @@ router.post( '/change-password', passwordLimiter, requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('clientProof').exists().trim().notEmpty(), body('protectedKey').exists().isString().trim().notEmpty(), @@ -62,7 +65,7 @@ router.post( '/backup-private-key', passwordLimiter, requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('clientProof').exists().isString().trim().notEmpty(), body('encryptedPrivateKey').exists().isString().trim().notEmpty(), // (backup) private key encrypted under a strong key diff --git a/backend/src/routes/v1/secret.ts b/backend/src/routes/v1/secret.ts index cce105500..e55dfaf43 100644 --- a/backend/src/routes/v1/secret.ts +++ b/backend/src/routes/v1/secret.ts @@ -8,15 +8,22 @@ import { } from '../../middleware'; import { body, query, param } from 'express-validator'; import { secretController } from '../../controllers/v1'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT +} from '../../variables'; + +// note to devs: these endpoints will be deprecated in favor of v2 router.post( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), body('secrets').exists(), body('keys').exists(), @@ -30,10 +37,11 @@ router.post( router.get( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('environment').exists().trim(), query('channel'), diff --git a/backend/src/routes/v1/secretsFolder.ts b/backend/src/routes/v1/secretsFolder.ts new file mode 100644 index 000000000..2644a835b --- /dev/null +++ b/backend/src/routes/v1/secretsFolder.ts @@ -0,0 +1,70 @@ +import express from "express"; +const router = express.Router(); +import { + requireAuth, + requireWorkspaceAuth, + validateRequest, +} from "../../middleware"; +import { body, param, query } from "express-validator"; +import { + createFolder, + deleteFolder, + getFolders, + updateFolderById, +} from "../../controllers/v1/secretsFolderController"; +import { ADMIN, MEMBER } from "../../variables"; + +router.post( + "/", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + }), + body("workspaceId").exists(), + body("environment").exists(), + body("folderName").exists(), + body("parentFolderId"), + validateRequest, + createFolder +); + +router.patch( + "/:folderId", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + body("workspaceId").exists(), + body("environment").exists(), + param("folderId").not().isIn(["root"]).exists(), + validateRequest, + updateFolderById +); + +router.delete( + "/:folderId", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + body("workspaceId").exists(), + body("environment").exists(), + param("folderId").not().isIn(["root"]).exists(), + validateRequest, + deleteFolder +); + +router.get( + "/", + requireAuth({ + acceptedAuthModes: ["jwt"], + }), + query("workspaceId").exists().isString().trim(), + query("environment").exists().isString().trim(), + query("parentFolderId").optional().isString().trim(), + validateRequest, + getFolders +); + +export default router; diff --git a/backend/src/routes/v1/serviceToken.ts b/backend/src/routes/v1/serviceToken.ts index 18487ac3e..2b75e7cbf 100644 --- a/backend/src/routes/v1/serviceToken.ts +++ b/backend/src/routes/v1/serviceToken.ts @@ -7,7 +7,11 @@ import { validateRequest } from '../../middleware'; import { body } from 'express-validator'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT +} from '../../variables'; import { serviceTokenController } from '../../controllers/v1'; // note: deprecate service-token routes in favor of service-token data routes/structure @@ -21,11 +25,11 @@ router.get( router.post( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], - location: 'body' + locationWorkspaceId: 'body' }), body('name').exists().trim().notEmpty(), body('workspaceId').exists().trim().notEmpty(), diff --git a/backend/src/routes/v1/user.ts b/backend/src/routes/v1/user.ts index e73a6e0f2..b9d88dfb1 100644 --- a/backend/src/routes/v1/user.ts +++ b/backend/src/routes/v1/user.ts @@ -2,11 +2,14 @@ import express from 'express'; const router = express.Router(); import { requireAuth } from '../../middleware'; import { userController } from '../../controllers/v1'; +import { + AUTH_MODE_JWT +} from '../../variables'; router.get( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), userController.getUser ); diff --git a/backend/src/routes/v1/userAction.ts b/backend/src/routes/v1/userAction.ts index b14ab3471..c8d21f918 100644 --- a/backend/src/routes/v1/userAction.ts +++ b/backend/src/routes/v1/userAction.ts @@ -3,12 +3,13 @@ const router = express.Router(); import { requireAuth, validateRequest } from '../../middleware'; import { body, query } from 'express-validator'; import { userActionController } from '../../controllers/v1'; +import { AUTH_MODE_JWT } from '../../variables'; // note: [userAction] will be deprecated in /v2 in favor of [action] router.post( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('action'), validateRequest, @@ -18,7 +19,7 @@ router.post( router.get( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), query('action'), validateRequest, diff --git a/backend/src/routes/v1/workspace.ts b/backend/src/routes/v1/workspace.ts index 801462662..431a2e4f9 100644 --- a/backend/src/routes/v1/workspace.ts +++ b/backend/src/routes/v1/workspace.ts @@ -6,16 +6,21 @@ import { requireWorkspaceAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT +} from '../../variables'; import { workspaceController, membershipController } from '../../controllers/v1'; router.get( '/:workspaceId/keys', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -25,10 +30,11 @@ router.get( router.get( '/:workspaceId/users', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -38,7 +44,7 @@ router.get( router.get( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), workspaceController.getWorkspaces ); @@ -46,10 +52,11 @@ router.get( router.get( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -59,7 +66,7 @@ router.get( router.post( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('workspaceName').exists().trim().notEmpty(), body('organizationId').exists().trim().notEmpty(), @@ -70,10 +77,11 @@ router.post( router.delete( '/:workspaceId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN] + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -83,10 +91,11 @@ router.delete( router.post( '/:workspaceId/name', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('name').exists().trim().notEmpty(), @@ -97,10 +106,11 @@ router.post( router.post( '/:workspaceId/invite-signup', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('email').exists().trim().notEmpty(), @@ -111,10 +121,11 @@ router.post( router.get( '/:workspaceId/integrations', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -124,10 +135,11 @@ router.get( router.get( '/:workspaceId/authorizations', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -137,10 +149,11 @@ router.get( router.get( '/:workspaceId/service-tokens', // deprecate requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v2/apiKeyData.ts b/backend/src/routes/v2/apiKeyData.ts index 07bbcbc44..939bdbe1f 100644 --- a/backend/src/routes/v2/apiKeyData.ts +++ b/backend/src/routes/v2/apiKeyData.ts @@ -1,16 +1,19 @@ import express from 'express'; const router = express.Router(); +import { param, body } from 'express-validator'; import { requireAuth, validateRequest } from '../../middleware'; -import { param, body } from 'express-validator'; import { apiKeyDataController } from '../../controllers/v2'; +import { + AUTH_MODE_JWT +} from '../../variables'; router.get( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), apiKeyDataController.getAPIKeyData ); @@ -18,7 +21,7 @@ router.get( router.post( '/', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('name').exists().trim(), body('expiresIn'), // measured in ms @@ -29,7 +32,7 @@ router.post( router.delete( '/:apiKeyDataId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('apiKeyDataId').exists().trim(), validateRequest, diff --git a/backend/src/routes/v2/auth.ts b/backend/src/routes/v2/auth.ts index 128a08fae..288004e65 100644 --- a/backend/src/routes/v2/auth.ts +++ b/backend/src/routes/v2/auth.ts @@ -26,7 +26,7 @@ router.post( router.post( '/mfa/send', authLimiter, - body('email').isString().trim().notEmpty(), + body('email').isString().trim().notEmpty().isEmail(), validateRequest, authController.sendMfaToken ); diff --git a/backend/src/routes/v2/environment.ts b/backend/src/routes/v2/environment.ts index 11afa4f2e..0eb4b4a20 100644 --- a/backend/src/routes/v2/environment.ts +++ b/backend/src/routes/v2/environment.ts @@ -7,15 +7,20 @@ import { requireWorkspaceAuth, validateRequest, } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT +} from '../../variables'; router.post( '/:workspaceId/environments', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('environmentSlug').exists().trim(), @@ -27,10 +32,11 @@ router.post( router.put( '/:workspaceId/environments', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('environmentSlug').exists().trim(), @@ -43,10 +49,11 @@ router.put( router.delete( '/:workspaceId/environments', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('environmentSlug').exists().trim(), @@ -57,14 +64,15 @@ router.delete( router.get( '/:workspaceId/environments', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [MEMBER, ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, environmentController.getAllAccessibleEnvironmentsOfWorkspace ); -export default router; +export default router; \ No newline at end of file diff --git a/backend/src/routes/v2/index.ts b/backend/src/routes/v2/index.ts index 538ee4800..c088771eb 100644 --- a/backend/src/routes/v2/index.ts +++ b/backend/src/routes/v2/index.ts @@ -6,6 +6,7 @@ import workspace from './workspace'; import secret from './secret'; // deprecated import secrets from './secrets'; import serviceTokenData from './serviceTokenData'; +import serviceAccounts from './serviceAccounts'; import apiKeyData from './apiKeyData'; import environment from "./environment" import tags from "./tags" @@ -19,6 +20,7 @@ export { secret, secrets, serviceTokenData, + serviceAccounts, apiKeyData, environment, tags diff --git a/backend/src/routes/v2/organizations.ts b/backend/src/routes/v2/organizations.ts index e1488e8a7..eb2cef8eb 100644 --- a/backend/src/routes/v2/organizations.ts +++ b/backend/src/routes/v2/organizations.ts @@ -6,8 +6,15 @@ import { requireMembershipOrgAuth, validateRequest } from '../../middleware'; -import { body, param, query } from 'express-validator'; -import { OWNER, ADMIN, MEMBER, ACCEPTED } from '../../variables'; +import { body, param } from 'express-validator'; +import { + OWNER, + ADMIN, + MEMBER, + ACCEPTED, + AUTH_MODE_JWT, + AUTH_MODE_API_KEY +} from '../../variables'; import { organizationsController } from '../../controllers/v2'; // TODO: /POST to create membership @@ -17,7 +24,7 @@ router.get( param('organizationId').exists().trim(), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN, MEMBER], @@ -33,14 +40,15 @@ router.patch( body('role').exists().isString().trim().isIn([OWNER, ADMIN, MEMBER]), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN], acceptedStatuses: [ACCEPTED] }), requireMembershipOrgAuth({ - acceptedRoles: [OWNER, ADMIN] + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] }), organizationsController.updateOrganizationMembership ); @@ -51,14 +59,15 @@ router.delete( param('membershipId').exists().trim(), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN], acceptedStatuses: [ACCEPTED] }), requireMembershipOrgAuth({ - acceptedRoles: [OWNER, ADMIN] + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] }), organizationsController.deleteOrganizationMembership ); @@ -68,7 +77,7 @@ router.get( param('organizationId').exists().trim(), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireOrganizationAuth({ acceptedRoles: [OWNER, ADMIN], @@ -77,4 +86,18 @@ router.get( organizationsController.getOrganizationWorkspaces ); +router.get( + '/:organizationId/service-accounts', + param('organizationId').exists().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + organizationsController.getOrganizationServiceAccounts +); + export default router; \ No newline at end of file diff --git a/backend/src/routes/v2/secret.ts b/backend/src/routes/v2/secret.ts index f1b61b47c..f2c825ba8 100644 --- a/backend/src/routes/v2/secret.ts +++ b/backend/src/routes/v2/secret.ts @@ -6,7 +6,14 @@ import { validateRequest } from '../../middleware'; import { body, param, query } from 'express-validator'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_TOKEN, + PERMISSION_READ_SECRETS, + PERMISSION_WRITE_SECRETS +} from '../../variables'; import { CreateSecretRequestBody, ModifySecretRequestBody } from '../../types/secret'; import { secretController } from '../../controllers/v2'; @@ -17,10 +24,11 @@ const router = express.Router(); router.post( '/batch-create/workspace/:workspaceId/environment/:environment', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().isMongoId().trim(), param('environment').exists().trim(), @@ -33,10 +41,11 @@ router.post( router.post( '/workspace/:workspaceId/environment/:environment', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().isMongoId().trim(), param('environment').exists().trim(), @@ -51,10 +60,11 @@ router.get( param('workspaceId').exists().trim(), query("environment").exists(), requireAuth({ - acceptedAuthModes: ['jwt', 'serviceToken'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_SERVICE_TOKEN] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('channel'), validateRequest, @@ -64,10 +74,11 @@ router.get( router.get( '/:secretId', requireAuth({ - acceptedAuthModes: ['jwt', 'serviceToken'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_SERVICE_TOKEN] }), requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_READ_SECRETS] }), validateRequest, secretController.getSecret @@ -76,13 +87,14 @@ router.get( router.delete( '/batch/workspace/:workspaceId/environment/:environmentName', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), param('workspaceId').exists().isMongoId().trim(), param('environmentName').exists().trim(), body('secretIds').exists().isArray().custom(array => array.length > 0), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.deleteSecrets @@ -91,10 +103,11 @@ router.delete( router.delete( '/:secretId', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireSecretAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_READ_SECRETS, PERMISSION_WRITE_SECRETS] }), param('secretId').isMongoId(), validateRequest, @@ -104,29 +117,30 @@ router.delete( router.patch( '/batch-modify/workspace/:workspaceId/environment/:environmentName', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('secrets').exists().isArray().custom((secrets: ModifySecretRequestBody[]) => secrets.length > 0), param('workspaceId').exists().isMongoId().trim(), param('environmentName').exists().trim(), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.updateSecrets ); - router.patch( '/workspace/:workspaceId/environment/:environmentName', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), body('secret').isObject(), param('workspaceId').exists().isMongoId().trim(), param('environmentName').exists().trim(), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), validateRequest, secretController.updateSecret diff --git a/backend/src/routes/v2/secrets.ts b/backend/src/routes/v2/secrets.ts index 983a8e54f..3cf7e83d5 100644 --- a/backend/src/routes/v2/secrets.ts +++ b/backend/src/routes/v2/secrets.ts @@ -1,199 +1,237 @@ -import express from 'express'; +import express from "express"; const router = express.Router(); +import { Types } from "mongoose"; import { - requireAuth, - requireWorkspaceAuth, - requireSecretsAuth, - validateRequest -} from '../../middleware'; -import { query, body } from 'express-validator'; -import { secretsController } from '../../controllers/v2'; -import { validateSecrets } from '../../helpers/secret'; + requireAuth, + requireWorkspaceAuth, + requireSecretsAuth, + validateRequest, +} from "../../middleware"; +import { validateClientForSecrets } from "../../validation"; +import { query, body } from "express-validator"; +import { secretsController } from "../../controllers/v2"; import { - ADMIN, - MEMBER, - SECRET_PERSONAL, - SECRET_SHARED -} from '../../variables'; -import { - BatchSecretRequest -} from '../../types/secret'; + ADMIN, + MEMBER, + SECRET_PERSONAL, + SECRET_SHARED, + PERMISSION_READ_SECRETS, + PERMISSION_WRITE_SECRETS, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY, +} from "../../variables"; +import { BatchSecretRequest } from "../../types/secret"; router.post( - '/batch', - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken'], - requiredServiceTokenPermissions: ['read', 'write'] + "/batch", + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + }), + body("workspaceId").exists().isString().trim(), + body("folderId").default("root").isString().trim(), + body("environment").exists().isString().trim(), + body("secretPath").optional().isString().trim(), + body("requests") + .exists() + .custom(async (requests: BatchSecretRequest[], { req }) => { + if (Array.isArray(requests)) { + const secretIds = requests + .map((request) => request.secret._id) + .filter((secretId) => secretId !== undefined); + + if (secretIds.length > 0) { + req.secrets = await validateClientForSecrets({ + authData: req.authData, + secretIds: secretIds.map( + (secretId: string) => new Types.ObjectId(secretId) + ), + requiredPermissions: [], + }); + } + } + return true; }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'body' - }), - body('workspaceId').exists().isString().trim(), - body('environment').exists().isString().trim(), - body('requests') - .exists() - .custom(async (requests: BatchSecretRequest[], { req }) => { - if (Array.isArray(requests)) { - const secretIds = requests - .map((request) => request.secret._id) - .filter((secretId) => secretId !== undefined) - - if (secretIds.length > 0) { - const relevantSecrets = await validateSecrets({ - userId: req.user._id.toString(), - secretIds - }); - - req.secrets = relevantSecrets; - } - } - return true; - }), - validateRequest, - secretsController.batchSecrets + validateRequest, + secretsController.batchSecrets ); router.post( - '/', - body('workspaceId').exists().isString().trim(), - body('environment').exists().isString().trim(), - body('secrets') - .exists() - .custom((value) => { - if (Array.isArray(value)) { - // case: create multiple secrets - if (value.length === 0) throw new Error('secrets cannot be an empty array') - for (const secret of value) { - if ( - !secret.type || - !(secret.type === SECRET_PERSONAL || secret.type === SECRET_SHARED) || - !secret.secretKeyCiphertext || - !secret.secretKeyIV || - !secret.secretKeyTag || - (typeof secret.secretValueCiphertext !== 'string') || - !secret.secretValueIV || - !secret.secretValueTag - ) { - throw new Error('secrets array must contain objects that have required secret properties'); - } - } - } else if (typeof value === 'object') { - // case: update 1 secret - if ( - !value.type || - !(value.type === SECRET_PERSONAL || value.type === SECRET_SHARED) || - !value.secretKeyCiphertext || - !value.secretKeyIV || - !value.secretKeyTag || - !value.secretValueCiphertext || - !value.secretValueIV || - !value.secretValueTag - ) { - throw new Error('secrets object is missing required secret properties'); - } - } else { - throw new Error('secrets must be an object or an array of objects') - } + "/", + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("folderId").default("root").isString().trim(), + body("secretPath").optional().isString().trim(), + body("secrets") + .exists() + .custom((value) => { + if (Array.isArray(value)) { + // case: create multiple secrets + if (value.length === 0) + throw new Error("secrets cannot be an empty array"); + for (const secret of value) { + if ( + !secret.type || + !( + secret.type === SECRET_PERSONAL || secret.type === SECRET_SHARED + ) || + !secret.secretKeyCiphertext || + !secret.secretKeyIV || + !secret.secretKeyTag || + typeof secret.secretValueCiphertext !== "string" || + !secret.secretValueIV || + !secret.secretValueTag + ) { + throw new Error( + "secrets array must contain objects that have required secret properties" + ); + } + } + } else if (typeof value === "object") { + // case: update 1 secret + if ( + !value.type || + !(value.type === SECRET_PERSONAL || value.type === SECRET_SHARED) || + !value.secretKeyCiphertext || + !value.secretKeyIV || + !value.secretKeyTag || + !value.secretValueCiphertext || + !value.secretValueIV || + !value.secretValueTag + ) { + throw new Error( + "secrets object is missing required secret properties" + ); + } + } else { + throw new Error("secrets must be an object or an array of objects"); + } - return true; - }), - validateRequest, - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken'], - requiredServiceTokenPermissions: ['write'] + return true; }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'body' - }), - secretsController.createSecrets + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + }), + secretsController.createSecrets ); router.get( - '/', - query('workspaceId').exists().trim(), - query('environment').exists().trim(), - query('tagSlugs'), - validateRequest, - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken'], - requiredServiceTokenPermissions: ['read'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'query' - }), - secretsController.getSecrets + "/", + query("workspaceId").exists().trim(), + query("environment").exists().trim(), + query("tagSlugs"), + query("folderId").default("root").isString().trim(), + query("secretPath").optional().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + }), + secretsController.getSecrets ); router.patch( - '/', - body('secrets') - .exists() - .custom((value) => { - if (Array.isArray(value)) { - // case: update multiple secrets - if (value.length === 0) throw new Error('secrets cannot be an empty array') - for (const secret of value) { - if ( - !secret.id - ) { - throw new Error('Each secret must contain a ID property'); - } - } - } else if (typeof value === 'object') { - // case: update 1 secret - if ( - !value.id - ) { - throw new Error('secret must contain a ID property'); - } - } else { - throw new Error('secrets must be an object or an array of objects') - } + "/", + body("secrets") + .exists() + .custom((value) => { + if (Array.isArray(value)) { + // case: update multiple secrets + if (value.length === 0) + throw new Error("secrets cannot be an empty array"); + for (const secret of value) { + if (!secret.id) { + throw new Error("Each secret must contain a ID property"); + } + } + } else if (typeof value === "object") { + // case: update 1 secret + if (!value.id) { + throw new Error("secret must contain a ID property"); + } + } else { + throw new Error("secrets must be an object or an array of objects"); + } - return true; - }), - validateRequest, - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken'], - requiredServiceTokenPermissions: ['write'] + return true; }), - requireSecretsAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - secretsController.updateSecrets + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + ], + }), + requireSecretsAuth({ + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_WRITE_SECRETS], + }), + secretsController.updateSecrets ); router.delete( - '/', - body('secretIds') - .exists() - .custom((value) => { - // case: delete 1 secret - if (typeof value === 'string') return true; + "/", + body("secretIds") + .exists() + .custom((value) => { + // case: delete 1 secret + if (typeof value === "string") return true; - if (Array.isArray(value)) { - // case: delete multiple secrets - if (value.length === 0) throw new Error('secrets cannot be an empty array'); - return value.every((id: string) => typeof id === 'string') - } + if (Array.isArray(value)) { + // case: delete multiple secrets + if (value.length === 0) + throw new Error("secrets cannot be an empty array"); + return value.every((id: string) => typeof id === "string"); + } - throw new Error('secretIds must be a string or an array of strings'); - }) - .not() - .isEmpty(), - validateRequest, - requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey', 'serviceToken'], - requiredServiceTokenPermissions: ['write'] - }), - requireSecretsAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - secretsController.deleteSecrets + throw new Error("secretIds must be a string or an array of strings"); + }) + .not() + .isEmpty(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + ], + }), + requireSecretsAuth({ + acceptedRoles: [ADMIN, MEMBER], + requiredPermissions: [PERMISSION_WRITE_SECRETS], + }), + secretsController.deleteSecrets ); export default router; - diff --git a/backend/src/routes/v2/serviceAccounts.ts b/backend/src/routes/v2/serviceAccounts.ts new file mode 100644 index 000000000..6f0db91b7 --- /dev/null +++ b/backend/src/routes/v2/serviceAccounts.ts @@ -0,0 +1,159 @@ +import express from 'express'; +const router = express.Router(); +import { + requireAuth, + requireOrganizationAuth, + requireWorkspaceAuth, + requireServiceAccountAuth, + requireServiceAccountWorkspacePermissionAuth, + validateRequest +} from '../../middleware'; +import { param, query, body } from 'express-validator'; +import { + OWNER, + ADMIN, + MEMBER, + ACCEPTED, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT +} from '../../variables'; +import { serviceAccountsController } from '../../controllers/v2'; + +router.get( // TODO: check + '/me', + requireAuth({ + acceptedAuthModes: [AUTH_MODE_SERVICE_ACCOUNT] + }), + serviceAccountsController.getCurrentServiceAccount +); + +router.get( + '/:serviceAccountId', + param('serviceAccountId').exists().isString().trim(), + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.getServiceAccountById +); + +router.post( + '/', + body('organizationId').exists().isString().trim(), + body('name').exists().isString().trim(), + body('publicKey').exists().isString().trim(), + body('expiresIn').isNumeric(), // measured in ms + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireOrganizationAuth({ + acceptedRoles: [OWNER, ADMIN, MEMBER], + acceptedStatuses: [ACCEPTED], + locationOrganizationId: 'body' + }), + serviceAccountsController.createServiceAccount +); + +router.patch( + '/:serviceAccountId/name', + param('serviceAccountId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.changeServiceAccountName +); + +router.delete( + '/:serviceAccountId', + param('serviceAccountId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.deleteServiceAccount +); + +router.get( + '/:serviceAccountId/permissions/workspace', + param('serviceAccountId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.getServiceAccountWorkspacePermissions +); + +router.post( + '/:serviceAccountId/permissions/workspace', + param('serviceAccountId').exists().isString().trim(), + body('workspaceId').exists().isString().notEmpty(), + body('environment').exists().isString().notEmpty(), + body('read').isBoolean().optional(), + body('write').isBoolean().optional(), + body('encryptedKey').exists().isString().notEmpty(), + body('nonce').exists().isString().notEmpty(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'body' + }), + serviceAccountsController.addServiceAccountWorkspacePermission +); + +router.delete( + '/:serviceAccountId/permissions/workspace/:serviceAccountWorkspacePermissionId', + param('serviceAccountId').exists().isString().trim(), + param('serviceAccountWorkspacePermissionId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + requireServiceAccountWorkspacePermissionAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.deleteServiceAccountWorkspacePermission +); + +router.get( + '/:serviceAccountId/keys', + query('workspaceId').optional().isString(), + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_SERVICE_ACCOUNT] + }), + requireServiceAccountAuth({ + acceptedRoles: [OWNER, ADMIN], + acceptedStatuses: [ACCEPTED] + }), + serviceAccountsController.getServiceAccountKeys +); + +export default router; \ No newline at end of file diff --git a/backend/src/routes/v2/serviceTokenData.ts b/backend/src/routes/v2/serviceTokenData.ts index 11e8b1c71..e96064715 100644 --- a/backend/src/routes/v2/serviceTokenData.ts +++ b/backend/src/routes/v2/serviceTokenData.ts @@ -1,66 +1,79 @@ -import express from 'express'; +import express from "express"; const router = express.Router(); import { - requireAuth, - requireWorkspaceAuth, - requireServiceTokenDataAuth, - validateRequest -} from '../../middleware'; -import { param, body } from 'express-validator'; + requireAuth, + requireWorkspaceAuth, + requireServiceTokenDataAuth, + validateRequest, +} from "../../middleware"; +import { param, body } from "express-validator"; import { - ADMIN, - MEMBER, -} from '../../variables'; -import { serviceTokenDataController } from '../../controllers/v2'; + ADMIN, + MEMBER, + PERMISSION_WRITE_SECRETS, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, +} from "../../variables"; +import { serviceTokenDataController } from "../../controllers/v2"; router.get( - '/', - requireAuth({ - acceptedAuthModes: ['serviceToken'] - }), - serviceTokenDataController.getServiceTokenData + "/", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_SERVICE_TOKEN], + }), + serviceTokenDataController.getServiceTokenData ); router.post( - '/', - requireAuth({ - acceptedAuthModes: ['jwt'] - }), - requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER], - location: 'body' - }), - body('name').exists().isString().trim(), - body('workspaceId').exists().isString().trim(), - body('environment').exists().isString().trim(), - body('encryptedKey').exists().isString().trim(), - body('iv').exists().isString().trim(), - body('tag').exists().isString().trim(), - body('expiresIn').exists().isNumeric(), // measured in ms - body('permissions').isArray({ min: 1 }).custom((value: string[]) => { - const allowedPermissions = ['read', 'write']; - const invalidValues = value.filter((v) => !allowedPermissions.includes(v)); - if (invalidValues.length > 0) { - throw new Error(`permissions contains invalid values: ${invalidValues.join(', ')}`); - } + "/", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_SERVICE_ACCOUNT], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + }), + body("name").exists().isString().trim(), + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("encryptedKey").exists().isString().trim(), + body("iv").exists().isString().trim(), + body("secretPath").isString().default("/").trim(), + body("tag").exists().isString().trim(), + body("expiresIn").exists().isNumeric(), // measured in ms + body("permissions") + .isArray({ min: 1 }) + .custom((value: string[]) => { + const allowedPermissions = ["read", "write"]; + const invalidValues = value.filter( + (v) => !allowedPermissions.includes(v) + ); + if (invalidValues.length > 0) { + throw new Error( + `permissions contains invalid values: ${invalidValues.join(", ")}` + ); + } - return true + return true; }), - validateRequest, - serviceTokenDataController.createServiceTokenData + validateRequest, + serviceTokenDataController.createServiceTokenData ); router.delete( - '/:serviceTokenDataId', - requireAuth({ - acceptedAuthModes: ['jwt'] - }), - requireServiceTokenDataAuth({ - acceptedRoles: [ADMIN, MEMBER] - }), - param('serviceTokenDataId').exists().trim(), - validateRequest, - serviceTokenDataController.deleteServiceTokenData + "/:serviceTokenDataId", + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT], + }), + requireServiceTokenDataAuth({ + acceptedRoles: [ADMIN, MEMBER], + }), + param("serviceTokenDataId").exists().trim(), + validateRequest, + serviceTokenDataController.deleteServiceTokenData ); -export default router; \ No newline at end of file +export default router; diff --git a/backend/src/routes/v2/tags.ts b/backend/src/routes/v2/tags.ts index d78e1e0f1..c9a11c1bc 100644 --- a/backend/src/routes/v2/tags.ts +++ b/backend/src/routes/v2/tags.ts @@ -5,17 +5,22 @@ import { tagController } from '../../controllers/v2'; import { requireAuth, requireWorkspaceAuth, - validateRequest, + validateRequest } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT +} from '../../variables'; router.get( '/:workspaceId/tags', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [MEMBER, ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -25,7 +30,7 @@ router.get( router.delete( '/tags/:tagId', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), param('tagId').exists().trim(), validateRequest, @@ -35,10 +40,11 @@ router.delete( router.post( '/:workspaceId/tags', requireAuth({ - acceptedAuthModes: ['jwt'], + acceptedAuthModes: [AUTH_MODE_JWT], }), requireWorkspaceAuth({ acceptedRoles: [MEMBER, ADMIN], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('name').exists().trim(), diff --git a/backend/src/routes/v2/users.ts b/backend/src/routes/v2/users.ts index bdf0978e1..63ae5eee9 100644 --- a/backend/src/routes/v2/users.ts +++ b/backend/src/routes/v2/users.ts @@ -6,11 +6,15 @@ import { } from '../../middleware'; import { body } from 'express-validator'; import { usersController } from '../../controllers/v2'; +import { + AUTH_MODE_JWT, + AUTH_MODE_API_KEY +} from '../../variables'; router.get( '/me', requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), usersController.getMe ); @@ -18,7 +22,7 @@ router.get( router.patch( '/me/mfa', requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), body('isMfaEnabled').exists().isBoolean(), validateRequest, @@ -28,7 +32,7 @@ router.patch( router.get( '/me/organizations', requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), usersController.getMyOrganizations ); diff --git a/backend/src/routes/v2/workspace.ts b/backend/src/routes/v2/workspace.ts index 6183c9e66..e258636fb 100644 --- a/backend/src/routes/v2/workspace.ts +++ b/backend/src/routes/v2/workspace.ts @@ -7,16 +7,23 @@ import { requireWorkspaceAuth, validateRequest } from '../../middleware'; -import { ADMIN, MEMBER } from '../../variables'; +import { + ADMIN, + MEMBER, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../../variables'; import { workspaceController } from '../../controllers/v2'; router.post( '/:workspaceId/secrets', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), body('secrets').exists(), body('keys').exists(), @@ -30,10 +37,11 @@ router.post( router.get( '/:workspaceId/secrets', requireAuth({ - acceptedAuthModes: ['jwt', 'serviceToken'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_SERVICE_TOKEN] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), query('environment').exists().trim(), query('channel'), @@ -45,10 +53,11 @@ router.get( router.get( '/:workspaceId/encrypted-key', requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, @@ -58,27 +67,27 @@ router.get( router.get( '/:workspaceId/service-token-data', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), validateRequest, workspaceController.getWorkspaceServiceTokenData ); -// TODO: /POST to create membership and re-route inviting user to workspace there - router.get( // new - TODO: rewire dashboard to this route '/:workspaceId/memberships', param('workspaceId').exists().trim(), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), workspaceController.getWorkspaceMemberships ); @@ -90,13 +99,15 @@ router.patch( // TODO - rewire dashboard to this route body('role').exists().isString().trim().isIn([ADMIN, MEMBER]), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), requireMembershipAuth({ - acceptedRoles: [ADMIN] + acceptedRoles: [ADMIN], + locationMembershipId: 'params' }), workspaceController.updateWorkspaceMembership ); @@ -107,13 +118,15 @@ router.delete( // TODO - rewire dashboard to this route param('membershipId').exists().trim(), validateRequest, requireAuth({ - acceptedAuthModes: ['jwt', 'apiKey'] + acceptedAuthModes: [AUTH_MODE_JWT, AUTH_MODE_API_KEY] }), requireWorkspaceAuth({ acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' }), requireMembershipAuth({ - acceptedRoles: [ADMIN] + acceptedRoles: [ADMIN], + locationMembershipId: 'params' }), workspaceController.deleteWorkspaceMembership ); @@ -121,10 +134,11 @@ router.delete( // TODO - rewire dashboard to this route router.patch( '/:workspaceId/auto-capitalization', requireAuth({ - acceptedAuthModes: ['jwt'] + acceptedAuthModes: [AUTH_MODE_JWT] }), requireWorkspaceAuth({ - acceptedRoles: [ADMIN, MEMBER] + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: 'params' }), param('workspaceId').exists().trim(), body('autoCapitalization').exists().trim().notEmpty(), diff --git a/backend/src/routes/v3/auth.ts b/backend/src/routes/v3/auth.ts new file mode 100644 index 000000000..6539b5c0f --- /dev/null +++ b/backend/src/routes/v3/auth.ts @@ -0,0 +1,29 @@ +import express from 'express'; +import { body } from 'express-validator'; +import { validateRequest } from '../../middleware'; +import { authController } from '../../controllers/v3'; +import { authLimiter } from '../../helpers/rateLimiter'; + +const router = express.Router(); + +router.post( + '/login1', + authLimiter, + body('email').isString().trim(), + body('providerAuthToken').isString().trim().optional({nullable: true}), + body('clientPublicKey').isString().trim().notEmpty(), + validateRequest, + authController.login1 +); + +router.post( + '/login2', + authLimiter, + body('email').isString().trim(), + body('providerAuthToken').isString().trim().optional({nullable: true}), + body('clientProof').isString().trim().notEmpty(), + validateRequest, + authController.login2 +); + +export default router; diff --git a/backend/src/routes/v3/index.ts b/backend/src/routes/v3/index.ts new file mode 100644 index 000000000..2560a8f82 --- /dev/null +++ b/backend/src/routes/v3/index.ts @@ -0,0 +1,11 @@ +import auth from './auth'; +import secrets from './secrets'; +import workspaces from './workspaces'; +import signup from './signup'; + +export { + auth, + secrets, + signup, + workspaces, +} diff --git a/backend/src/routes/v3/secrets.ts b/backend/src/routes/v3/secrets.ts new file mode 100644 index 000000000..56573dd9f --- /dev/null +++ b/backend/src/routes/v3/secrets.ts @@ -0,0 +1,301 @@ +import express from "express"; +const router = express.Router(); +import { + requireAuth, + requireWorkspaceAuth, + validateRequest, +} from "../../middleware"; +import { body, param, query } from "express-validator"; +import { secretsController } from "../../controllers/v3"; +import { + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ADMIN, + MEMBER, + PERMISSION_WRITE_SECRETS, + SECRET_SHARED, + SECRET_PERSONAL, + PERMISSION_READ_SECRETS, +} from "../../variables"; + +router.get( + "/raw", + query("workspaceId").exists().isString().trim(), + query("environment").exists().isString().trim(), + query("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }), + secretsController.getSecretsRaw +); + +router.get( + "/raw/:secretName", + param("secretName").exists().isString().trim(), + query("workspaceId").exists().isString().trim(), + query("environment").exists().isString().trim(), + query("secretPath").default("/").isString().trim(), + query("type").optional().isIn([SECRET_SHARED, SECRET_PERSONAL]), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }), + secretsController.getSecretByNameRaw +); + +router.post( + "/raw/:secretName", + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + body("secretValue").exists().isString().trim(), + body("secretComment").default("").isString().trim(), + body("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }), + secretsController.createSecretRaw +); + +router.patch( + "/raw/:secretName", + param("secretName").exists().isString().trim(), + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + body("secretValue").exists().isString().trim(), + body("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }), + secretsController.updateSecretByNameRaw +); + +router.delete( + "/raw/:secretName", + param("secretName").exists().isString().trim(), + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("secretPath").default("/").isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: true + }), + secretsController.deleteSecretByNameRaw +); + +router.get( + "/", + query("workspaceId").exists().isString().trim(), + query("environment").exists().isString().trim(), + query("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: false + }), + secretsController.getSecrets +); + +router.post( + "/:secretName", + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + body("secretKeyCiphertext").exists().isString().trim(), + body("secretKeyIV").exists().isString().trim(), + body("secretKeyTag").exists().isString().trim(), + body("secretValueCiphertext").exists().isString().trim(), + body("secretValueIV").exists().isString().trim(), + body("secretValueTag").exists().isString().trim(), + body("secretCommentCiphertext").optional().isString().trim(), + body("secretCommentIV").optional().isString().trim(), + body("secretCommentTag").optional().isString().trim(), + body("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: false + }), + secretsController.createSecret +); + +router.get( + "/:secretName", + param("secretName").exists().isString().trim(), + query("workspaceId").exists().isString().trim(), + query("environment").exists().isString().trim(), + query("secretPath").default("/").isString().trim(), + query("type").optional().isIn([SECRET_SHARED, SECRET_PERSONAL]), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "query", + locationEnvironment: "query", + requiredPermissions: [PERMISSION_READ_SECRETS], + requireBlindIndicesEnabled: true, + }), + secretsController.getSecretByName +); + +router.patch( + "/:secretName", + param("secretName").exists().isString().trim(), + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + body("secretValueCiphertext").exists().isString().trim(), + body("secretValueIV").exists().isString().trim(), + body("secretValueTag").exists().isString().trim(), + body("secretPath").default("/").isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: false + }), + secretsController.updateSecretByName +); + +router.delete( + "/:secretName", + param("secretName").exists().isString().trim(), + body("workspaceId").exists().isString().trim(), + body("environment").exists().isString().trim(), + body("secretPath").default("/").isString().trim(), + body("type").exists().isIn([SECRET_SHARED, SECRET_PERSONAL]), + validateRequest, + requireAuth({ + acceptedAuthModes: [ + AUTH_MODE_JWT, + AUTH_MODE_API_KEY, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_SERVICE_ACCOUNT, + ], + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN, MEMBER], + locationWorkspaceId: "body", + locationEnvironment: "body", + requiredPermissions: [PERMISSION_WRITE_SECRETS], + requireBlindIndicesEnabled: true, + requireE2EEOff: false + }), + secretsController.deleteSecretByName +); + +export default router; diff --git a/backend/src/routes/v3/signup.ts b/backend/src/routes/v3/signup.ts new file mode 100644 index 000000000..b2fb4af81 --- /dev/null +++ b/backend/src/routes/v3/signup.ts @@ -0,0 +1,29 @@ +import express from 'express'; +const router = express.Router(); +import { body } from 'express-validator'; +import { signupController } from '../../controllers/v3'; +import { authLimiter } from '../../helpers/rateLimiter'; +import { validateRequest } from '../../middleware'; + +router.post( + '/complete-account/signup', + authLimiter, + body('email').exists().isString().trim().notEmpty().isEmail(), + body('firstName').exists().isString().trim().notEmpty(), + body('lastName').exists().isString().trim().optional({nullable: true}), + body('protectedKey').exists().isString().trim().notEmpty(), + body('protectedKeyIV').exists().isString().trim().notEmpty(), + body('protectedKeyTag').exists().isString().trim().notEmpty(), + body('publicKey').exists().isString().trim().notEmpty(), + body('encryptedPrivateKey').exists().isString().trim().notEmpty(), + body('encryptedPrivateKeyIV').exists().isString().trim().notEmpty(), + body('encryptedPrivateKeyTag').exists().isString().trim().notEmpty(), + 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}), + validateRequest, + signupController.completeAccountSignup, +); + +export default router; diff --git a/backend/src/routes/v3/workspaces.ts b/backend/src/routes/v3/workspaces.ts new file mode 100644 index 000000000..5c4df39d8 --- /dev/null +++ b/backend/src/routes/v3/workspaces.ts @@ -0,0 +1,79 @@ +import express from 'express'; +const router = express.Router(); +import { + requireAuth, + requireWorkspaceAuth, + validateRequest +} from '../../middleware'; +import { workspacesController } from '../../controllers/v3'; +import { + AUTH_MODE_JWT, + ADMIN +} from '../../variables'; +import { param, body } from 'express-validator'; + +// -- migration to blind indices endpoints + +router.get( + '/:workspaceId/secrets/blind-index-status', + param('workspaceId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params', + }), + workspacesController.getWorkspaceBlindIndexStatus +); + +router.get( // allow admins to get all workspace secrets (part of blind indices migration) + '/:workspaceId/secrets', + param('workspaceId').exists().isString().trim(), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params', + }), + workspacesController.getWorkspaceSecrets +); + +router.post( // allow admins to name all workspace secrets (part of blind indices migration) + '/:workspaceId/secrets/names', + param('workspaceId').exists().isString().trim(), + body('secretsToUpdate') + .exists() + .isArray() + .withMessage('secretsToUpdate must be an array') + .customSanitizer((value) => { + return value.map((secret: any) => ({ + secretName: secret.secretName, + _id: secret._id + })); + }), + body('secretsToUpdate.*.secretName') + .exists() + .isString() + .withMessage('secretName must be a string'), + body('secretsToUpdate.*._id') + .exists() + .isString() + .withMessage('secretId must be a string'), + validateRequest, + requireAuth({ + acceptedAuthModes: [AUTH_MODE_JWT] + }), + requireWorkspaceAuth({ + acceptedRoles: [ADMIN], + locationWorkspaceId: 'params' + }), + workspacesController.nameWorkspaceSecrets +); + +// -- + +export default router; \ No newline at end of file diff --git a/backend/src/services/BotService.ts b/backend/src/services/BotService.ts index 792bd8e35..7081a64cb 100644 --- a/backend/src/services/BotService.ts +++ b/backend/src/services/BotService.ts @@ -1,7 +1,10 @@ +import { Types } from 'mongoose'; import { - getSecretsHelper, + getSecretsBotHelper, encryptSymmetricHelper, - decryptSymmetricHelper + decryptSymmetricHelper, + getKey, + getIsWorkspaceE2EEHelper } from '../helpers/bot'; /** @@ -9,6 +12,31 @@ import { */ class BotService { + /** + * Return whether or not workspace with id [workspaceId] is end-to-end encrypted + * @param workspaceId - id of workspace + * @returns {Boolean} + */ + static async getIsWorkspaceE2EE(workspaceId: Types.ObjectId) { + return await getIsWorkspaceE2EEHelper(workspaceId); + } + + /** + * Get workspace key for workspace with id [workspaceId] shared to bot. + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId - id of workspace to get workspace key for + * @returns + */ + static async getWorkspaceKeyWithBot({ + workspaceId + }: { + workspaceId: Types.ObjectId; + }) { + return await getKey({ + workspaceId + }); + } + /** * Return decrypted secrets for workspace with id [workspaceId] and * environment [environmen] shared to bot. @@ -21,10 +49,10 @@ class BotService { workspaceId, environment }: { - workspaceId: string; + workspaceId: Types.ObjectId; environment: string; }) { - return await getSecretsHelper({ + return await getSecretsBotHelper({ workspaceId, environment }); @@ -41,7 +69,7 @@ class BotService { workspaceId, plaintext }: { - workspaceId: string; + workspaceId: Types.ObjectId; plaintext: string; }) { return await encryptSymmetricHelper({ @@ -65,7 +93,7 @@ class BotService { iv, tag }: { - workspaceId: string; + workspaceId: Types.ObjectId; ciphertext: string; iv: string; tag: string; diff --git a/backend/src/services/DatabaseService.ts b/backend/src/services/DatabaseService.ts index fdfd7660a..616f56c47 100644 --- a/backend/src/services/DatabaseService.ts +++ b/backend/src/services/DatabaseService.ts @@ -1,5 +1,3 @@ -import mongoose from 'mongoose'; -import { getLogger } from '../utils/logger'; import { initDatabaseHelper, closeDatabaseHelper diff --git a/backend/src/services/EventService.ts b/backend/src/services/EventService.ts index 9f982bf75..160086be8 100644 --- a/backend/src/services/EventService.ts +++ b/backend/src/services/EventService.ts @@ -1,8 +1,10 @@ +import { Types } from 'mongoose'; import { handleEventHelper } from '../helpers/event'; interface Event { name: string; - workspaceId: string; + workspaceId: Types.ObjectId; + environment?: string; payload: any; } diff --git a/backend/src/services/FolderService.ts b/backend/src/services/FolderService.ts new file mode 100644 index 000000000..f2dfb3050 --- /dev/null +++ b/backend/src/services/FolderService.ts @@ -0,0 +1,217 @@ +import { nanoid } from "nanoid"; +import { Types } from "mongoose"; +import Folder, { TFolderSchema } from "../models/folder"; + +type TAppendFolderDTO = { + folderName: string; + parentFolderId?: string; +}; + +type TRenameFolderDTO = { + folderName: string; + folderId: string; +}; + +export const validateFolderName = (folderName: string) => { + const validNameRegex = /^[a-zA-Z0-9-_]+$/; + return validNameRegex.test(folderName); +}; + +export const generateFolderId = (): string => nanoid(12); + +// simple bfs search +export const searchByFolderId = ( + root: TFolderSchema, + folderId: string +): TFolderSchema | undefined => { + const queue = [root]; + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + if (folder.id === folderId) { + return folder; + } + queue.push(...folder.children); + } +}; + +export const folderBfsTraversal = async ( + root: TFolderSchema, + callback: (data: TFolderSchema) => void | Promise +) => { + const queue = [root]; + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + await callback(folder); + queue.push(...folder.children); + } +}; + +// bfs and then append to the folder +const appendChild = (folders: TFolderSchema, folderName: string) => { + const folder = folders.children.find(({ name }) => name === folderName); + if (folder) { + throw new Error("Folder already exists"); + } + const id = generateFolderId(); + folders.version += 1; + folders.children.push({ + id, + name: folderName, + children: [], + version: 1, + }); + return { id, name: folderName }; +}; + +// root of append child wrapper +export const appendFolder = ( + folders: TFolderSchema, + { folderName, parentFolderId }: TAppendFolderDTO +) => { + const isRoot = !parentFolderId; + + if (isRoot) { + return appendChild(folders, folderName); + } + const folder = searchByFolderId(folders, parentFolderId); + if (!folder) { + throw new Error("Parent Folder not found"); + } + return appendChild(folder, folderName); +}; + +export const renameFolder = ( + folders: TFolderSchema, + { folderName, folderId }: TRenameFolderDTO +) => { + const folder = searchByFolderId(folders, folderId); + if (!folder) { + throw new Error("Folder doesn't exist"); + } + + folder.name = folderName; +}; + +// bfs but stops on parent folder +// Then unmount the required child and then return both +export const deleteFolderById = (folders: TFolderSchema, folderId: string) => { + const queue = [folders]; + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + const index = folder.children.findIndex(({ id }) => folderId === id); + if (index !== -1) { + const deletedFolder = folder.children.splice(index, 1); + return { deletedNode: deletedFolder[0], parent: folder }; + } + queue.push(...folder.children); + } +}; + +// bfs but return parent of the folderID +export const getParentFromFolderId = ( + folders: TFolderSchema, + folderId: string +) => { + const queue = [folders]; + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + const index = folder.children.findIndex(({ id }) => folderId === id); + if (index !== -1) return folder; + + queue.push(...folder.children); + } +}; + +// to get all folders ids from everything from below nodes +export const getAllFolderIds = (folders: TFolderSchema) => { + const folderIds: Array<{ id: string; name: string }> = []; + const queue = [folders]; + while (queue.length) { + const folder = queue.pop() as TFolderSchema; + folderIds.push({ id: folder.id, name: folder.name }); + queue.push(...folder.children); + } + return folderIds; +}; + +// To get the path of a folder from the root. Used for breadcrumbs +// LOGIC: We do dfs instead if bfs +// Each time we go down we record the current node +// We then record the number of childs of each root node +// When we reach leaf node or when all childs of a root node are visited +// We remove it from path recorded by using the total child record +export const searchByFolderIdWithDir = ( + folders: TFolderSchema, + folderId: string +) => { + const stack = [folders]; + const dir: Array<{ id: string; name: string }> = []; + const hits: Record = {}; + + while (stack.length) { + const folder = stack.shift() as TFolderSchema; + // score the hit + hits[folder.id] = folder.children.length; + const parent = dir[dir.length - 1]; + if (parent) hits[parent.id] -= 1; + + if (folder.id === folderId) { + dir.push({ name: folder.name, id: folder.id }); + return { folder, dir }; + } + + if (folder.children.length) { + dir.push({ name: folder.name, id: folder.id }); + stack.unshift(...folder.children); + } else { + if (!hits[parent.id]) { + dir.pop(); + } + } + } + return; +}; + +// to get folder of a path given +// Like /frontend/folder#1 +export const getFolderByPath = (folders: TFolderSchema, searchPath: string) => { + // corner case when its just / return root + if (searchPath === "/") { + return folders.id === "root" ? folders : undefined; + } + + const path = searchPath.split("/").filter(Boolean); + const queue = [folders]; + let segment: TFolderSchema | undefined; + while (queue.length && path.length) { + const folder = queue.pop(); + const segmentPath = path.shift(); + segment = folder?.children.find(({ name }) => name === segmentPath); + if (!segment) return; + + queue.push(segment); + } + return segment; +}; + +export const getFolderIdFromServiceToken = async ( + workspaceId: Types.ObjectId | string, + environment: string, + secretPath: string +) => { + const folders = await Folder.findOne({ + workspace: workspaceId, + environment, + }); + + if (!folders) { + if (secretPath !== "/") throw new Error("Invalid path. Folders not found"); + } else { + const folder = getFolderByPath(folders.nodes, secretPath); + if (!folder) { + throw new Error("Folder not found"); + } + return folder.id; + } + return "root"; +}; diff --git a/backend/src/services/IntegrationService.ts b/backend/src/services/IntegrationService.ts index 7b3a20a6b..1e7409ad0 100644 --- a/backend/src/services/IntegrationService.ts +++ b/backend/src/services/IntegrationService.ts @@ -1,3 +1,4 @@ +import { Types } from 'mongoose'; import { handleOAuthExchangeHelper, syncIntegrationsHelper, @@ -51,9 +52,11 @@ class IntegrationService { * @param {Object} obj.workspaceId - id of workspace */ static async syncIntegrations({ - workspaceId + workspaceId, + environment }: { - workspaceId: string; + workspaceId: Types.ObjectId; + environment?: string; }) { return await syncIntegrationsHelper({ workspaceId @@ -67,7 +70,7 @@ class IntegrationService { * @param {String} obj.integrationAuthId - id of integration auth * @param {String} refreshToken - decrypted refresh token */ - static async getIntegrationAuthRefresh({ integrationAuthId }: { integrationAuthId: string}) { + static async getIntegrationAuthRefresh({ integrationAuthId }: { integrationAuthId: Types.ObjectId}) { return await getIntegrationAuthRefreshHelper({ integrationAuthId }); @@ -80,7 +83,7 @@ class IntegrationService { * @param {String} obj.integrationAuthId - id of integration auth * @param {String} accessToken - decrypted access token */ - static async getIntegrationAuthAccess({ integrationAuthId }: { integrationAuthId: string}) { + static async getIntegrationAuthAccess({ integrationAuthId }: { integrationAuthId: Types.ObjectId }) { return await getIntegrationAuthAccessHelper({ integrationAuthId }); diff --git a/backend/src/services/PostHogClient.ts b/backend/src/services/PostHogClient.ts deleted file mode 100644 index 15ccf0919..000000000 --- a/backend/src/services/PostHogClient.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { PostHog } from 'posthog-node'; -import { getLogger } from '../utils/logger'; -import { - getNodeEnv, - getTelemetryEnabled, - getPostHogProjectApiKey, - getPostHogHost -} from '../config'; - -/** - * Logs telemetry enable/disable notice. - */ -const logTelemetryMessage = () => { - if(!getTelemetryEnabled()){ - getLogger("backend-main").info([ - "", - "To improve, Infisical collects telemetry data about general usage.", - "This helps us understand how the product is doing and guide our product development to create the best possible platform; it also helps us demonstrate growth as we support Infisical as open-source software.", - "To opt into telemetry, you can set `TELEMETRY_ENABLED=true` within the environment variables.", - ].join('\n')) - } -} - -/** - * Return an instance of the PostHog client initialized. - * @returns - */ -const getPostHogClient = () => { - let postHogClient: any; - if (getNodeEnv() === 'production' && getTelemetryEnabled()) { - // case: enable opt-out telemetry in production - postHogClient = new PostHog(getPostHogProjectApiKey(), { - host: getPostHogHost() - }); - } - - return postHogClient; -} - -export { - logTelemetryMessage, - getPostHogClient -} - diff --git a/backend/src/services/SecretService.ts b/backend/src/services/SecretService.ts new file mode 100644 index 000000000..afd706dbd --- /dev/null +++ b/backend/src/services/SecretService.ts @@ -0,0 +1,168 @@ +import { Types } from "mongoose"; +import { + CreateSecretParams, + GetSecretsParams, + GetSecretParams, + UpdateSecretParams, + DeleteSecretParams +} from '../interfaces/services/SecretService'; +import { + createSecretBlindIndexDataHelper, + getSecretBlindIndexSaltHelper, + generateSecretBlindIndexWithSaltHelper, + generateSecretBlindIndexHelper, + createSecretHelper, + getSecretsHelper, + getSecretHelper, + updateSecretHelper, + deleteSecretHelper +} from '../helpers/secrets'; + +class SecretService { + /** + * Create secret blind index data containing encrypted blind index salt + * for workspace with id [workspaceId] + * @param {Object} obj + * @param {Buffer} obj.salt - 16-byte random salt + * @param {Types.ObjectId} obj.workspaceId + */ + static async createSecretBlindIndexData({ + workspaceId, + }: { + workspaceId: Types.ObjectId; + }) { + return await createSecretBlindIndexDataHelper({ + workspaceId, + }); + } + + /** + * Get secret blind index salt for workspace with id [workspaceId] + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId - id of workspace to get salt for + * @returns + */ + static async getSecretBlindIndexSalt({ + workspaceId, + }: { + workspaceId: Types.ObjectId; + }) { + return await getSecretBlindIndexSaltHelper({ + workspaceId, + }); + } + + /** + * Generate blind index for secret with name [secretName] + * and salt [salt] + * @param {Object} obj + * @param {Object} obj.secretName - name of secret to generate blind index for + * @param {String} obj.salt - base64-salt + */ + static async generateSecretBlindIndexWithSalt({ + secretName, + salt, + }: { + secretName: string; + salt: string; + }) { + return await generateSecretBlindIndexWithSaltHelper({ + secretName, + salt, + }); + } + + /** + * Create and return blind index for secret with + * name [secretName] part of workspace with id [workspaceId] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to generate blind index for + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + */ + static async generateSecretBlindIndex({ + secretName, + workspaceId, + }: { + secretName: string; + workspaceId: Types.ObjectId; + }) { + return await generateSecretBlindIndexHelper({ + secretName, + workspaceId, + }); + } + + /** + * Create secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to create + * @param {Types.ObjectId} obj.workspaceId - id of workspace to create secret for + * @param {String} obj.environment - environment in workspace to create secret for + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + static async createSecret(createSecretParams: CreateSecretParams) { + return await createSecretHelper(createSecretParams); + } + + /** + * Get secrets for workspace with id [workspaceId] and environment [environment] + * @param {Object} obj + * @param {Types.ObjectId} obj.workspaceId - id of workspace + * @param {String} obj.environment - environment in workspace + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + static async getSecrets(getSecretsParams: GetSecretsParams) { + return await getSecretsHelper(getSecretsParams); + } + + /** + * Get secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to get + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + static async getSecret(getSecretParams: GetSecretParams) { + // TODO(akhilmhdh) The one above is diff. Change this to some other name + return await getSecretHelper(getSecretParams); + } + + /** + * Update secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to update + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {String} obj.secretValueCiphertext - ciphertext of secret value + * @param {String} obj.secretValueIV - IV of secret value + * @param {String} obj.secretValueTag - tag of secret value + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + static async updateSecret(updateSecretParams: UpdateSecretParams) { + return await updateSecretHelper(updateSecretParams); + } + + /** + * Delete secret with name [secretName] + * @param {Object} obj + * @param {String} obj.secretName - name of secret to delete + * @param {Types.ObjectId} obj.workspaceId - id of workspace that secret belongs to + * @param {String} obj.environment - environment in workspace that secret belongs to + * @param {'shared' | 'personal'} obj.type - type of secret + * @param {AuthData} obj.authData - authentication data on request + * @returns + */ + static async deleteSecret(deleteSecretParams: DeleteSecretParams) { + return await deleteSecretHelper(deleteSecretParams); + } +} + +export default SecretService; diff --git a/backend/src/services/TelemetryService.ts b/backend/src/services/TelemetryService.ts new file mode 100644 index 000000000..da90732eb --- /dev/null +++ b/backend/src/services/TelemetryService.ts @@ -0,0 +1,83 @@ +import { PostHog } from 'posthog-node'; +import { getLogger } from '../utils/logger'; +import { AuthData } from '../interfaces/middleware'; +import { + getNodeEnv, + getTelemetryEnabled, + getPostHogProjectApiKey, + getPostHogHost +} from '../config'; +import { + IUser, + User, + IServiceAccount, + ServiceAccount, + IServiceTokenData, + ServiceTokenData +} from '../models'; +import { + AccountNotFoundError, + BadRequestError +} from '../utils/errors'; + +class Telemetry { + /** + * Logs telemetry enable/disable notice. + */ + static logTelemetryMessage = async () => { + if(!(await getTelemetryEnabled())){ + (await getLogger("backend-main")).info([ + "", + "To improve, Infisical collects telemetry data about general usage.", + "This helps us understand how the product is doing and guide our product development to create the best possible platform; it also helps us demonstrate growth as we support Infisical as open-source software.", + "To opt into telemetry, you can set `TELEMETRY_ENABLED=true` within the environment variables.", + ].join('\n')) + } + } + + /** + * Return an instance of the PostHog client initialized. + * @returns + */ + static getPostHogClient = async () => { + let postHogClient: any; + if ((await getNodeEnv()) === 'production' && (await getTelemetryEnabled())) { + // case: enable opt-out telemetry in production + postHogClient = new PostHog(await getPostHogProjectApiKey(), { + host: await getPostHogHost() + }); + } + + return postHogClient; + } + + static getDistinctId = async ({ + authData + }: { + authData: AuthData; + }) => { + let distinctId = ''; + if (authData.authPayload instanceof User) { + distinctId = authData.authPayload.email; + } else if (authData.authPayload instanceof ServiceAccount) { + distinctId = `sa.${authData.authPayload._id.toString()}`; + } else if (authData.authPayload instanceof ServiceTokenData) { + + if (authData.authPayload.user) { + const user = await User.findById(authData.authPayload.user, 'email'); + if (!user) throw AccountNotFoundError(); + distinctId = user.email; + } else if (authData.authPayload.serviceAccount) { + distinctId = distinctId = `sa.${authData.authPayload.serviceAccount.toString()}`; + } + } + + if (distinctId === '') throw BadRequestError({ + message: 'Failed to obtain distinct id for logging telemetry' + }); + + return distinctId; + } +} + +export default Telemetry; \ No newline at end of file diff --git a/backend/src/services/health.ts b/backend/src/services/health.ts index 9c441ba9d..daf3bf962 100644 --- a/backend/src/services/health.ts +++ b/backend/src/services/health.ts @@ -3,8 +3,8 @@ import { createTerminus } from '@godaddy/terminus'; import { getLogger } from '../utils/logger'; export const setUpHealthEndpoint = (server: T) => { - const onSignal = () => { - getLogger('backend-main').info('Server is starting clean-up'); + const onSignal = async () => { + (await getLogger('backend-main')).info('Server is starting clean-up'); return Promise.all([ new Promise((resolve) => { if (mongoose.connection && mongoose.connection.readyState == 1) { diff --git a/backend/src/services/index.ts b/backend/src/services/index.ts index d98b70718..db0bd39a3 100644 --- a/backend/src/services/index.ts +++ b/backend/src/services/index.ts @@ -1,16 +1,18 @@ import DatabaseService from './DatabaseService'; -import { logTelemetryMessage, getPostHogClient } from './PostHogClient'; +// import { logTelemetryMessage, getPostHogClient } from './TelemetryService'; +import TelemetryService from './TelemetryService'; import BotService from './BotService'; import EventService from './EventService'; import IntegrationService from './IntegrationService'; import TokenService from './TokenService'; +import SecretService from './SecretService'; export { - logTelemetryMessage, - getPostHogClient, + TelemetryService, DatabaseService, BotService, EventService, IntegrationService, - TokenService + TokenService, + SecretService } \ No newline at end of file diff --git a/backend/src/services/smtp.ts b/backend/src/services/smtp.ts index 7a4ebf00b..0231e7f54 100644 --- a/backend/src/services/smtp.ts +++ b/backend/src/services/smtp.ts @@ -1,9 +1,10 @@ import nodemailer from 'nodemailer'; import { - SMTP_HOST_SENDGRID, + SMTP_HOST_SENDGRID, SMTP_HOST_MAILGUN, SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL + SMTP_HOST_ZOHOMAIL, + SMTP_HOST_GMAIL } from '../variables'; import SMTPConnection from 'nodemailer/lib/smtp-connection'; import * as Sentry from '@sentry/node'; @@ -15,44 +16,50 @@ import { getSmtpPort } from '../config'; -export const initSmtp = () => { +export const initSmtp = async () => { const mailOpts: SMTPConnection.Options = { - host: getSmtpHost(), - port: getSmtpPort() + host: await getSmtpHost(), + port: await getSmtpPort() }; - if (getSmtpUsername() && getSmtpPassword()) { + if ((await getSmtpUsername()) && (await getSmtpPassword())) { mailOpts.auth = { - user: getSmtpUsername(), - pass: getSmtpPassword() + user: await getSmtpUsername(), + pass: await getSmtpPassword() }; } - if (getSmtpSecure() ? getSmtpSecure() : false) { - switch (getSmtpHost()) { + if ((await getSmtpSecure()) ? (await getSmtpSecure()) : false) { + switch (await getSmtpHost()) { case SMTP_HOST_SENDGRID: mailOpts.requireTLS = true; break; case SMTP_HOST_MAILGUN: - mailOpts.requireTLS = true; + mailOpts.requireTLS = true; mailOpts.tls = { ciphers: 'TLSv1.2' } break; case SMTP_HOST_SOCKETLABS: - mailOpts.requireTLS = true; + mailOpts.requireTLS = true; mailOpts.tls = { ciphers: 'TLSv1.2' } break; case SMTP_HOST_ZOHOMAIL: - mailOpts.requireTLS = true; + mailOpts.requireTLS = true; mailOpts.tls = { ciphers: 'TLSv1.2' } - break; + break; + case SMTP_HOST_GMAIL: + mailOpts.requireTLS = true; + mailOpts.tls = { + ciphers: 'TLSv1.2' + } + break; default: - if (getSmtpHost().includes('amazonaws.com')) { + if ((await getSmtpHost()).includes('amazonaws.com')) { mailOpts.tls = { ciphers: 'TLSv1.2' } @@ -66,14 +73,15 @@ export const initSmtp = () => { const transporter = nodemailer.createTransport(mailOpts); transporter .verify() - .then(() => { + .then((err) => { Sentry.setUser(null); Sentry.captureMessage('SMTP - Successfully connected'); + console.log("SMTP - Successfully connected") }) - .catch((err) => { + .catch(async (err) => { Sentry.setUser(null); Sentry.captureException( - `SMTP - Failed to connect to ${getSmtpHost()}:${getSmtpPort()} \n\t${err}` + `SMTP - Failed to connect to ${await getSmtpHost()}:${await getSmtpPort()} \n\t${err}` ); }); diff --git a/backend/src/templates/organizationInvitation.handlebars b/backend/src/templates/organizationInvitation.handlebars index 045a9602b..b281786f4 100644 --- a/backend/src/templates/organizationInvitation.handlebars +++ b/backend/src/templates/organizationInvitation.handlebars @@ -9,7 +9,7 @@

Join your organization on Infisical

{{inviterFirstName}} ({{inviterEmail}}) has invited you to their Infisical organization — {{organizationName}}

- Join now + Join now

What is Infisical?

Infisical is an easy-to-use end-to-end encrypted tool that enables developers to sync and manage their secrets and configs.

diff --git a/backend/src/types/express/index.d.ts b/backend/src/types/express/index.d.ts index acee877bd..b5ca0ab28 100644 --- a/backend/src/types/express/index.d.ts +++ b/backend/src/types/express/index.d.ts @@ -1,5 +1,20 @@ import * as express from 'express'; -import { ISecret } from '../../models'; +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + ISecret +} from '../../models'; +import { + AuthData +} from '../../interfaces/middleware'; + +declare module 'express' { + interface Request { + user?: any; + } +} // TODO: fix (any) types declare global { @@ -10,6 +25,7 @@ declare global { workspace: any; membership: any; targetMembership: any; + providerAuthToken: any; organization: any; membershipOrg: any; integration: any; @@ -19,10 +35,17 @@ declare global { secrets: any; secretSnapshot: any; serviceToken: any; + serviceAccount: any; accessToken: any; serviceTokenData: any; apiKeyData: any; query?: any; + tokenVersionId?: Types.ObjectId; + authData: AuthData; + realIP: string; + requestData: { + [key: string]: string + }; } } } diff --git a/backend/src/types/secret/index.d.ts b/backend/src/types/secret/index.d.ts index 257038f60..deab73e95 100644 --- a/backend/src/types/secret/index.d.ts +++ b/backend/src/types/secret/index.d.ts @@ -1,52 +1,47 @@ -import { Types } from 'mongoose'; -import { Assign, Omit } from 'utility-types'; -import { ISecret } from '../../models'; -import { mongo } from 'mongoose'; +import { Types } from "mongoose"; +import { Assign, Omit } from "utility-types"; +import { ISecret } from "../../models"; +import { mongo } from "mongoose"; // Everything is required, except the omitted types -export type CreateSecretRequestBody = Omit; +export type CreateSecretRequestBody = Omit< + ISecret, + "user" | "version" | "environment" | "workspace" +>; -// Omit the listed properties, then make everything optional and then make _id required -export type ModifySecretRequestBody = Assign>, { _id: string }>; +// Omit the listed properties, then make everything optional and then make _id required +export type ModifySecretRequestBody = Assign< + Partial>, + { _id: string } +>; // Used for modeling sanitized secrets before uplaod. To be used for converting user input for uploading -export type SanitizedSecretModify = Partial>; +export type SanitizedSecretModify = Partial< + Omit +>; // Everything is required, except the omitted types export type SanitizedSecretForCreate = Omit; export interface BatchSecretRequest { - id: string; - method: 'POST' | 'PATCH' | 'DELETE'; - secret: Secret; + id: string; + method: "POST" | "PATCH" | "DELETE"; + secret: Secret; } export interface BatchSecret { - _id: string; - type: 'shared' | 'personal', - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; + _id: string; + type: "shared" | "personal"; + secretBlindIndex: string; + secretKeyCiphertext: string; + secretKeyIV: string; + secretKeyTag: string; + secretValueCiphertext: string; + secretValueIV: string; + secretValueTag: string; + secretCommentCiphertext: string; + secretCommentIV: string; + secretCommentTag: string; + tags: string[]; + folder: string } - -export interface BatchSecret { - _id: string; - type: 'shared' | 'personal', - secretKeyCiphertext: string; - secretKeyIV: string; - secretKeyTag: string; - secretValueCiphertext: string; - secretValueIV: string; - secretValueTag: string; - secretCommentCiphertext: string; - secretCommentIV: string; - secretCommentTag: string; - tags: string[]; -} \ No newline at end of file diff --git a/backend/src/utils/addDevelopmentUser.ts b/backend/src/utils/addDevelopmentUser.ts index 585740a6b..2c7866229 100644 --- a/backend/src/utils/addDevelopmentUser.ts +++ b/backend/src/utils/addDevelopmentUser.ts @@ -5,20 +5,22 @@ ************************************************************************************************/ import { Key, Membership, MembershipOrg, Organization, User, Workspace } from "../models"; +import { SecretService } from "../services"; import { Types } from 'mongoose'; import { getNodeEnv } from '../config'; -export const createTestUserForDevelopment = async () => { - if (getNodeEnv() === "development") { - const testUserEmail = "test@localhost.local" - const testUserPassword = "testInfisical1" - const testUserId = "63cefa6ec8d3175601cfa980" - const testWorkspaceId = "63cefb15c8d3175601cfa989" - const testOrgId = "63cefb15c8d3175601cfa985" - const testMembershipId = "63cefb159185d9aa3ef0cf35" - const testMembershipOrgId = "63cefb159185d9aa3ef0cf31" - const testWorkspaceKeyId = "63cf48f0225e6955acec5eff" +export const testUserEmail = "test@localhost.local" +export const testUserPassword = "testInfisical1" +export const testUserId = "63cefa6ec8d3175601cfa980" +export const testWorkspaceId = "63cefb15c8d3175601cfa989" +export const testOrgId = "63cefb15c8d3175601cfa985" +export const testMembershipId = "63cefb159185d9aa3ef0cf35" +export const testMembershipOrgId = "63cefb159185d9aa3ef0cf31" +export const testWorkspaceKeyId = "63cf48f0225e6955acec5eff" +export const plainTextWorkspaceKey = "543fef8224813a46230b0a50a46c5fb2" +export const createTestUserForDevelopment = async () => { + if ((await getNodeEnv()) === "development" || (await getNodeEnv()) === "test") { const testUser = { _id: testUserId, email: testUserEmail, @@ -118,7 +120,12 @@ export const createTestUserForDevelopment = async () => { // create workspace if not exist const workspaceInDB = await Workspace.findById(testWorkspaceId) if (!workspaceInDB) { - await Workspace.create(testWorkspace) + const workspace = await Workspace.create(testWorkspace) + + // initialize blind index salt for workspace + await SecretService.createSecretBlindIndexData({ + workspaceId: workspace._id + }); } // create workspace key if not exist diff --git a/backend/src/utils/auth.ts b/backend/src/utils/auth.ts new file mode 100644 index 000000000..5144af16d --- /dev/null +++ b/backend/src/utils/auth.ts @@ -0,0 +1,118 @@ +import express from 'express'; +import passport from 'passport'; +import { AuthData } from '../interfaces/middleware'; +import { + AuthProvider, + User, + ServiceAccount, + ServiceTokenData, +} from '../models'; +import { createToken } from '../helpers/auth'; +import { + getClientIdGoogle, + getClientSecretGoogle, + getJwtProviderAuthLifetime, + getJwtProviderAuthSecret +} 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 + +/** + * Returns an object containing the id of the authentication data payload + * @param {AuthData} authData - authentication data object + * @returns + */ +const getAuthDataPayloadIdObj = (authData: AuthData) => { + if (authData.authPayload instanceof User) { + return { userId: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceAccount) { + return { serviceAccountId: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceTokenData) { + return { serviceTokenDataId: authData.authPayload._id }; + } +}; + + +/** + * Returns an object containing the user associated with the authentication data payload + * @param {AuthData} authData - authentication data object + * @returns + */ +const getAuthDataPayloadUserObj = (authData: AuthData) => { + + if (authData.authPayload instanceof User) { + return { user: authData.authPayload._id }; + } + + if (authData.authPayload instanceof ServiceAccount) { + return { user: authData.authPayload.user }; + } + + if (authData.authPayload instanceof ServiceTokenData) { + return { user: authData.authPayload.user }; + } +} + +const initializePassport = async () => { + const googleClientSecret = await getClientSecretGoogle(); + const googleClientId = await getClientIdGoogle(); + + passport.use(new GoogleStrategy({ + passReqToCallback: true, + clientID: googleClientId, + clientSecret: googleClientSecret, + callbackURL: '/api/v1/auth/callback/google', + scope: ['profile', ' email'], + }, async ( + req: express.Request, + accessToken: string, + refreshToken: string, + profile: any, + cb: any + ) => { + try { + const email = profile.emails[0].value; + let user = await User.findOne({ + authProvider: AuthProvider.GOOGLE, + authId: profile.id, + }).select('+publicKey') + + if (!user) { + user = await new User({ + email, + authProvider: AuthProvider.GOOGLE, + authId: profile.id, + }).save(); + } + + const providerAuthToken = createToken({ + payload: { + userId: user._id.toString(), + email: user.email, + authProvider: user.authProvider, + isUserCompleted: !!user.publicKey + }, + expiresIn: await getJwtProviderAuthLifetime(), + secret: await getJwtProviderAuthSecret(), + }); + + req.providerAuthToken = providerAuthToken; + cb(null, profile); + } catch (err) { + cb(null, false); + } + })); +} + +export { + getAuthDataPayloadIdObj, + getAuthDataPayloadUserObj, + initializePassport, +} diff --git a/backend/src/utils/crypto.ts b/backend/src/utils/crypto.ts deleted file mode 100644 index 28f96b0cf..000000000 --- a/backend/src/utils/crypto.ts +++ /dev/null @@ -1,171 +0,0 @@ -import nacl from 'tweetnacl'; -import util from 'tweetnacl-util'; -import AesGCM from './aes-gcm'; -import * as Sentry from '@sentry/node'; - -/** - * Return new base64, NaCl, public-private key pair. - * @returns {Object} obj - * @returns {String} obj.publicKey - base64, NaCl, public key - * @returns {String} obj.privateKey - base64, NaCl, private key - */ -const generateKeyPair = () => { - const pair = nacl.box.keyPair(); - - return ({ - publicKey: util.encodeBase64(pair.publicKey), - privateKey: util.encodeBase64(pair.secretKey) - }); -} - -/** - * Return assymmetrically encrypted [plaintext] using [publicKey] where - * [publicKey] likely belongs to the recipient. - * @param {Object} obj - * @param {String} obj.plaintext - plaintext to encrypt - * @param {String} obj.publicKey - public key of the recipient - * @param {String} obj.privateKey - private key of the sender (current user) - * @returns {Object} obj - * @returns {String} ciphertext - base64-encoded ciphertext - * @returns {String} nonce - base64-encoded nonce - */ -const encryptAsymmetric = ({ - plaintext, - publicKey, - privateKey -}: { - plaintext: string; - publicKey: string; - privateKey: string; -}) => { - let nonce, ciphertext; - try { - nonce = nacl.randomBytes(24); - ciphertext = nacl.box( - util.decodeUTF8(plaintext), - nonce, - util.decodeBase64(publicKey), - util.decodeBase64(privateKey) - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform asymmetric encryption'); - } - - return { - ciphertext: util.encodeBase64(ciphertext), - nonce: util.encodeBase64(nonce) - }; -}; - -/** - * Return assymmetrically decrypted [ciphertext] using [privateKey] where - * [privateKey] likely belongs to the recipient. - * @param {Object} obj - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.nonce - nonce - * @param {String} obj.publicKey - public key of the sender - * @param {String} obj.privateKey - private key of the receiver (current user) - * @param {String} plaintext - UTF8 plaintext - */ -const decryptAsymmetric = ({ - ciphertext, - nonce, - publicKey, - privateKey -}: { - ciphertext: string; - nonce: string; - publicKey: string; - privateKey: string; -}): string => { - let plaintext: any; - try { - plaintext = nacl.box.open( - util.decodeBase64(ciphertext), - util.decodeBase64(nonce), - util.decodeBase64(publicKey), - util.decodeBase64(privateKey) - ); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform asymmetric decryption'); - } - - return util.encodeUTF8(plaintext); -}; - -/** - * Return symmetrically encrypted [plaintext] using [key]. - * @param {Object} obj - * @param {String} obj.plaintext - plaintext to encrypt - * @param {String} obj.key - hex key - */ -const encryptSymmetric = ({ - plaintext, - key -}: { - plaintext: string; - key: string; -}) => { - let ciphertext, iv, tag; - try { - const obj = AesGCM.encrypt(plaintext, key); - ciphertext = obj.ciphertext; - iv = obj.iv; - tag = obj.tag; - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform symmetric encryption'); - } - - return { - ciphertext, - iv, - tag - }; -}; - -/** - * Return symmetrically decypted [ciphertext] using [iv], [tag], - * and [key]. - * @param {Object} obj - * @param {String} obj.ciphertext - ciphertext to decrypt - * @param {String} obj.iv - iv - * @param {String} obj.tag - tag - * @param {String} obj.key - hex key - * - */ -const decryptSymmetric = ({ - ciphertext, - iv, - tag, - key -}: { - ciphertext: string; - iv: string; - tag: string; - key: string; -}): string => { - let plaintext; - try { - plaintext = AesGCM.decrypt(ciphertext, iv, tag, key); - } catch (err) { - Sentry.setUser(null); - Sentry.captureException(err); - throw new Error('Failed to perform symmetric decryption'); - } - - return plaintext; -}; - -export { - generateKeyPair, - encryptAsymmetric, - decryptAsymmetric, - encryptSymmetric, - decryptSymmetric -}; diff --git a/backend/src/utils/crypto/index.ts b/backend/src/utils/crypto/index.ts new file mode 100644 index 000000000..9c3877717 --- /dev/null +++ b/backend/src/utils/crypto/index.ts @@ -0,0 +1,166 @@ +import crypto from 'crypto'; +import nacl from 'tweetnacl'; +import util from 'tweetnacl-util'; +import { + IGenerateKeyPairOutput, + IEncryptAsymmetricInput, + IEncryptAsymmetricOutput, + IDecryptAsymmetricInput, + IEncryptSymmetricInput, + IDecryptSymmetricInput +} from '../../interfaces/utils'; +import { BadRequestError } from '../errors'; +import { + ALGORITHM_AES_256_GCM, + NONCE_BYTES_SIZE, + BLOCK_SIZE_BYTES_16 +} from '../../variables'; + +/** + * Return new base64, NaCl, public-private key pair. + * @returns {Object} obj + * @returns {String} obj.publicKey - (base64) NaCl, public key + * @returns {String} obj.privateKey - (base64), NaCl, private key + */ +const generateKeyPair = (): IGenerateKeyPairOutput => { + const pair = nacl.box.keyPair(); + + return ({ + publicKey: util.encodeBase64(pair.publicKey), + privateKey: util.encodeBase64(pair.secretKey) + }); +} + +/** + * Return assymmetrically encrypted [plaintext] using [publicKey] where + * [publicKey] likely belongs to the recipient. + * @param {Object} obj + * @param {String} obj.plaintext - plaintext to encrypt + * @param {String} obj.publicKey - (base64) Nacl public key of the recipient + * @param {String} obj.privateKey - (base64) Nacl private key of the sender (current user) + * @returns {Object} obj + * @returns {String} obj.ciphertext - (base64) ciphertext + * @returns {String} obj.nonce - (base64) nonce + */ +const encryptAsymmetric = ({ + plaintext, + publicKey, + privateKey +}: IEncryptAsymmetricInput): IEncryptAsymmetricOutput => { + const nonce = nacl.randomBytes(24); + const ciphertext = nacl.box( + util.decodeUTF8(plaintext), + nonce, + util.decodeBase64(publicKey), + util.decodeBase64(privateKey) + ); + + return { + ciphertext: util.encodeBase64(ciphertext), + nonce: util.encodeBase64(nonce) + }; +}; + +/** + * Return assymmetrically decrypted [ciphertext] using [privateKey] where + * [privateKey] likely belongs to the recipient. + * @param {Object} obj + * @param {String} obj.ciphertext - ciphertext to decrypt + * @param {String} obj.nonce - (base64) nonce + * @param {String} obj.publicKey - (base64) public key of the sender + * @param {String} obj.privateKey - (base64) private key of the receiver (current user) + * @returns {String} plaintext - (utf8) plaintext + */ +const decryptAsymmetric = ({ + ciphertext, + nonce, + publicKey, + privateKey +}: IDecryptAsymmetricInput): string => { + const plaintext: Uint8Array | null = nacl.box.open( + util.decodeBase64(ciphertext), + util.decodeBase64(nonce), + util.decodeBase64(publicKey), + util.decodeBase64(privateKey) + ); + + if (plaintext == null) throw BadRequestError({ + message: 'Invalid ciphertext or keys' + }); + + return util.encodeUTF8(plaintext); +}; + +/** + * Return symmetrically encrypted [plaintext] using [key]. + * + * NOTE: THIS FUNCTION SHOULD NOT BE USED FOR ALL FUTURE + * ENCRYPTION OPERATIONS UNLESS IT TOUCHES OLD FUNCTIONALITY + * THAT USES IT. USE encryptSymmetric() instead + * + * @param {Object} obj + * @param {String} obj.plaintext - (utf8) plaintext to encrypt + * @param {String} obj.key - (hex) 128-bit key + * @returns {Object} obj + * @returns {String} obj.ciphertext (base64) ciphertext + * @returns {String} obj.iv (base64) iv + * @returns {String} obj.tag (base64) tag + */ +const encryptSymmetric128BitHexKeyUTF8 = ({ + plaintext, + key +}: IEncryptSymmetricInput) => { + const iv = crypto.randomBytes(BLOCK_SIZE_BYTES_16); + const cipher = crypto.createCipheriv(ALGORITHM_AES_256_GCM, key, iv); + + let ciphertext = cipher.update(plaintext, 'utf8', 'base64'); + ciphertext += cipher.final('base64'); + + return { + ciphertext, + iv: iv.toString('base64'), + tag: cipher.getAuthTag().toString('base64') + }; +} +/** + * Return symmetrically decrypted [ciphertext] using [iv], [tag], + * and [key]. + * + * NOTE: THIS FUNCTION SHOULD NOT BE USED FOR ALL FUTURE + * DECRYPTION OPERATIONS UNLESS IT TOUCHES OLD FUNCTIONALITY + * THAT USES IT. USE decryptSymmetric() instead + * + * @param {Object} obj + * @param {String} obj.ciphertext - ciphertext to decrypt + * @param {String} obj.iv - (base64) 256-bit iv + * @param {String} obj.tag - (base64) tag + * @param {String} obj.key - (hex) 128-bit key + * @returns {String} cleartext - the deciphered ciphertext + */ +const decryptSymmetric128BitHexKeyUTF8 = ({ + ciphertext, + iv, + tag, + key +}: IDecryptSymmetricInput) => { + const decipher = crypto.createDecipheriv( + ALGORITHM_AES_256_GCM, + key, + Buffer.from(iv, 'base64') + ); + + decipher.setAuthTag(Buffer.from(tag, 'base64')); + + let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); + cleartext += decipher.final('utf8'); + + return cleartext; +} + +export { + generateKeyPair, + encryptAsymmetric, + decryptAsymmetric, + encryptSymmetric128BitHexKeyUTF8, + decryptSymmetric128BitHexKeyUTF8 +}; diff --git a/backend/src/utils/errors.ts b/backend/src/utils/errors.ts index e9972edf5..4b698bee3 100644 --- a/backend/src/utils/errors.ts +++ b/backend/src/utils/errors.ts @@ -73,6 +73,16 @@ export const ValidationError = (error?: Partial) => new Req stack: error?.stack }); +//* ----->[INTEGRATION AUTH ERRORS]<----- +export const IntegrationAuthNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'integration_auth_not_found_error', + message: error?.message ?? 'The requested integration authorization was not found', + context: error?.context, + stack: error?.stack +}); + //* ----->[INTEGRATION ERRORS]<----- export const IntegrationNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.ERROR, @@ -93,6 +103,16 @@ export const WorkspaceNotFoundError = (error?: Partial) => stack: error?.stack }); +//* ----->[WORKSPACE MEMBERSHIP ERRORS]<----- +export const MembershipNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'workspace_membership_not_found_error', + message: error?.message ?? 'The requested membership was not found', + context: error?.context, + stack: error?.stack +}); + //* ----->[ORGANIZATION ERRORS]<----- export const OrganizationNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.ERROR, @@ -103,6 +123,16 @@ export const OrganizationNotFoundError = (error?: Partial) stack: error?.stack }); +//* ----->[MEMBERSHIP ORGANIZATION ERRORS]<----- +export const MembershipOrgNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'organization_membership_not_found_error', + message: error?.message ?? 'The requested organization membership was not found', + context: error?.context, + stack: error?.stack +}); + //* ----->[ACCOUNT ERRORS]<----- export const AccountNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.ERROR, @@ -123,6 +153,16 @@ export const SecretNotFoundError = (error?: Partial) => new stack: error?.stack }); +//* ----->[SECRET BLIND INDEX DATA ERRORS]<----- +export const SecretBlindIndexDataNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'secret_blind_index_data_not_found_error', + message: error?.message ?? 'The requested secret was not found', + context: error?.context, + stack: error?.stack +}); + //* ----->[SECRET SNAPSHOT ERRORS]<----- export const SecretSnapshotNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.ERROR, @@ -157,10 +197,38 @@ export const ServiceTokenDataNotFoundError = (error?: Partial) => new RequestError({ logLevel: error?.logLevel ?? LogLevel.ERROR, statusCode: error?.statusCode ?? 404, - type: error?.type ?? 'service_token_data_not_found_error', + type: error?.type ?? 'api_key_data_not_found_error', message: error?.message ?? 'The requested service token data was not found', context: error?.context, stack: error?.stack +}); + +//* ----->[SERVICE_ACCOUNT ERRORS]<----- +export const ServiceAccountNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'service_account_not_found_error', + message: error?.message ?? 'The requested service account was not found', + context: error?.context, + stack: error?.stack +}); + +export const ServiceAccountKeyNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'service_account_key_not_found_error', + message: error?.message ?? 'The requested service account key was not found', + context: error?.context, + stack: error?.stack }) +export const BotNotFoundError = (error?: Partial) => new RequestError({ + logLevel: error?.logLevel ?? LogLevel.ERROR, + statusCode: error?.statusCode ?? 404, + type: error?.type ?? 'bot_not_found_error', + message: error?.message ?? 'The requested bot was not found', + context: error?.context, + stack: error?.stack +}) + //* ----->[MISC ERRORS]<----- diff --git a/backend/src/utils/folder.ts b/backend/src/utils/folder.ts new file mode 100644 index 000000000..45a8b94d6 --- /dev/null +++ b/backend/src/utils/folder.ts @@ -0,0 +1,87 @@ +// import Folder from "../models/folder"; + +// export const ROOT_FOLDER_PATH = "/" + +// export const getFolderPath = async (folderId: string) => { +// let currentFolder = await Folder.findById(folderId); +// const pathSegments = []; + +// while (currentFolder) { +// pathSegments.unshift(currentFolder.name); +// currentFolder = currentFolder.parent ? await Folder.findById(currentFolder.parent) : null; +// } + +// return '/' + pathSegments.join('/'); +// }; + +// /** +// Returns the folder ID associated with the specified secret path in the given workspace and environment. +// @param workspaceId - The ID of the workspace to search in. +// @param environment - The environment to search in. +// @param secretPath - The secret path to search for. +// @returns The folder ID associated with the specified secret path, or undefined if the path is at the root folder level. +// @throws Error if the specified secret path is not found. +// */ +// export const getFolderIdFromPath = async (workspaceId: string, environment: string, secretPath: string) => { +// const secretPathParts = secretPath.split("/").filter(path => path != "") +// if (secretPathParts.length <= 1) { +// return undefined // root folder, so no folder id +// } + +// const folderId = await Folder.find({ path: secretPath, workspace: workspaceId, environment: environment }) +// if (!folderId) { +// throw Error("Secret path not found") +// } + +// return folderId +// } + +// /** +// * Cleans up a path by removing empty parts, duplicate slashes, +// * and ensuring it starts with ROOT_FOLDER_PATH. +// * @param path - The input path to clean up. +// * @returns The cleaned-up path string. +// */ +// export const normalizePath = (path: string) => { +// if (path == undefined || path == "" || path == ROOT_FOLDER_PATH) { +// return ROOT_FOLDER_PATH +// } + +// const pathParts = path.split("/").filter(part => part != "") +// const cleanPathString = ROOT_FOLDER_PATH + pathParts.join("/") + +// return cleanPathString +// } + +// export const getFoldersInDirectory = async (workspaceId: string, environment: string, pathString: string) => { +// const normalizedPath = normalizePath(pathString) +// const foldersInDirectory = await Folder.find({ +// workspace: workspaceId, +// environment: environment, +// parentPath: normalizedPath, +// }); + +// return foldersInDirectory; +// } + +// /** +// * Returns the parent path of the given path. +// * @param path - The input path. +// * @returns The parent path string. +// */ +// export const getParentPath = (path: string) => { +// const normalizedPath = normalizePath(path); +// const folderParts = normalizedPath.split('/').filter(part => part !== ''); + +// let folderParent = ROOT_FOLDER_PATH; +// if (folderParts.length > 1) { +// folderParent = ROOT_FOLDER_PATH + folderParts.slice(0, folderParts.length - 1).join('/'); +// } + +// return folderParent; +// } + +// export const validateFolderName = (folderName: string) => { +// const validNameRegex = /^[a-zA-Z0-9-_]+$/; +// return validNameRegex.test(folderName); +// } diff --git a/backend/src/utils/logger.ts b/backend/src/utils/logger.ts index ed29c97ca..15335a619 100644 --- a/backend/src/utils/logger.ts +++ b/backend/src/utils/logger.ts @@ -12,7 +12,7 @@ const logFormat = (prefix: string) => combine( printf((info) => `${info.timestamp} ${info.label} ${info.level}: ${info.message}`) ); -const createLoggerWithLabel = (level: string, label: string) => { +const createLoggerWithLabel = async (level: string, label: string) => { const _level = level.toLowerCase() || 'info' //* Always add Console output to transports const _transports: any[] = [ @@ -25,10 +25,10 @@ const createLoggerWithLabel = (level: string, label: string) => { }) ] //* Add LokiTransport if it's enabled - if(getLokiHost() !== undefined){ + if((await getLokiHost()) !== undefined){ _transports.push( new LokiTransport({ - host: getLokiHost(), + host: await getLokiHost(), handleExceptions: true, handleRejections: true, batching: true, @@ -40,7 +40,7 @@ const createLoggerWithLabel = (level: string, label: string) => { labels: { app: process.env.npm_package_name, version: process.env.npm_package_version, - environment: getNodeEnv() + environment: await getNodeEnv() }, onConnectionError: (err: Error)=> console.error('Connection error while connecting to Loki Server.\n', err) }) @@ -58,12 +58,10 @@ const createLoggerWithLabel = (level: string, label: string) => { }); } -const DEFAULT_LOGGERS = { - "backend-main": createLoggerWithLabel('info', '[IFSC:backend-main]'), - "database": createLoggerWithLabel('info', '[IFSC:database]'), -} -type LoggerNames = keyof typeof DEFAULT_LOGGERS - -export const getLogger = (loggerName: LoggerNames) => { - return DEFAULT_LOGGERS[loggerName] +export const getLogger = async (loggerName: 'backend-main' | 'database') => { + const logger = { + "backend-main": await createLoggerWithLabel('info', '[IFSC:backend-main]'), + "database": await createLoggerWithLabel('info', '[IFSC:database]'), + } + return logger[loggerName] } diff --git a/backend/src/utils/patchAsyncRoutes.js b/backend/src/utils/patchAsyncRoutes.js deleted file mode 100644 index 24fe007f9..000000000 --- a/backend/src/utils/patchAsyncRoutes.js +++ /dev/null @@ -1,69 +0,0 @@ -/* -Original work Copyright (c) 2016, Nikolay Nemshilov -Modified work Copyright (c) 2016, David Banham - -Permission to use, copy, modify, and/or distribute this software for any purpose -with or without fee is hereby granted, provided that the above copyright notice -and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH -REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, -INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS -OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER -TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF -THIS SOFTWARE. - -*/ - -/* eslint-disable @typescript-eslint/no-var-requires */ -/* eslint-env node */ -const Layer = require('express/lib/router/layer'); -const Router = require('express/lib/router'); - -const last = (arr = []) => arr[arr.length - 1]; -const noop = Function.prototype; - -function copyFnProps(oldFn, newFn) { - Object.keys(oldFn).forEach((key) => { - newFn[key] = oldFn[key]; - }); - return newFn; -} - -function wrap(fn) { - const newFn = function newFn(...args) { - const ret = fn.apply(this, args); - const next = (args.length === 5 ? args[2] : last(args)) || noop; - if (ret && ret.catch) ret.catch(err => next(err)); - return ret; - }; - Object.defineProperty(newFn, 'length', { - value: fn.length, - writable: false, - }); - return copyFnProps(fn, newFn); -} - -function patchRouterParam() { - const originalParam = Router.prototype.constructor.param; - Router.prototype.constructor.param = function param(name, fn) { - fn = wrap(fn); - return originalParam.call(this, name, fn); - }; -} - -Object.defineProperty(Layer.prototype, 'handle', { - enumerable: true, - get() { - return this.__handle; - }, - set(fn) { - fn = wrap(fn); - this.__handle = fn; - }, -}); - -module.exports = { - patchRouterParam -}; diff --git a/backend/src/utils/requestError.ts b/backend/src/utils/requestError.ts index 4b5635bac..570ed132e 100644 --- a/backend/src/utils/requestError.ts +++ b/backend/src/utils/requestError.ts @@ -81,13 +81,13 @@ export default class RequestError extends Error{ return obj } - public format(req: Request){ + public async format(req: Request){ let _context = Object.assign({ stacktrace: this.stacktrace }, this.context) //* Omit sensitive information from context that can leak internal workings of this program if user is not developer - if(!getVerboseErrorOutput()){ + if(!(await getVerboseErrorOutput())){ _context = this._omit(_context, [ 'stacktrace', 'exception', diff --git a/backend/src/utils/setup/backfillData.ts b/backend/src/utils/setup/backfillData.ts new file mode 100644 index 000000000..4bb163aae --- /dev/null +++ b/backend/src/utils/setup/backfillData.ts @@ -0,0 +1,426 @@ +/* eslint-disable no-console */ +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 { + Secret, + ISecret, + SecretBlindIndexData, + Workspace, + Bot, + BackupPrivateKey, + IntegrationAuth, + ServiceTokenData, +} from "../../models"; +import { generateKeyPair } from "../../utils/crypto"; +import { client, getEncryptionKey, getRootEncryptionKey } from "../../config"; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64, +} from "../../variables"; +import { InternalServerError } from "../errors"; + +/** + * Backfill secrets to ensure that they're all versioned and have + * corresponding secret versions + */ +export const backfillSecretVersions = async () => { + await Secret.updateMany( + { version: { $exists: false } }, + { $set: { version: 1 } } + ); + + const unversionedSecrets: ISecret[] = await Secret.aggregate([ + { + $lookup: { + from: "secretversions", + localField: "_id", + foreignField: "secret", + as: "versions", + }, + }, + { + $match: { + versions: { $size: 0 }, + }, + }, + ]); + + if (unversionedSecrets.length > 0) { + await EESecretService.addSecretVersions({ + secretVersions: unversionedSecrets.map( + (s, idx) => + new SecretVersion({ + ...s, + secret: s._id, + version: s.version ? s.version : 1, + isDeleted: false, + workspace: s.workspace, + environment: s.environment, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }) + ), + }); + } + console.log("Migration: Secret version migration v1 complete"); +}; + +/** + * Backfill workspace bots to ensure that every workspace has a bot + */ +export const backfillBots = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const workspaceIdsWithBot = await Bot.distinct("workspace"); + const workspaceIdsToAddBot = await Workspace.distinct("_id", { + _id: { + $nin: workspaceIdsWithBot, + }, + }); + + if (workspaceIdsToAddBot.length === 0) return; + + const botsToInsert = await Promise.all( + workspaceIdsToAddBot.map(async (workspaceToAddBot) => { + const { publicKey, privateKey } = generateKeyPair(); + + if (rootEncryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv, + tag, + } = client.encryptSymmetric(privateKey, rootEncryptionKey); + + return new Bot({ + name: "Infisical Bot", + workspace: workspaceToAddBot, + isActive: false, + publicKey, + encryptedPrivateKey, + iv, + tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64, + }); + } else if (encryptionKey) { + const { + ciphertext: encryptedPrivateKey, + iv, + tag, + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: privateKey, + key: encryptionKey, + }); + + return new Bot({ + name: "Infisical Bot", + workspace: workspaceToAddBot, + isActive: false, + publicKey, + encryptedPrivateKey, + iv, + tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + } + + throw InternalServerError({ + message: + "Failed to backfill workspace bots due to missing encryption key", + }); + }) + ); + + await Bot.insertMany(botsToInsert); +}; + +/** + * Backfill secret blind index data to ensure that every workspace + * has a secret blind index data + */ +export const backfillSecretBlindIndexData = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + const workspaceIdsBlindIndexed = await SecretBlindIndexData.distinct( + "workspace" + ); + const workspaceIdsToBlindIndex = await Workspace.distinct("_id", { + _id: { + $nin: workspaceIdsBlindIndexed, + }, + }); + + if (workspaceIdsToBlindIndex.length === 0) return; + + const secretBlindIndexDataToInsert = await Promise.all( + workspaceIdsToBlindIndex.map(async (workspaceToBlindIndex) => { + const salt = crypto.randomBytes(16).toString("base64"); + + if (rootEncryptionKey) { + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag, + } = client.encryptSymmetric(salt, rootEncryptionKey); + + return new SecretBlindIndexData({ + workspace: workspaceToBlindIndex, + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64, + }); + } else if (encryptionKey) { + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag, + } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: salt, + key: encryptionKey, + }); + + return new SecretBlindIndexData({ + workspace: workspaceToBlindIndex, + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }); + } + + throw InternalServerError({ + message: + "Failed to backfill secret blind index data due to missing encryption key", + }); + }) + ); + + SecretBlindIndexData.insertMany(secretBlindIndexDataToInsert); +}; + +/** + * Backfill Secret, SecretVersion, SecretBlindIndexData, Bot, + * BackupPrivateKey, IntegrationAuth collections to ensure that + * they all have encryption metadata documented + */ +export const backfillEncryptionMetadata = async () => { + // backfill secret encryption metadata + await Secret.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); + + // backfill secret version encryption metadata + await SecretVersion.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); + + // backfill secret blind index encryption metadata + await SecretBlindIndexData.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); + + // backfill bot encryption metadata + await Bot.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); + + // backfill backup private key encryption metadata + await BackupPrivateKey.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); + + // backfill integration auth encryption metadata + await IntegrationAuth.updateMany( + { + algorithm: { + $exists: false, + }, + keyEncoding: { + $exists: false, + }, + }, + { + $set: { + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8, + }, + } + ); +}; + +export const backfillSecretFolders = async () => { + await Secret.updateMany( + { + folder: { + $exists: false, + }, + }, + { + $set: { + folder: "root", + }, + } + ); + + await SecretVersion.updateMany( + { + folder: { + $exists: false, + }, + }, + { + $set: { + folder: "root", + }, + } + ); + + // Back fill because tags were missing in secret versions + await SecretVersion.updateMany( + { + tags: { + $exists: false, + }, + }, + { + $set: { + tags: [], + }, + } + ); + + let secretSnapshots = await SecretSnapshot.find({ + environment: { + $exists: false, + }, + }) + .populate<{ secretVersions: ISecretVersion[] }>("secretVersions") + .limit(50); + + while (secretSnapshots.length > 0) { + for (const secSnapshot of secretSnapshots) { + const groupSnapByEnv: Record> = {}; + secSnapshot.secretVersions.forEach((secVer) => { + if (!groupSnapByEnv?.[secVer.environment]) + groupSnapByEnv[secVer.environment] = []; + groupSnapByEnv[secVer.environment].push(secVer); + }); + + const newSnapshots = Object.keys(groupSnapByEnv).map((snapEnv) => { + const secretIdsOfEnvGroup = groupSnapByEnv[snapEnv] + ? groupSnapByEnv[snapEnv].map((secretVersion) => secretVersion._id) + : []; + return { + ...secSnapshot.toObject({ virtuals: false }), + _id: new Types.ObjectId(), + environment: snapEnv, + secretVersions: secretIdsOfEnvGroup, + }; + }); + + await SecretSnapshot.insertMany(newSnapshots); + await secSnapshot.delete(); + } + + secretSnapshots = await SecretSnapshot.find({ + environment: { + $exists: false, + }, + }) + .populate<{ secretVersions: ISecretVersion[] }>("secretVersions") + .limit(50); + } + + console.log("Migration: Folder migration v1 complete"); +}; + +export const backfillServiceToken = async () => { + await ServiceTokenData.updateMany( + { + secretPath: { + $exists: false, + }, + }, + { + $set: { + secretPath: "/", + }, + } + ); + console.log("Migration: Service token migration v1 complete"); +}; diff --git a/backend/src/utils/setup/index.ts b/backend/src/utils/setup/index.ts new file mode 100644 index 000000000..bec142e9e --- /dev/null +++ b/backend/src/utils/setup/index.ts @@ -0,0 +1,95 @@ +import * as Sentry from "@sentry/node"; +import { DatabaseService, TelemetryService } from "../../services"; +import { setTransporter } from "../../helpers/nodemailer"; +import { EELicenseService } from "../../ee/services"; +import { initSmtp } from "../../services/smtp"; +import { createTestUserForDevelopment } from "../addDevelopmentUser"; +// eslint-disable-next-line @typescript-eslint/no-var-requires +import { validateEncryptionKeysConfig } from "./validateConfig"; +import { + backfillSecretVersions, + backfillBots, + backfillSecretBlindIndexData, + backfillEncryptionMetadata, + backfillSecretFolders, + backfillServiceToken, +} from "./backfillData"; +import { + reencryptBotPrivateKeys, + reencryptSecretBlindIndexDataSalts, +} from "./reencryptData"; +import { + getNodeEnv, + getMongoURL, + getSentryDSN, + getClientSecretGoogle, + getClientIdGoogle, +} from "../../config"; +import { initializePassport } from "../auth"; + +/** + * Prepare Infisical upon startup. This includes tasks like: + * - Log initial telemetry message + * - Initializing SMTP configuration + * - Initializing the instance global feature set (if applicable) + * - Initializing the database connection + * - Initializing Sentry + * - Backfilling data + * - Re-encrypting data + */ +export const setup = async () => { + await validateEncryptionKeysConfig(); + await TelemetryService.logTelemetryMessage(); + + // initializing SMTP configuration + setTransporter(await initSmtp()); + + // initializing global feature set + await EELicenseService.initGlobalFeatureSet(); + + // initializing the database connection + await DatabaseService.initDatabase(await getMongoURL()); + + const googleClientSecret: string = await getClientSecretGoogle(); + const googleClientId: string = await getClientIdGoogle(); + + if (googleClientId && googleClientSecret) { + await initializePassport(); + } + + // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY + // to base64 256-bit ROOT_ENCRYPTION_KEY + // await reencryptBotPrivateKeys(); + // await reencryptSecretBlindIndexDataSalts(); + + // initializing the database connection + await DatabaseService.initDatabase(await getMongoURL()); + + /** + * NOTE: the order in this setup function is critical. + * It is important to backfill data before performing any re-encryption functionality. + */ + + // backfilling data to catch up with new collections and updated fields + await backfillSecretVersions(); + await backfillBots(); + await backfillSecretBlindIndexData(); + await backfillEncryptionMetadata(); + await backfillSecretFolders(); + await backfillServiceToken(); + + // re-encrypt any data previously encrypted under server hex 128-bit ENCRYPTION_KEY + // to base64 256-bit ROOT_ENCRYPTION_KEY + await reencryptBotPrivateKeys(); + await reencryptSecretBlindIndexDataSalts(); + + // initializing Sentry + Sentry.init({ + dsn: await getSentryDSN(), + tracesSampleRate: 1.0, + debug: (await getNodeEnv()) === "production" ? false : true, + environment: await getNodeEnv(), + }); + + await createTestUserForDevelopment(); +}; diff --git a/backend/src/utils/setup/reencryptData.ts b/backend/src/utils/setup/reencryptData.ts new file mode 100644 index 000000000..0741b44f4 --- /dev/null +++ b/backend/src/utils/setup/reencryptData.ts @@ -0,0 +1,124 @@ +import { + Bot, + IBot, + ISecretBlindIndexData, + SecretBlindIndexData +} from '../../models'; +import { decryptSymmetric128BitHexKeyUTF8 } from '../../utils/crypto'; +import { + client, + getEncryptionKey, + getRootEncryptionKey +} from '../../config'; +import { + ALGORITHM_AES_256_GCM, + ENCODING_SCHEME_UTF8, + ENCODING_SCHEME_BASE64 +} from '../../variables'; + +/** + * Re-encrypt bot private keys from hex 128-bit ENCRYPTION_KEY + * to base64 256-bit ROOT_ENCRYPTION_KEY + */ +export const reencryptBotPrivateKeys = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if (encryptionKey && rootEncryptionKey) { + // 1: re-encrypt bot private keys under ROOT_ENCRYPTION_KEY + const bots = await Bot.find({ + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }).select('+encryptedPrivateKey iv tag algorithm keyEncoding'); + + if (bots.length === 0) return; + + const operationsBot = await Promise.all( + bots.map(async (bot: IBot) => { + + const privateKey = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: bot.encryptedPrivateKey, + iv: bot.iv, + tag: bot.tag, + key: encryptionKey + }); + + const { + ciphertext: encryptedPrivateKey, + iv, + tag + } = client.encryptSymmetric(privateKey, rootEncryptionKey); + + return ({ + updateOne: { + filter: { + _id: bot._id + }, + update: { + encryptedPrivateKey, + iv, + tag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64 + } + } + }) + }) + ); + + await Bot.bulkWrite(operationsBot); + } +} + +/** + * Re-encrypt secret blind index data salts from hex 128-bit ENCRYPTION_KEY + * to base64 256-bit ROOT_ENCRYPTION_KEY + */ +export const reencryptSecretBlindIndexDataSalts = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if (encryptionKey && rootEncryptionKey) { + const secretBlindIndexData = await SecretBlindIndexData.find({ + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_UTF8 + }).select('+encryptedSaltCiphertext +saltIV +saltTag +algorithm +keyEncoding'); + + if (secretBlindIndexData.length == 0) return; + + const operationsSecretBlindIndexData = await Promise.all( + secretBlindIndexData.map(async (secretBlindIndexDatum: ISecretBlindIndexData) => { + + const salt = decryptSymmetric128BitHexKeyUTF8({ + ciphertext: secretBlindIndexDatum.encryptedSaltCiphertext, + iv: secretBlindIndexDatum.saltIV, + tag: secretBlindIndexDatum.saltTag, + key: encryptionKey + }); + + const { + ciphertext: encryptedSaltCiphertext, + iv: saltIV, + tag: saltTag + } = client.encryptSymmetric(salt, rootEncryptionKey); + + return ({ + updateOne: { + filter: { + _id: secretBlindIndexDatum._id + }, + update: { + encryptedSaltCiphertext, + saltIV, + saltTag, + algorithm: ALGORITHM_AES_256_GCM, + keyEncoding: ENCODING_SCHEME_BASE64 + } + } + }) + }) + ); + + await SecretBlindIndexData.bulkWrite(operationsSecretBlindIndexData); + } +} \ No newline at end of file diff --git a/backend/src/utils/setup/validateConfig.ts b/backend/src/utils/setup/validateConfig.ts new file mode 100644 index 000000000..f8ebd3c17 --- /dev/null +++ b/backend/src/utils/setup/validateConfig.ts @@ -0,0 +1,61 @@ +import { + getEncryptionKey, + getRootEncryptionKey +} from '../../config'; +import { + InternalServerError +} from '../../utils/errors'; + +/** + * Validate ENCRYPTION_KEY and ROOT_ENCRYPTION_KEY. Specifically: + * - ENCRYPTION_KEY is a hex, 128-bit string + * - ROOT_ENCRYPTION_KEY is a base64, 128-bit string + * - Either ENCRYPTION_KEY or ROOT_ENCRYPTION_KEY are present + * + * - Encrypted data is consistent with the passed in encryption keys + * + * NOTE 1: ENCRYPTION_KEY is being transitioned to ROOT_ENCRYPTION_KEY + * NOTE 2: In the future, we will have a superior validation function + * built into the SDK. + */ +export const validateEncryptionKeysConfig = async () => { + const encryptionKey = await getEncryptionKey(); + const rootEncryptionKey = await getRootEncryptionKey(); + + if ( + (encryptionKey === undefined || encryptionKey === "") && + (rootEncryptionKey === undefined || rootEncryptionKey === "") + ) throw InternalServerError({ + message: "Failed to find required root encryption key environment variable. Please make sure that you're passing in a ROOT_ENCRYPTION_KEY environment variable." + }); + + // if (encryptionKey && encryptionKey !== '') { + // // validate [encryptionKey] + + // const keyBuffer = Buffer.from(encryptionKey, 'hex'); + // const decoded = keyBuffer.toString('hex'); + + // if (decoded !== encryptionKey) throw InternalServerError({ + // message: 'Failed to validate that the encryption key is correctly encoded in hex.' + // }); + + // if (keyBuffer.length !== 16) throw InternalServerError({ + // message: 'Failed to validate that the encryption key is a 128-bit hex string.' + // }); + // } + + if (rootEncryptionKey && rootEncryptionKey !== '') { + // validate [rootEncryptionKey] + + const keyBuffer = Buffer.from(rootEncryptionKey, 'base64') + const decoded = keyBuffer.toString('base64'); + + if (decoded !== rootEncryptionKey) throw InternalServerError({ + message: 'Failed to validate that the root encryption key is correctly encoded in base64' + }); + + if (keyBuffer.length !== 32) throw InternalServerError({ + message: 'Failed to validate that the encryption key is a 256-bit base64 string' + }); + } +} \ No newline at end of file diff --git a/backend/src/validation/bot.ts b/backend/src/validation/bot.ts new file mode 100644 index 000000000..7104eec33 --- /dev/null +++ b/backend/src/validation/bot.ts @@ -0,0 +1,98 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + Bot, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; +import { validateUserClientForWorkspace } from './user'; +import { + UnauthorizedRequestError, + BotNotFoundError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +/** + * Validate authenticated clients for bot with id [botId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.botId - id of bot to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + */ +export const validateClientForBot = async ({ + authData, + botId, + acceptedRoles, +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + botId: Types.ObjectId; + acceptedRoles: Array<"admin" | "member">; +}) => { + const bot = await Bot.findById(botId); + + if (!bot) throw BotNotFoundError(); + + if ( + authData.authMode === AUTH_MODE_JWT && + authData.authPayload instanceof User + ) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: bot.workspace, + acceptedRoles, + }); + + return bot; + } + + if ( + authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && + authData.authPayload instanceof ServiceAccount + ) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: bot.workspace, + }); + + return bot; + } + + if ( + authData.authMode === AUTH_MODE_SERVICE_TOKEN && + authData.authPayload instanceof ServiceTokenData + ) { + throw UnauthorizedRequestError({ + message: "Failed service token authorization for bot", + }); + } + + if ( + authData.authMode === AUTH_MODE_API_KEY && + authData.authPayload instanceof User + ) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: bot.workspace, + acceptedRoles, + }); + + return bot; + } + + throw BotNotFoundError({ + message: "Failed client authorization for bot", + }); +}; \ No newline at end of file diff --git a/backend/src/validation/index.ts b/backend/src/validation/index.ts new file mode 100644 index 000000000..177c716ea --- /dev/null +++ b/backend/src/validation/index.ts @@ -0,0 +1,11 @@ +export * from './user'; +export * from './workspace'; +export * from './bot'; +export * from './integration'; +export * from './integrationAuth'; +export * from './membership'; +export * from './membershipOrg'; +export * from './organization'; +export * from './secrets'; +export * from './serviceAccount'; +export * from './serviceTokenData'; \ No newline at end of file diff --git a/backend/src/validation/integration.ts b/backend/src/validation/integration.ts new file mode 100644 index 000000000..5b2f4ad3c --- /dev/null +++ b/backend/src/validation/integration.ts @@ -0,0 +1,103 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + Integration, + IntegrationAuth, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; +import { validateUserClientForWorkspace } from './user'; +import { IntegrationService } from '../services'; +import { + IntegrationNotFoundError, + IntegrationAuthNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +/** + * Validate authenticated clients for integration with id [integrationId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.integrationId - id of integration to validate against + * @param {String} obj.environment - (optional) environment in workspace to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint + */ +export const validateClientForIntegration = async ({ + authData, + integrationId, + acceptedRoles +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + integrationId: Types.ObjectId; + acceptedRoles: Array<'admin' | 'member'>; +}) => { + + const integration = await Integration.findById(integrationId); + if (!integration) throw IntegrationNotFoundError(); + + const integrationAuth = await IntegrationAuth + .findById(integration.integrationAuth) + .select( + '+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt' + ); + + if (!integrationAuth) throw IntegrationAuthNotFoundError(); + + const accessToken = (await IntegrationService.getIntegrationAuthAccess({ + integrationAuthId: integrationAuth._id + })).accessToken; + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: integration.workspace, + acceptedRoles + }); + + return ({ integration, accessToken }); + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: integration.workspace + }); + + return ({ integration, accessToken }); + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for integration' + }); + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: integration.workspace, + acceptedRoles + }); + + return ({ integration, accessToken }); + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for integration' + }); +} \ No newline at end of file diff --git a/backend/src/validation/integrationAuth.ts b/backend/src/validation/integrationAuth.ts new file mode 100644 index 000000000..b43dd4cbd --- /dev/null +++ b/backend/src/validation/integrationAuth.ts @@ -0,0 +1,108 @@ +import { Types } from 'mongoose'; +import { + IntegrationAuth, + IUser, + User, + IServiceAccount, + ServiceAccount, + IServiceTokenData, + ServiceTokenData, + IWorkspace +} from '../models'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; +import { + IntegrationAuthNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; +import { IntegrationService } from '../services'; +import { validateUserClientForWorkspace } from './user'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; + +/** + * Validate authenticated clients for integration authorization with id [integrationAuthId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.integrationAuthId - id of integration authorization to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint + */ + const validateClientForIntegrationAuth = async ({ + authData, + integrationAuthId, + acceptedRoles, + attachAccessToken +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + integrationAuthId: Types.ObjectId; + acceptedRoles: Array<'admin' | 'member'>; + attachAccessToken?: boolean; +}) => { + + const integrationAuth = await IntegrationAuth + .findById(integrationAuthId) + .populate<{ workspace: IWorkspace }>('workspace') + .select( + '+refreshCiphertext +refreshIV +refreshTag +accessCiphertext +accessIV +accessTag +accessExpiresAt' + ); + + if (!integrationAuth) throw IntegrationAuthNotFoundError(); + + let accessToken; + if (attachAccessToken) { + accessToken = (await IntegrationService.getIntegrationAuthAccess({ + integrationAuthId: integrationAuth._id + })).accessToken; + } + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: integrationAuth.workspace._id, + acceptedRoles + }); + + return ({ integrationAuth, accessToken }); + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: integrationAuth.workspace._id + }); + + return ({ integrationAuth, accessToken }); + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for integration authorization' + }); + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: integrationAuth.workspace._id, + acceptedRoles + }); + + return ({ integrationAuth, accessToken }); + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for integration authorization' + }); +} + +export { + validateClientForIntegrationAuth +}; \ No newline at end of file diff --git a/backend/src/validation/membership.ts b/backend/src/validation/membership.ts new file mode 100644 index 000000000..ab4f8dc76 --- /dev/null +++ b/backend/src/validation/membership.ts @@ -0,0 +1,94 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + Membership, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; +import { validateUserClientForWorkspace } from './user'; +import { validateServiceTokenDataClientForWorkspace } from './serviceTokenData'; +import { + MembershipNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +/** + * Validate authenticated clients for membership with id [membershipId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.membershipId - id of membership to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspaceRoles + * @returns {Membership} - validated membership + */ +export const validateClientForMembership = async ({ + authData, + membershipId, + acceptedRoles +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + membershipId: Types.ObjectId; + acceptedRoles: Array<'admin' | 'member'>; +}) => { + + const membership = await Membership.findById(membershipId); + + if (!membership) throw MembershipNotFoundError({ + message: 'Failed to find membership' + }); + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: membership.workspace, + acceptedRoles + }); + + return membership; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: membership.workspace + }); + + return membership; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + await validateServiceTokenDataClientForWorkspace({ + serviceTokenData: authData.authPayload, + workspaceId: new Types.ObjectId(membership.workspace) + }); + + return membership; + } + + if (authData.authMode == AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: membership.workspace, + acceptedRoles + }); + + return membership; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for membership' + }); +} \ No newline at end of file diff --git a/backend/src/validation/membershipOrg.ts b/backend/src/validation/membershipOrg.ts new file mode 100644 index 000000000..7fd86a374 --- /dev/null +++ b/backend/src/validation/membershipOrg.ts @@ -0,0 +1,93 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + MembershipOrg, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { + validateMembershipOrg +} from '../helpers/membershipOrg'; +import { + MembershipOrgNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +/** + * Validate authenticated clients for organization membership with id [membershipOrgId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.membershipOrgId - id of organization membership to validate against + * @param {Array<'owner' | 'admin' | 'member'>} obj.acceptedRoles - accepted organization roles + * @param {MembershipOrg} - validated organization membership + */ +export const validateClientForMembershipOrg = async ({ + authData, + membershipOrgId, + acceptedRoles, + acceptedStatuses +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + membershipOrgId: Types.ObjectId; + acceptedRoles: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses: Array<'invited' | 'accepted'>; +}) => { + const membershipOrg = await MembershipOrg.findById(membershipOrgId); + + if (!membershipOrg) throw MembershipOrgNotFoundError({ + message: 'Failed to find organization membership ' + }); + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateMembershipOrg({ + userId: authData.authPayload._id, + organizationId: membershipOrg.organization, + acceptedRoles, + acceptedStatuses + }); + + return membershipOrg; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + if (!authData.authPayload.organization.equals(membershipOrg.organization)) throw UnauthorizedRequestError({ + message: 'Failed service account client authorization for organization membership' + }); + + return membershipOrg; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + throw UnauthorizedRequestError({ + message: 'Failed service account client authorization for organization membership' + }); + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateMembershipOrg({ + userId: authData.authPayload._id, + organizationId: membershipOrg.organization, + acceptedRoles, + acceptedStatuses + }); + + return membershipOrg; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for organization membership' + }); +} \ No newline at end of file diff --git a/backend/src/validation/organization.ts b/backend/src/validation/organization.ts new file mode 100644 index 000000000..239517b75 --- /dev/null +++ b/backend/src/validation/organization.ts @@ -0,0 +1,104 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + Organization, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; +import { + OrganizationNotFoundError, + UnauthorizedRequestError +} from '../utils/errors'; +import { validateUserClientForOrganization } from './user'; +import { validateServiceAccountClientForOrganization } from './serviceAccount'; + +/** + * Validate accepted clients for organization with id [organizationId] + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.organizationId - id of organization to validate against + */ +export const validateClientForOrganization = async ({ + authData, + organizationId, + acceptedRoles, + acceptedStatuses, +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + organizationId: Types.ObjectId; + acceptedRoles: Array<"owner" | "admin" | "member">; + acceptedStatuses: Array<"invited" | "accepted">; +}) => { + const organization = await Organization.findById(organizationId); + + if (!organization) { + throw OrganizationNotFoundError({ + message: "Failed to find organization", + }); + } + + if ( + authData.authMode === AUTH_MODE_JWT && + authData.authPayload instanceof User + ) { + const membershipOrg = await validateUserClientForOrganization({ + user: authData.authPayload, + organization, + acceptedRoles, + acceptedStatuses, + }); + + return { organization, membershipOrg }; + } + + if ( + authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && + authData.authPayload instanceof ServiceAccount + ) { + await validateServiceAccountClientForOrganization({ + serviceAccount: authData.authPayload, + organization, + }); + + return { organization }; + } + + if ( + authData.authMode === AUTH_MODE_SERVICE_TOKEN && + authData.authPayload instanceof ServiceTokenData + ) { + throw UnauthorizedRequestError({ + message: "Failed service token authorization for organization", + }); + } + + if ( + authData.authMode === AUTH_MODE_API_KEY && + authData.authPayload instanceof User + ) { + const membershipOrg = await validateUserClientForOrganization({ + user: authData.authPayload, + organization, + acceptedRoles, + acceptedStatuses, + }); + + return { organization, membershipOrg }; + } + + throw UnauthorizedRequestError({ + message: "Failed client authorization for organization", + }); +}; \ No newline at end of file diff --git a/backend/src/validation/secrets.ts b/backend/src/validation/secrets.ts new file mode 100644 index 000000000..272fe4545 --- /dev/null +++ b/backend/src/validation/secrets.ts @@ -0,0 +1,174 @@ +import { Types } from 'mongoose'; +import { + ISecret, + Secret, + User, + ServiceAccount, + ServiceTokenData +} from '../models'; +import { validateServiceAccountClientForWorkspace, validateServiceAccountClientForSecrets } from './serviceAccount'; +import { validateUserClientForSecret, validateUserClientForSecrets } from './user'; +import { validateServiceTokenDataClientForWorkspace, validateServiceTokenDataClientForSecrets } from './serviceTokenData'; +import { AuthData } from '../interfaces/middleware'; +import { + SecretNotFoundError, + UnauthorizedRequestError, + BadRequestError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +/** + * Validate authenticated clients for secrets with id [secretId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.secretId - id of secret to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint + */ +export const validateClientForSecret = async ({ + authData, + secretId, + acceptedRoles, + requiredPermissions +}: { + authData: AuthData; + secretId: Types.ObjectId; + acceptedRoles: Array<'admin' | 'member'>; + requiredPermissions: string[]; +}) => { + const secret = await Secret.findById(secretId); + + if (!secret) throw SecretNotFoundError({ + message: 'Failed to find secret' + }); + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForSecret({ + user: authData.authPayload, + secret, + acceptedRoles, + requiredPermissions + }); + + return secret; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: secret.workspace, + environment: secret.environment, + requiredPermissions + }); + + return secret; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + await validateServiceTokenDataClientForWorkspace({ + serviceTokenData: authData.authPayload, + workspaceId: secret.workspace, + environment: secret.environment + }); + + return secret; + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForSecret({ + user: authData.authPayload, + secret, + acceptedRoles, + requiredPermissions + }); + + return secret; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for secret' + }); +} + +/** + * Validate authenticated clients for secrets with ids [secretIds] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId[]} obj.secretIds - id of workspace to validate against + * @param {String} obj.environment - (optional) environment in workspace to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint + */ +export const validateClientForSecrets = async ({ + authData, + secretIds, + requiredPermissions +}: { + authData: AuthData; + secretIds: Types.ObjectId[]; + requiredPermissions: string[]; +}) => { + + let secrets: ISecret[] = []; + + secrets = await Secret.find({ + _id: { + $in: secretIds + } + }); + + if (secrets.length != secretIds.length) { + throw BadRequestError({ message: 'Failed to validate non-existent secrets' }) + } + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForSecrets({ + user: authData.authPayload, + secrets, + requiredPermissions + }); + + return secrets; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForSecrets({ + serviceAccount: authData.authPayload, + secrets, + requiredPermissions + }); + + return secrets; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + await validateServiceTokenDataClientForSecrets({ + serviceTokenData: authData.authPayload, + secrets, + requiredPermissions + }); + + return secrets; + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForSecrets({ + user: authData.authPayload, + secrets, + requiredPermissions + }); + + return secrets; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for secrets resource' + }); +} \ No newline at end of file diff --git a/backend/src/validation/serviceAccount.ts b/backend/src/validation/serviceAccount.ts new file mode 100644 index 000000000..11997763c --- /dev/null +++ b/backend/src/validation/serviceAccount.ts @@ -0,0 +1,260 @@ +import _ from 'lodash'; +import { Types } from 'mongoose'; +import { + User, + IUser, + ServiceAccount, + IServiceAccount, + ServiceTokenData, + IServiceTokenData, + ISecret, + IOrganization, + ServiceAccountWorkspacePermission +} from '../models'; +import { validateUserClientForServiceAccount } from './user'; +import { + BadRequestError, + UnauthorizedRequestError, + ServiceAccountNotFoundError +} from '../utils/errors'; +import { + PERMISSION_READ_SECRETS, + PERMISSION_WRITE_SECRETS, + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; + +export const validateClientForServiceAccount = async ({ + authData, + serviceAccountId, + requiredPermissions +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }, + serviceAccountId: Types.ObjectId; + requiredPermissions?: string[]; +}) => { + const serviceAccount = await ServiceAccount.findById(serviceAccountId); + + if (!serviceAccount) { + throw ServiceAccountNotFoundError({ + message: 'Failed to find service account' + }); + } + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForServiceAccount({ + user: authData.authPayload, + serviceAccount, + requiredPermissions + }); + + return serviceAccount; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForServiceAccount({ + serviceAccount: authData.authPayload, + targetServiceAccount: serviceAccount, + requiredPermissions + }); + + return serviceAccount; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for service account resource' + }); + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForServiceAccount({ + user: authData.authPayload, + serviceAccount, + requiredPermissions + }); + + return serviceAccount; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for service account resource' + }); +} + +/** + * Validate that service account (client) can access workspace + * with id [workspaceId] and its environment [environment] with required permissions + * [requiredPermissions] + * @param {Object} obj + * @param {ServiceAccount} obj.serviceAccount - service account client + * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against + * @param {String} environment - (optional) environment in workspace to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateServiceAccountClientForWorkspace = async ({ + serviceAccount, + workspaceId, + environment, + requiredPermissions +}: { + serviceAccount: IServiceAccount; + workspaceId: Types.ObjectId; + environment?: string; + requiredPermissions?: string[]; +}) => { + if (environment) { + // case: environment specified -> + // evaluate service account authorization for workspace + // in the context of a specific environment [environment] + const permission = await ServiceAccountWorkspacePermission.findOne({ + serviceAccount, + workspace: new Types.ObjectId(workspaceId), + environment + }); + + if (!permission) throw UnauthorizedRequestError({ + message: 'Failed service account authorization for the given workspace environment' + }); + + let runningIsDisallowed = false; + requiredPermissions?.forEach((requiredPermission: string) => { + switch (requiredPermission) { + case PERMISSION_READ_SECRETS: + if (!permission.read) runningIsDisallowed = true; + break; + case PERMISSION_WRITE_SECRETS: + if (!permission.write) runningIsDisallowed = true; + break; + default: + break; + } + + if (runningIsDisallowed) { + throw UnauthorizedRequestError({ + message: `Failed permissions authorization for workspace environment action : ${requiredPermission}` + }); + } + }); + + } else { + // case: no environment specified -> + // evaluate service account authorization for workspace + // without need of environment [environment] + + const permission = await ServiceAccountWorkspacePermission.findOne({ + serviceAccount, + workspace: new Types.ObjectId(workspaceId) + }); + + if (!permission) throw UnauthorizedRequestError({ + message: 'Failed service account authorization for the given workspace' + }); + } +} + +/** + * Validate that service account (client) can access secrets + * with required permissions [requiredPermissions] + * @param {Object} obj + * @param {ServiceAccount} obj.serviceAccount - service account client + * @param {Secret[]} secrets - secrets to validate against + * @param {string[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateServiceAccountClientForSecrets = async ({ + serviceAccount, + secrets, + requiredPermissions +}: { + serviceAccount: IServiceAccount; + secrets: ISecret[]; + requiredPermissions?: string[]; +}) => { + + const permissions = await ServiceAccountWorkspacePermission.find({ + serviceAccount: serviceAccount._id + }); + + const permissionsObj = _.keyBy(permissions, (p) => { + return `${p.workspace.toString()}-${p.environment}` + }); + + secrets.forEach((secret: ISecret) => { + const permission = permissionsObj[`${secret.workspace.toString()}-${secret.environment}`]; + + if (!permission) throw BadRequestError({ + message: 'Failed to find any permission for the secret workspace and environment' + }); + + requiredPermissions?.forEach((requiredPermission: string) => { + let runningIsDisallowed = false; + requiredPermissions?.forEach((requiredPermission: string) => { + switch (requiredPermission) { + case PERMISSION_READ_SECRETS: + if (!permission.read) runningIsDisallowed = true; + break; + case PERMISSION_WRITE_SECRETS: + if (!permission.write) runningIsDisallowed = true; + break; + default: + break; + } + + if (runningIsDisallowed) { + throw UnauthorizedRequestError({ + message: `Failed permissions authorization for workspace environment action : ${requiredPermission}` + }); + } + }); + }); + }); +} + +/** + * Validate that service account (client) can access target service + * account [serviceAccount] with required permissions [requiredPermissions] + * @param {Object} obj + * @param {SerivceAccount} obj.serviceAccount - service account client + * @param {ServiceAccount} targetServiceAccount - target service account to validate against + * @param {string[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateServiceAccountClientForServiceAccount = ({ + serviceAccount, + targetServiceAccount, + requiredPermissions +}: { + serviceAccount: IServiceAccount; + targetServiceAccount: IServiceAccount; + requiredPermissions?: string[]; +}) => { + if (!serviceAccount.organization.equals(targetServiceAccount.organization)) { + throw UnauthorizedRequestError({ + message: 'Failed service account authorization for the given service account' + }); + } +} + +/** + * Validate that service account (client) can access organization [organization] + * @param {Object} obj + * @param {User} obj.user - service account client + * @param {Organization} obj.organization - organization to validate against + */ +export const validateServiceAccountClientForOrganization = async ({ + serviceAccount, + organization +}: { + serviceAccount: IServiceAccount; + organization: IOrganization; +}) => { + if (!serviceAccount.organization.equals(organization._id)) { + throw UnauthorizedRequestError({ + message: 'Failed service account authorization for the given organization' + }); + } +} \ No newline at end of file diff --git a/backend/src/validation/serviceTokenData.ts b/backend/src/validation/serviceTokenData.ts new file mode 100644 index 000000000..8713e000f --- /dev/null +++ b/backend/src/validation/serviceTokenData.ts @@ -0,0 +1,182 @@ +import { Types } from 'mongoose'; +import { + ISecret, + IServiceTokenData, + ServiceTokenData, + IUser, + User, + IServiceAccount, + ServiceAccount, +} from '../models'; +import { + UnauthorizedRequestError, + ServiceTokenDataNotFoundError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; +import { validateUserClientForWorkspace } from './user'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; + +/** + * Validate authenticated clients for service token with id [serviceTokenId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.serviceTokenData - id of service token to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + */ +export const validateClientForServiceTokenData = async ({ + authData, + serviceTokenDataId, + acceptedRoles +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + serviceTokenDataId: Types.ObjectId; + acceptedRoles: Array<'admin' | 'member'>; +}) => { + const serviceTokenData = await ServiceTokenData + .findById(serviceTokenDataId) + .select('+encryptedKey +iv +tag') + .populate<{ user: IUser }>('user'); + + if (!serviceTokenData) throw ServiceTokenDataNotFoundError({ + message: 'Failed to find service token data' + }); + + if (authData.authMode === AUTH_MODE_JWT && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: serviceTokenData.workspace, + acceptedRoles + }); + + return serviceTokenData; + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId: serviceTokenData.workspace + }); + + return serviceTokenData; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for service token data' + }); + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId: serviceTokenData.workspace, + acceptedRoles + }); + + return serviceTokenData; + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for service token data' + }); +} + +/** + * Validate that service token (client) can access workspace + * with id [workspaceId] and its environment [environment] with required permissions + * [requiredPermissions] + * @param {Object} obj + * @param {ServiceTokenData} obj.serviceTokenData - service token client + * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against + * @param {String} environment - (optional) environment in workspace to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateServiceTokenDataClientForWorkspace = async ({ + serviceTokenData, + workspaceId, + environment, + requiredPermissions +}: { + serviceTokenData: IServiceTokenData; + workspaceId: Types.ObjectId; + environment?: string; + requiredPermissions?: string[]; +}) => { + if (!serviceTokenData.workspace.equals(workspaceId)) { + // case: invalid workspaceId passed + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for the given workspace' + }); + } + + if (environment) { + // case: environment is specified + + if (serviceTokenData.environment !== environment) { + // case: invalid environment passed + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for the given workspace environment' + }); + } + + requiredPermissions?.forEach((permission) => { + if (!serviceTokenData.permissions.includes(permission)) { + throw UnauthorizedRequestError({ + message: `Failed service token authorization for the given workspace environment action: ${permission}` + }); + } + }); + } +} + +/** + * Validate that service token (client) can access secrets + * with required permissions [requiredPermissions] + * @param {Object} obj + * @param {ServiceTokenData} obj.serviceTokenData - service token client + * @param {Secret[]} secrets - secrets to validate against + * @param {string[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateServiceTokenDataClientForSecrets = async ({ + serviceTokenData, + secrets, + requiredPermissions +}: { + serviceTokenData: IServiceTokenData; + secrets: ISecret[]; + requiredPermissions?: string[]; +}) => { + + secrets.forEach((secret: ISecret) => { + if (!serviceTokenData.workspace.equals(secret.workspace)) { + // case: invalid workspaceId passed + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for the given workspace' + }); + } + + if (serviceTokenData.environment !== secret.environment) { + // case: invalid environment passed + throw UnauthorizedRequestError({ + message: 'Failed service token authorization for the given workspace environment' + }); + } + + requiredPermissions?.forEach((permission) => { + if (!serviceTokenData.permissions.includes(permission)) { + throw UnauthorizedRequestError({ + message: `Failed service token authorization for the given workspace environment action: ${permission}` + }); + } + }); + }); +} \ No newline at end of file diff --git a/backend/src/validation/user.ts b/backend/src/validation/user.ts new file mode 100644 index 000000000..4c412e52f --- /dev/null +++ b/backend/src/validation/user.ts @@ -0,0 +1,227 @@ +import fs from 'fs'; +import path from 'path'; +import { Types } from 'mongoose'; +import { + IUser, + ISecret, + IServiceAccount, + Membership, + IOrganization, +} from '../models'; +import { validateMembership } from '../helpers/membership'; +import _ from 'lodash'; +import { BadRequestError, UnauthorizedRequestError, ValidationError } from '../utils/errors'; +import { + validateMembershipOrg +} from '../helpers/membershipOrg'; +import { + PERMISSION_READ_SECRETS, + PERMISSION_WRITE_SECRETS +} from '../variables'; + +/** + * Validate that email [email] is not disposable + * @param email - email to validate + */ +export const validateUserEmail = (email: string) => { + const emailDomain = email.split('@')[1]; + const disposableEmails = fs.readFileSync( + path.resolve(__dirname, '../data/' + 'disposable_emails.txt'), + 'utf8' + ).split('\n'); + + if (disposableEmails.includes(emailDomain)) throw ValidationError({ + message: 'Failed to validate email as non-disposable' + }); +} + +/** + * Validate that user (client) can access workspace + * with id [workspaceId] and its environment [environment] with required permissions + * [requiredPermissions] + * @param {Object} obj + * @param {User} obj.user - user client + * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against + * @param {String} environment - (optional) environment in workspace to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateUserClientForWorkspace = async ({ + user, + workspaceId, + environment, + acceptedRoles, + requiredPermissions +}: { + user: IUser; + workspaceId: Types.ObjectId; + environment?: string; + acceptedRoles: Array<'admin' | 'member'>; + requiredPermissions?: string[]; +}) => { + + // validate user membership in workspace + const membership = await validateMembership({ + userId: user._id, + workspaceId, + acceptedRoles + }); + + let runningIsDisallowed = false; + requiredPermissions?.forEach((requiredPermission: string) => { + switch (requiredPermission) { + case PERMISSION_READ_SECRETS: + runningIsDisallowed = _.some(membership.deniedPermissions, { environmentSlug: environment, ability: PERMISSION_READ_SECRETS }); + break; + case PERMISSION_WRITE_SECRETS: + runningIsDisallowed = _.some(membership.deniedPermissions, { environmentSlug: environment, ability: PERMISSION_WRITE_SECRETS }); + break; + default: + break; + } + + if (runningIsDisallowed) { + throw UnauthorizedRequestError({ + message: `Failed permissions authorization for workspace environment action : ${requiredPermission}` + }); + } + }); + + return membership; +} + +/** + * Validate that user (client) can access secret [secret] + * with required permissions [requiredPermissions] + * @param {Object} obj + * @param {User} obj.user - user client + * @param {Secret[]} obj.secrets - secrets to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateUserClientForSecret = async ({ + user, + secret, + acceptedRoles, + requiredPermissions +}: { + user: IUser; + secret: ISecret; + acceptedRoles?: Array<'admin' | 'member'>; + requiredPermissions?: string[]; +}) => { + const membership = await validateMembership({ + userId: user._id, + workspaceId: secret.workspace, + acceptedRoles + }); + + if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) { + const isDisallowed = _.some(membership.deniedPermissions, { environmentSlug: secret.environment, ability: PERMISSION_WRITE_SECRETS }); + + if (isDisallowed) { + throw UnauthorizedRequestError({ + message: 'You do not have the required permissions to perform this action' + }); + } + } +} + +/** + * Validate that user (client) can access secrets [secrets] + * with required permissions [requiredPermissions] + * @param {Object} obj + * @param {User} obj.user - user client + * @param {Secret[]} obj.secrets - secrets to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateUserClientForSecrets = async ({ + user, + secrets, + requiredPermissions +}: { + user: IUser; + secrets: ISecret[]; + requiredPermissions?: string[]; +}) => { + + // TODO: add acceptedRoles? + + const userMemberships = await Membership.find({ user: user._id }) + const userMembershipById = _.keyBy(userMemberships, 'workspace'); + const workspaceIdsSet = new Set(userMemberships.map((m) => m.workspace.toString())); + + // for each secret check if the secret belongs to a workspace the user is a member of + secrets.forEach((secret: ISecret) => { + if (!workspaceIdsSet.has(secret.workspace.toString())) { + throw BadRequestError({ + message: 'Failed authorization for the secret' + }); + } + + if (requiredPermissions?.includes(PERMISSION_WRITE_SECRETS)) { + const deniedMembershipPermissions = userMembershipById[secret.workspace.toString()].deniedPermissions; + const isDisallowed = _.some(deniedMembershipPermissions, { environmentSlug: secret.environment, ability: PERMISSION_WRITE_SECRETS }); + + if (isDisallowed) { + throw UnauthorizedRequestError({ + message: 'You do not have the required permissions to perform this action' + }); + } + } + }); +} + +/** + * Validate that user (client) can access service account [serviceAccount] + * with required permissions [requiredPermissions] + * @param {Object} obj + * @param {User} obj.user - user client + * @param {ServiceAccount} obj.serviceAccount - service account to validate against + * @param {String[]} requiredPermissions - required permissions as part of the endpoint + */ +export const validateUserClientForServiceAccount = async ({ + user, + serviceAccount, + requiredPermissions +}: { + user: IUser; + serviceAccount: IServiceAccount; + requiredPermissions?: string[]; +}) => { + if (!serviceAccount.user.equals(user._id)) { + // case: user who created service account is not the + // same user that is on the request + await validateMembershipOrg({ + userId: user._id, + organizationId: serviceAccount.organization, + acceptedRoles: [], + acceptedStatuses: [] + }); + } +} + +/** + * Validate that user (client) can access organization [organization] + * @param {Object} obj + * @param {User} obj.user - user client + * @param {Organization} obj.organization - organization to validate against + */ +export const validateUserClientForOrganization = async ({ + user, + organization, + acceptedRoles, + acceptedStatuses +}: { + user: IUser; + organization: IOrganization; + acceptedRoles: Array<'owner' | 'admin' | 'member'>; + acceptedStatuses: Array<'invited' | 'accepted'>; +}) => { + const membershipOrg = await validateMembershipOrg({ + userId: user._id, + organizationId: organization._id, + acceptedRoles, + acceptedStatuses + }); + + return membershipOrg; +} \ No newline at end of file diff --git a/backend/src/validation/workspace.ts b/backend/src/validation/workspace.ts new file mode 100644 index 000000000..28c4a20ea --- /dev/null +++ b/backend/src/validation/workspace.ts @@ -0,0 +1,135 @@ +import { Types } from 'mongoose'; +import { + IUser, + IServiceAccount, + IServiceTokenData, + Workspace, + User, + ServiceAccount, + ServiceTokenData, + SecretBlindIndexData +} from '../models'; +import { validateServiceAccountClientForWorkspace } from './serviceAccount'; +import { validateUserClientForWorkspace } from './user'; +import { validateServiceTokenDataClientForWorkspace } from './serviceTokenData'; +import { + BadRequestError, + UnauthorizedRequestError, + WorkspaceNotFoundError +} from '../utils/errors'; +import { + AUTH_MODE_JWT, + AUTH_MODE_SERVICE_ACCOUNT, + AUTH_MODE_SERVICE_TOKEN, + AUTH_MODE_API_KEY +} from '../variables'; +import { BotService } from '../services'; + +/** + * Validate authenticated clients for workspace with id [workspaceId] based + * on any known permissions. + * @param {Object} obj + * @param {Object} obj.authData - authenticated client details + * @param {Types.ObjectId} obj.workspaceId - id of workspace to validate against + * @param {String} obj.environment - (optional) environment in workspace to validate against + * @param {Array<'admin' | 'member'>} obj.acceptedRoles - accepted workspace roles + * @param {String[]} obj.requiredPermissions - required permissions as part of the endpoint + */ +export const validateClientForWorkspace = async ({ + authData, + workspaceId, + environment, + acceptedRoles, + requiredPermissions, + requireBlindIndicesEnabled, + requireE2EEOff +}: { + authData: { + authMode: string; + authPayload: IUser | IServiceAccount | IServiceTokenData; + }; + workspaceId: Types.ObjectId; + environment?: string; + acceptedRoles: Array<'admin' | 'member'>; + requiredPermissions?: string[]; + requireBlindIndicesEnabled: boolean; + requireE2EEOff: boolean; +}) => { + const workspace = await Workspace.findById(workspaceId); + + if (!workspace) throw WorkspaceNotFoundError({ + message: 'Failed to find workspace' + }); + + if (requireBlindIndicesEnabled) { + // case: blind indices are not enabled for secrets in this workspace + // (i.e. workspace was created before blind indices were introduced + // and no admin has enabled it) + + const secretBlindIndexData = await SecretBlindIndexData.exists({ + workspace: new Types.ObjectId(workspaceId) + }); + + if (!secretBlindIndexData) throw UnauthorizedRequestError({ + message: 'Failed workspace authorization due to blind indices not being enabled' + }); + } + + if (requireE2EEOff) { + const isWorkspaceE2EE = await BotService.getIsWorkspaceE2EE(workspaceId); + + if (isWorkspaceE2EE) throw BadRequestError({ + 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({ + user: authData.authPayload, + workspaceId, + environment, + acceptedRoles, + requiredPermissions + }); + + return ({ membership, workspace }); + } + + if (authData.authMode === AUTH_MODE_SERVICE_ACCOUNT && authData.authPayload instanceof ServiceAccount) { + await validateServiceAccountClientForWorkspace({ + serviceAccount: authData.authPayload, + workspaceId, + environment, + requiredPermissions + }); + + return {}; + } + + if (authData.authMode === AUTH_MODE_SERVICE_TOKEN && authData.authPayload instanceof ServiceTokenData) { + await validateServiceTokenDataClientForWorkspace({ + serviceTokenData: authData.authPayload, + workspaceId, + environment, + requiredPermissions + }); + + return {}; + } + + if (authData.authMode === AUTH_MODE_API_KEY && authData.authPayload instanceof User) { + const membership = await validateUserClientForWorkspace({ + user: authData.authPayload, + workspaceId, + environment, + acceptedRoles, + requiredPermissions + }); + + return ({ membership, workspace }); + } + + throw UnauthorizedRequestError({ + message: 'Failed client authorization for workspace' + }); +} diff --git a/backend/src/variables/action.ts b/backend/src/variables/action.ts index 682b357a7..9d4fb18d9 100644 --- a/backend/src/variables/action.ts +++ b/backend/src/variables/action.ts @@ -1,15 +1,6 @@ -const ACTION_LOGIN = 'login'; -const ACTION_LOGOUT = 'logout'; -const ACTION_ADD_SECRETS = 'addSecrets'; -const ACTION_DELETE_SECRETS = 'deleteSecrets'; -const ACTION_UPDATE_SECRETS = 'updateSecrets'; -const ACTION_READ_SECRETS = 'readSecrets'; - -export { - ACTION_LOGIN, - ACTION_LOGOUT, - ACTION_ADD_SECRETS, - ACTION_DELETE_SECRETS, - ACTION_UPDATE_SECRETS, - ACTION_READ_SECRETS -} \ No newline at end of file +export const ACTION_LOGIN = 'login'; +export const ACTION_LOGOUT = 'logout'; +export const ACTION_ADD_SECRETS = 'addSecrets'; +export const ACTION_DELETE_SECRETS = 'deleteSecrets'; +export const ACTION_UPDATE_SECRETS = 'updateSecrets'; +export const ACTION_READ_SECRETS = 'readSecrets'; \ No newline at end of file diff --git a/backend/src/variables/authentication.ts b/backend/src/variables/authentication.ts new file mode 100644 index 000000000..ac19d2756 --- /dev/null +++ b/backend/src/variables/authentication.ts @@ -0,0 +1,4 @@ +export const AUTH_MODE_JWT = 'jwt'; +export const AUTH_MODE_SERVICE_ACCOUNT = 'serviceAccount'; +export const AUTH_MODE_SERVICE_TOKEN = 'serviceToken'; +export const AUTH_MODE_API_KEY = 'apiKey'; // TODO: deprecate \ No newline at end of file diff --git a/backend/src/variables/crypto.ts b/backend/src/variables/crypto.ts new file mode 100644 index 000000000..bd2ae110c --- /dev/null +++ b/backend/src/variables/crypto.ts @@ -0,0 +1,7 @@ +export const ALGORITHM_AES_256_GCM = 'aes-256-gcm'; +export const NONCE_BYTES_SIZE = 12; +export const BLOCK_SIZE_BYTES_16 = 16; + +export const ENCODING_SCHEME_UTF8 = 'utf8'; +export const ENCODING_SCHEME_HEX = 'hex'; +export const ENCODING_SCHEME_BASE64 = 'base64'; \ No newline at end of file diff --git a/backend/src/variables/environment.ts b/backend/src/variables/environment.ts index 44d7cdbb2..b068b3d36 100644 --- a/backend/src/variables/environment.ts +++ b/backend/src/variables/environment.ts @@ -1,14 +1,6 @@ // environments -const ENV_DEV = 'dev'; -const ENV_TESTING = 'test'; -const ENV_STAGING = 'staging'; -const ENV_PROD = 'prod'; -const ENV_SET = new Set([ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD]); - -export { - ENV_DEV, - ENV_TESTING, - ENV_STAGING, - ENV_PROD, - ENV_SET -} \ No newline at end of file +export const ENV_DEV = 'dev'; +export const ENV_TESTING = 'test'; +export const ENV_STAGING = 'staging'; +export const ENV_PROD = 'prod'; +export const ENV_SET = new Set([ENV_DEV, ENV_TESTING, ENV_STAGING, ENV_PROD]); \ No newline at end of file diff --git a/backend/src/variables/event.ts b/backend/src/variables/event.ts index 4477e8e02..1c55eb3ec 100644 --- a/backend/src/variables/event.ts +++ b/backend/src/variables/event.ts @@ -1,7 +1,2 @@ -const EVENT_PUSH_SECRETS = 'pushSecrets'; -const EVENT_PULL_SECRETS = 'pullSecrets'; - -export { - EVENT_PUSH_SECRETS, - EVENT_PULL_SECRETS -} \ No newline at end of file +export const EVENT_PUSH_SECRETS = 'pushSecrets'; +export const EVENT_PULL_SECRETS = 'pullSecrets'; \ No newline at end of file diff --git a/backend/src/variables/index.ts b/backend/src/variables/index.ts index b71044cba..281145a99 100644 --- a/backend/src/variables/index.ts +++ b/backend/src/variables/index.ts @@ -1,128 +1,13 @@ -import { - ENV_DEV, - ENV_TESTING, - ENV_STAGING, - ENV_PROD, - ENV_SET, -} from "./environment"; -import { - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_TRAVISCI, - INTEGRATION_SET, - INTEGRATION_OAUTH2, - INTEGRATION_AZURE_TOKEN_URL, - INTEGRATION_HEROKU_TOKEN_URL, - INTEGRATION_VERCEL_TOKEN_URL, - INTEGRATION_NETLIFY_TOKEN_URL, - INTEGRATION_GITHUB_TOKEN_URL, - INTEGRATION_GITLAB_TOKEN_URL, - INTEGRATION_HEROKU_API_URL, - INTEGRATION_GITLAB_API_URL, - INTEGRATION_VERCEL_API_URL, - INTEGRATION_NETLIFY_API_URL, - INTEGRATION_RENDER_API_URL, - INTEGRATION_FLYIO_API_URL, - INTEGRATION_CIRCLECI_API_URL, - INTEGRATION_TRAVISCI_API_URL, - getIntegrationOptions -} from "./integration"; -import { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED } from "./organization"; -import { SECRET_SHARED, SECRET_PERSONAL } from "./secret"; -import { EVENT_PUSH_SECRETS, EVENT_PULL_SECRETS } from "./event"; -import { - ACTION_LOGIN, - ACTION_LOGOUT, - ACTION_ADD_SECRETS, - ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS, - ACTION_READ_SECRETS -} from './action'; -import { - SMTP_HOST_SENDGRID, - SMTP_HOST_MAILGUN, - SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL -} from './smtp'; -import { PLAN_STARTER, PLAN_PRO } from './stripe'; -import { - MFA_METHOD_EMAIL -} from './user'; -import { - TOKEN_EMAIL_CONFIRMATION, - TOKEN_EMAIL_MFA, - TOKEN_EMAIL_ORG_INVITATION, - TOKEN_EMAIL_PASSWORD_RESET -} from './token'; - -export { - OWNER, - ADMIN, - MEMBER, - INVITED, - ACCEPTED, - SECRET_SHARED, - SECRET_PERSONAL, - ENV_DEV, - ENV_TESTING, - ENV_STAGING, - ENV_PROD, - ENV_SET, - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_TRAVISCI, - INTEGRATION_SET, - INTEGRATION_OAUTH2, - INTEGRATION_AZURE_TOKEN_URL, - INTEGRATION_HEROKU_TOKEN_URL, - INTEGRATION_VERCEL_TOKEN_URL, - INTEGRATION_NETLIFY_TOKEN_URL, - INTEGRATION_GITHUB_TOKEN_URL, - INTEGRATION_GITLAB_TOKEN_URL, - INTEGRATION_HEROKU_API_URL, - INTEGRATION_GITLAB_API_URL, - INTEGRATION_VERCEL_API_URL, - INTEGRATION_NETLIFY_API_URL, - INTEGRATION_RENDER_API_URL, - INTEGRATION_FLYIO_API_URL, - INTEGRATION_CIRCLECI_API_URL, - INTEGRATION_TRAVISCI_API_URL, - EVENT_PUSH_SECRETS, - EVENT_PULL_SECRETS, - ACTION_LOGIN, - ACTION_LOGOUT, - ACTION_ADD_SECRETS, - ACTION_UPDATE_SECRETS, - ACTION_DELETE_SECRETS, - ACTION_READ_SECRETS, - getIntegrationOptions, - SMTP_HOST_SENDGRID, - SMTP_HOST_MAILGUN, - SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL, - PLAN_STARTER, - PLAN_PRO, - MFA_METHOD_EMAIL, - TOKEN_EMAIL_CONFIRMATION, - TOKEN_EMAIL_MFA, - TOKEN_EMAIL_ORG_INVITATION, - TOKEN_EMAIL_PASSWORD_RESET -}; +export * from './action'; +export * from './authentication'; +export * from './crypto'; +export * from './environment'; +export * from './event'; +export * from './integration'; +export * from './organization'; +export * from './permission'; +export * from './secret'; +export * from './smtp'; +export * from './stripe'; +export * from './token'; +export * from './user'; diff --git a/backend/src/variables/integration.ts b/backend/src/variables/integration.ts index 52bfcc614..26e9f2544 100644 --- a/backend/src/variables/integration.ts +++ b/backend/src/variables/integration.ts @@ -8,19 +8,23 @@ import { } from '../config'; // integrations -const INTEGRATION_AZURE_KEY_VAULT = 'azure-key-vault'; -const INTEGRATION_AWS_PARAMETER_STORE = 'aws-parameter-store'; -const INTEGRATION_AWS_SECRET_MANAGER = 'aws-secret-manager'; -const INTEGRATION_HEROKU = "heroku"; -const INTEGRATION_VERCEL = "vercel"; -const INTEGRATION_NETLIFY = "netlify"; -const INTEGRATION_GITHUB = "github"; -const INTEGRATION_GITLAB = "gitlab"; -const INTEGRATION_RENDER = "render"; -const INTEGRATION_FLYIO = "flyio"; -const INTEGRATION_CIRCLECI = "circleci"; -const INTEGRATION_TRAVISCI = "travisci"; -const INTEGRATION_SET = new Set([ +export const INTEGRATION_AZURE_KEY_VAULT = 'azure-key-vault'; +export const INTEGRATION_AWS_PARAMETER_STORE = 'aws-parameter-store'; +export const INTEGRATION_AWS_SECRET_MANAGER = 'aws-secret-manager'; +export const INTEGRATION_HEROKU = "heroku"; +export const INTEGRATION_VERCEL = "vercel"; +export const INTEGRATION_NETLIFY = "netlify"; +export const INTEGRATION_GITHUB = "github"; +export const INTEGRATION_GITLAB = "gitlab"; +export const INTEGRATION_RENDER = "render"; +export const INTEGRATION_RAILWAY = "railway"; +export const INTEGRATION_FLYIO = "flyio"; +export const INTEGRATION_CIRCLECI = "circleci"; +export const INTEGRATION_TRAVISCI = "travisci"; +export const INTEGRATION_SUPABASE = 'supabase'; +export const INTEGRATION_CHECKLY = 'checkly'; +export const INTEGRATION_HASHICORP_VAULT = 'hashicorp-vault'; +export const INTEGRATION_SET = new Set([ INTEGRATION_AZURE_KEY_VAULT, INTEGRATION_HEROKU, INTEGRATION_VERCEL, @@ -31,32 +35,38 @@ const INTEGRATION_SET = new Set([ INTEGRATION_FLYIO, INTEGRATION_CIRCLECI, INTEGRATION_TRAVISCI, + INTEGRATION_SUPABASE, + INTEGRATION_CHECKLY, + INTEGRATION_HASHICORP_VAULT ]); // integration types -const INTEGRATION_OAUTH2 = "oauth2"; +export const INTEGRATION_OAUTH2 = "oauth2"; // integration oauth endpoints -const INTEGRATION_AZURE_TOKEN_URL = `https://login.microsoftonline.com/common/oauth2/v2.0/token`; -const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token'; -const INTEGRATION_VERCEL_TOKEN_URL = +export const INTEGRATION_AZURE_TOKEN_URL = `https://login.microsoftonline.com/common/oauth2/v2.0/token`; +export const INTEGRATION_HEROKU_TOKEN_URL = 'https://id.heroku.com/oauth/token'; +export const INTEGRATION_VERCEL_TOKEN_URL = "https://api.vercel.com/v2/oauth/access_token"; -const INTEGRATION_NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/token"; -const INTEGRATION_GITHUB_TOKEN_URL = +export const INTEGRATION_NETLIFY_TOKEN_URL = "https://api.netlify.com/oauth/token"; +export const INTEGRATION_GITHUB_TOKEN_URL = "https://github.com/login/oauth/access_token"; -const INTEGRATION_GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token"; +export const INTEGRATION_GITLAB_TOKEN_URL = "https://gitlab.com/oauth/token"; // integration apps endpoints -const INTEGRATION_HEROKU_API_URL = "https://api.heroku.com"; -const INTEGRATION_GITLAB_API_URL = "https://gitlab.com/api"; -const INTEGRATION_VERCEL_API_URL = "https://api.vercel.com"; -const INTEGRATION_NETLIFY_API_URL = "https://api.netlify.com"; -const INTEGRATION_RENDER_API_URL = "https://api.render.com"; -const INTEGRATION_FLYIO_API_URL = "https://api.fly.io/graphql"; -const INTEGRATION_CIRCLECI_API_URL = "https://circleci.com/api"; -const INTEGRATION_TRAVISCI_API_URL = "https://api.travis-ci.com"; +export const INTEGRATION_HEROKU_API_URL = "https://api.heroku.com"; +export const INTEGRATION_GITLAB_API_URL = "https://gitlab.com/api"; +export const INTEGRATION_VERCEL_API_URL = "https://api.vercel.com"; +export const INTEGRATION_NETLIFY_API_URL = "https://api.netlify.com"; +export const INTEGRATION_RENDER_API_URL = "https://api.render.com"; +export const INTEGRATION_RAILWAY_API_URL = "https://backboard.railway.app/graphql/v2"; +export const INTEGRATION_FLYIO_API_URL = "https://api.fly.io/graphql"; +export const INTEGRATION_CIRCLECI_API_URL = "https://circleci.com/api"; +export const INTEGRATION_TRAVISCI_API_URL = "https://api.travis-ci.com"; +export const INTEGRATION_SUPABASE_API_URL = 'https://api.supabase.com'; +export const INTEGRATION_CHECKLY_API_URL = 'https://api.checklyhq.com'; -const getIntegrationOptions = () => { +export const getIntegrationOptions = async () => { const INTEGRATION_OPTIONS = [ { name: 'Heroku', @@ -64,7 +74,7 @@ const getIntegrationOptions = () => { image: 'Heroku.png', isAvailable: true, type: 'oauth', - clientId: getClientIdHeroku(), + clientId: await getClientIdHeroku(), docsLink: '' }, { @@ -74,7 +84,7 @@ const getIntegrationOptions = () => { isAvailable: true, type: 'oauth', clientId: '', - clientSlug: getClientSlugVercel(), + clientSlug: await getClientSlugVercel(), docsLink: '' }, { @@ -83,7 +93,7 @@ const getIntegrationOptions = () => { image: 'Netlify.png', isAvailable: true, type: 'oauth', - clientId: getClientIdNetlify(), + clientId: await getClientIdNetlify(), docsLink: '' }, { @@ -92,7 +102,7 @@ const getIntegrationOptions = () => { image: 'GitHub.png', isAvailable: true, type: 'oauth', - clientId: getClientIdGitHub(), + clientId: await getClientIdGitHub(), docsLink: '' }, { @@ -104,6 +114,15 @@ const getIntegrationOptions = () => { clientId: '', docsLink: '' }, + { + name: 'Railway', + slug: 'railway', + image: 'Railway.png', + isAvailable: true, + type: 'pat', + clientId: '', + docsLink: '' + }, { name: 'Fly.io', slug: 'flyio', @@ -137,7 +156,7 @@ const getIntegrationOptions = () => { image: 'Microsoft Azure.png', isAvailable: true, type: 'oauth', - clientId: getClientIdAzure(), + clientId: await getClientIdAzure(), docsLink: '' }, { @@ -155,7 +174,7 @@ const getIntegrationOptions = () => { image: 'GitLab.png', isAvailable: true, type: 'custom', - clientId: getClientIdGitLab(), + clientId: await getClientIdGitLab(), docsLink: '' }, { @@ -167,6 +186,33 @@ const getIntegrationOptions = () => { clientId: '', docsLink: '' }, + { + name: 'Supabase', + slug: 'supabase', + image: 'Supabase.png', + isAvailable: true, + type: 'pat', + clientId: '', + docsLink: '' + }, + { + name: 'Checkly', + slug: 'checkly', + image: 'Checkly.png', + isAvailable: true, + type: 'pat', + clientId: '', + docsLink: '' + }, + { + name: 'HashiCorp Vault', + slug: 'hashicorp-vault', + image: 'Vault.png', + isAvailable: true, + type: 'pat', + clientId: '', + docsLink: '' + }, { name: 'Google Cloud Platform', slug: 'gcp', @@ -179,37 +225,4 @@ const getIntegrationOptions = () => { ] return INTEGRATION_OPTIONS; -} - - -export { - INTEGRATION_AZURE_KEY_VAULT, - INTEGRATION_AWS_PARAMETER_STORE, - INTEGRATION_AWS_SECRET_MANAGER, - INTEGRATION_HEROKU, - INTEGRATION_VERCEL, - INTEGRATION_NETLIFY, - INTEGRATION_GITHUB, - INTEGRATION_GITLAB, - INTEGRATION_RENDER, - INTEGRATION_FLYIO, - INTEGRATION_CIRCLECI, - INTEGRATION_TRAVISCI, - INTEGRATION_SET, - INTEGRATION_OAUTH2, - INTEGRATION_AZURE_TOKEN_URL, - INTEGRATION_HEROKU_TOKEN_URL, - INTEGRATION_VERCEL_TOKEN_URL, - INTEGRATION_NETLIFY_TOKEN_URL, - INTEGRATION_GITHUB_TOKEN_URL, - INTEGRATION_GITLAB_API_URL, - INTEGRATION_HEROKU_API_URL, - INTEGRATION_GITLAB_TOKEN_URL, - INTEGRATION_VERCEL_API_URL, - INTEGRATION_NETLIFY_API_URL, - INTEGRATION_RENDER_API_URL, - INTEGRATION_FLYIO_API_URL, - INTEGRATION_CIRCLECI_API_URL, - INTEGRATION_TRAVISCI_API_URL, - getIntegrationOptions -}; +} \ No newline at end of file diff --git a/backend/src/variables/organization.ts b/backend/src/variables/organization.ts index 91af2ff25..4f5620236 100644 --- a/backend/src/variables/organization.ts +++ b/backend/src/variables/organization.ts @@ -1,16 +1,10 @@ // membership roles -const OWNER = "owner"; -const ADMIN = "admin"; -const MEMBER = "member"; +export const OWNER = "owner"; +export const ADMIN = "admin"; +export const MEMBER = "member"; // membership statuses -const INVITED = "invited"; - -// membership permissions ability -const ABILITY_READ = "read"; -const ABILITY_WRITE = "write"; +export const INVITED = "invited"; // -- organization -const ACCEPTED = "accepted"; - -export { OWNER, ADMIN, MEMBER, INVITED, ACCEPTED, ABILITY_READ, ABILITY_WRITE }; +export const ACCEPTED = "accepted"; \ No newline at end of file diff --git a/backend/src/variables/permission.ts b/backend/src/variables/permission.ts new file mode 100644 index 000000000..98c9ef538 --- /dev/null +++ b/backend/src/variables/permission.ts @@ -0,0 +1,2 @@ +export const PERMISSION_READ_SECRETS = 'read'; +export const PERMISSION_WRITE_SECRETS = 'write'; \ No newline at end of file diff --git a/backend/src/variables/secret.ts b/backend/src/variables/secret.ts index 31cbcf951..571e66b9d 100644 --- a/backend/src/variables/secret.ts +++ b/backend/src/variables/secret.ts @@ -1,8 +1,3 @@ // secrets -const SECRET_SHARED = 'shared'; -const SECRET_PERSONAL = 'personal'; - -export { - SECRET_SHARED, - SECRET_PERSONAL -} \ No newline at end of file +export const SECRET_SHARED = 'shared'; +export const SECRET_PERSONAL = 'personal'; \ No newline at end of file diff --git a/backend/src/variables/smtp.ts b/backend/src/variables/smtp.ts index a88f229bd..f5dd05d0b 100644 --- a/backend/src/variables/smtp.ts +++ b/backend/src/variables/smtp.ts @@ -1,11 +1,5 @@ -const SMTP_HOST_SENDGRID = 'smtp.sendgrid.net'; -const SMTP_HOST_MAILGUN = 'smtp.mailgun.org'; -const SMTP_HOST_SOCKETLABS = 'smtp.socketlabs.com'; -const SMTP_HOST_ZOHOMAIL = 'smtp.zoho.com'; - -export { - SMTP_HOST_SENDGRID, - SMTP_HOST_MAILGUN, - SMTP_HOST_SOCKETLABS, - SMTP_HOST_ZOHOMAIL -} \ No newline at end of file +export const SMTP_HOST_SENDGRID = 'smtp.sendgrid.net'; +export const SMTP_HOST_MAILGUN = 'smtp.mailgun.org'; +export const SMTP_HOST_SOCKETLABS = 'smtp.socketlabs.com'; +export const SMTP_HOST_ZOHOMAIL = 'smtp.zoho.com'; +export const SMTP_HOST_GMAIL = 'smtp.gmail.com'; diff --git a/backend/src/variables/stripe.ts b/backend/src/variables/stripe.ts index ecdbd98ae..7b6ae8fa1 100644 --- a/backend/src/variables/stripe.ts +++ b/backend/src/variables/stripe.ts @@ -1,7 +1,2 @@ -const PLAN_STARTER = 'starter'; -const PLAN_PRO = 'pro'; - -export { - PLAN_STARTER, - PLAN_PRO -} \ No newline at end of file +export const PLAN_STARTER = 'starter'; +export const PLAN_PRO = 'pro'; \ No newline at end of file diff --git a/backend/src/variables/token.ts b/backend/src/variables/token.ts index ecb63990f..2ced95d9c 100644 --- a/backend/src/variables/token.ts +++ b/backend/src/variables/token.ts @@ -1,11 +1,4 @@ -const TOKEN_EMAIL_CONFIRMATION = 'emailConfirmation'; -const TOKEN_EMAIL_MFA = 'emailMfa'; -const TOKEN_EMAIL_ORG_INVITATION = 'organizationInvitation'; -const TOKEN_EMAIL_PASSWORD_RESET = 'passwordReset'; - -export { - TOKEN_EMAIL_CONFIRMATION, - TOKEN_EMAIL_MFA, - TOKEN_EMAIL_ORG_INVITATION, - TOKEN_EMAIL_PASSWORD_RESET -} \ No newline at end of file +export const TOKEN_EMAIL_CONFIRMATION = 'emailConfirmation'; +export const TOKEN_EMAIL_MFA = 'emailMfa'; +export const TOKEN_EMAIL_ORG_INVITATION = 'organizationInvitation'; +export const TOKEN_EMAIL_PASSWORD_RESET = 'passwordReset'; \ No newline at end of file diff --git a/backend/src/variables/user.ts b/backend/src/variables/user.ts index baa27d35d..7e5b53c4b 100644 --- a/backend/src/variables/user.ts +++ b/backend/src/variables/user.ts @@ -1,5 +1 @@ -const MFA_METHOD_EMAIL = 'email'; - -export { - MFA_METHOD_EMAIL -} \ No newline at end of file +export const MFA_METHOD_EMAIL = 'email'; \ No newline at end of file diff --git a/backend/swagger/index.ts b/backend/swagger/index.ts index 195a8198c..051f9d64f 100644 --- a/backend/swagger/index.ts +++ b/backend/swagger/index.ts @@ -220,7 +220,7 @@ const generateOpenAPISpec = async () => { const outputJSONFile = '../spec.json'; const outputYAMLFile = '../docs/spec.yaml'; - const endpointsFiles = ['../src/app.ts']; + const endpointsFiles = ['../src/index.ts']; const spec = await swaggerAutogen(outputJSONFile, endpointsFiles, doc); await fs.writeFile(outputYAMLFile, yaml.dump(spec.data)); diff --git a/backend/test-resources/env-vars.js b/backend/test-resources/env-vars.js index a7542728f..3149a27c9 100644 --- a/backend/test-resources/env-vars.js +++ b/backend/test-resources/env-vars.js @@ -3,3 +3,10 @@ process.env.MONGO_URL = 'mongodb://test:test1234@localhost:27018/?authSource=admin'; process.env.MONGO_USERNAME = 'test'; process.env.MONGO_PASSWORD = 'test1234'; +process.env.NODE_ENV = 'test'; +process.env.JWT_SIGNUP_SECRET= "38ea90fb7998b92176080f457d890392" +process.env.JWT_REFRESH_SECRET= "7764c7bbf3928ad501591a3e005eb364" +process.env.JWT_AUTH_SECRET= "5239fea3a4720c0e524f814a540e14a2" +process.env.JWT_SERVICE_SECRET= "8509fb8b90c9b53e9e61d1e35826dcb5" +process.env.ENCRYPTION_KEY="e05f54dffd58b5ab9b09e4c6fca7aff7" +process.env.ROOT_ENCRYPTION_KEY="MJA3DWJXjHiL6xjkUI2QCQuy/D+/SAbRNU1+rEo9gvQ=" diff --git a/backend/tests/data/batch-create-secrets-with-some-missing-params.json b/backend/tests/data/batch-create-secrets-with-some-missing-params.json new file mode 100644 index 000000000..40d07827c --- /dev/null +++ b/backend/tests/data/batch-create-secrets-with-some-missing-params.json @@ -0,0 +1,51 @@ +[ + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyCiphertext": "eaX9a2g=", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueCiphertext": "cw==", + "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentCiphertext": "", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + }, + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + }, + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueCiphertext": "cw==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentCiphertext": "", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + } +] \ No newline at end of file diff --git a/backend/tests/data/batch-secrets-no-override.json b/backend/tests/data/batch-secrets-no-override.json new file mode 100644 index 000000000..7236c907a --- /dev/null +++ b/backend/tests/data/batch-secrets-no-override.json @@ -0,0 +1,56 @@ +[ + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyCiphertext": "eaX9a2g=", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueCiphertext": "cw==", + "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentCiphertext": "", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + }, + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyCiphertext": "eaX9a2g=", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueCiphertext": "cw==", + "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentCiphertext": "", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + }, + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "tags": [], + "environment": "dev", + "secretKeyCiphertext": "eaX9a2g=", + "secretKeyIV": "YJ4adgI/wEHifGdtT9reaA==", + "secretKeyTag": "dP73x3wrq7pqxzAHo+bfPA==", + "secretValueCiphertext": "cw==", + "secretValueIV": "7ksYWWZ3+9rzLG5NpEbEgg==", + "secretValueTag": "H0YQ8vrhiVJ0XSW4nBJdQA==", + "secretCommentCiphertext": "", + "secretCommentIV": "yXhMdLdA9q7Vaw4UUaeBYA==", + "secretCommentTag": "qMj7SHESM5Jn+C2qpbw2pA==" + } + } +] \ No newline at end of file diff --git a/backend/tests/data/batch-secrets-with-overrides.json b/backend/tests/data/batch-secrets-with-overrides.json new file mode 100644 index 000000000..6173289aa --- /dev/null +++ b/backend/tests/data/batch-secrets-with-overrides.json @@ -0,0 +1,38 @@ +[ + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "shared", + "environment": "dev", + "secretKeyCiphertext": "IVMtGWE=", + "secretKeyIV": "BDsG7/ylk7mT8MrIMn0e7w==", + "secretKeyTag": "1ujy08fctmZ1xTXMYr23UQ==", + "secretValueCiphertext": "I9psUg==", + "secretValueIV": "W+DJETpCerHkFv8AR9Fv4w==", + "secretValueTag": "yODOeN3HBr/usly4VSMt9w==", + "secretCommentCiphertext": "", + "secretCommentIV": "QET7oX2ZiuLDSzwrkeL2Ig==", + "secretCommentTag": "6P3xeA9eO+3Wp66ROHXgfg==" + } + }, + { + "method": "POST", + "secret": { + "workspace": "63cefb15c8d3175601cfa989", + "type": "personal", + "user": "63cefa6ec8d3175601cfa980", + "tags": [], + "environment": "dev", + "secretKeyCiphertext": "Q7lyRO8=", + "secretKeyIV": "yz8koc3d63ywJMiGXpCNSw==", + "secretKeyTag": "j2bMQ2d4sDZKA0OaKM5SXA==", + "secretValueCiphertext": "X4kaiShmtGZt", + "secretValueIV": "p/GdbksLVveNLsV3vz5GLA==", + "secretValueTag": "//dhRL+pagecavHJCtMPWg==", + "secretCommentCiphertext": "", + "secretCommentIV": "7eYJzuilvjQPutqrqbd2MQ==", + "secretCommentTag": "LpPv9K0Hhd5noE39Zu9U+w==" + } + } +] \ No newline at end of file diff --git a/backend/tests/helper/helper.ts b/backend/tests/helper/helper.ts new file mode 100644 index 000000000..d72a101c1 --- /dev/null +++ b/backend/tests/helper/helper.ts @@ -0,0 +1,98 @@ +// Helper functions for integration tests + +import axiosInstance from "../../src/config/request"; +import { Secret } from "../../src/models"; +import { testUserEmail, testUserPassword } from "../../src/utils/addDevelopmentUser"; +// eslint-disable-next-line @typescript-eslint/no-var-requires +const crypto = require('crypto') +// eslint-disable-next-line @typescript-eslint/no-var-requires +const jsrp = require('jsrp'); +// eslint-disable-next-line @typescript-eslint/no-var-requires +const axios = require('axios'); +import { plainTextWorkspaceKey, testWorkspaceId } from "../../src/utils/addDevelopmentUser"; +import { + encryptSymmetric128BitHexKeyUTF8 +} from '../../src/utils/crypto'; + +interface TokenData { + token: string; + publicKey: string; + encryptedPrivateKey: string; + iv: string; + tag: string; +} + +export const getJWTFromTestUser = (): Promise => { + return new Promise((resolve, reject) => { + const client = new jsrp.client(); + const EMAIL = testUserEmail + const PASSWORD = testUserPassword + + client.init({ + username: EMAIL, + password: PASSWORD, + }, async () => { + const clientPublicKey = client.getPublicKey(); + + // POST: /login1 + const reqBody = { + email: EMAIL, + clientPublicKey + } + + + const loginOneRes = await axiosInstance.post('http://localhost:4000/api/v1/auth/login1', reqBody); + const serverPublicKey = loginOneRes.data.serverPublicKey; + const salt = loginOneRes.data.salt; + + client.setSalt(salt); + client.setServerPublicKey(serverPublicKey); + const clientSharedKey = client.getSharedKey(); // shared Key + const clientProof = client.getProof(); // called M1 + + // POST: /login2 + const reqBody2 = { + email: EMAIL, + clientProof + } + + const response2 = await axiosInstance.post('http://localhost:4000/api/v1/auth/login2', reqBody2); + + resolve(response2.data) + }) + }); +} + +export const getServiceTokenFromTestUser = async () => { + const loggedInUserDetails = await getJWTFromTestUser() + const randomBytes = crypto.randomBytes(16).toString('hex'); + const { ciphertext, iv, tag } = encryptSymmetric128BitHexKeyUTF8({ + plaintext: plainTextWorkspaceKey, + key: randomBytes, + }); + + const newServiceToken = await axiosInstance.post('http://localhost:4000/api/v2/service-token/', { + 'name': "test service token", + 'workspaceId': testWorkspaceId, + 'environment': "dev", + 'encryptedKey': ciphertext, + 'iv': iv, + 'tag': tag, + 'expiresIn': Date.now() + 90000, + 'permissions': ["read"] + }, { + headers: { + 'Authorization': `Bearer ${loggedInUserDetails.token}` + } + }); + + return `${newServiceToken.data.serviceToken}.${randomBytes}` +} + +export const deleteAllSecrets = async () => { + await Secret.deleteMany() +} + +export const getAllSecrets = async () => { + return await Secret.find() +} \ No newline at end of file diff --git a/backend/tests/integration-tests/routes/v2/secrets.test.ts b/backend/tests/integration-tests/routes/v2/secrets.test.ts new file mode 100644 index 000000000..700a6e8a2 --- /dev/null +++ b/backend/tests/integration-tests/routes/v2/secrets.test.ts @@ -0,0 +1,408 @@ +// import request from 'supertest' +// import main from '../../../../src/index' +// import { testWorkspaceId } from '../../../../src/utils/addDevelopmentUser'; +// import { deleteAllSecrets, getAllSecrets, getJWTFromTestUser, getServiceTokenFromTestUser } from '../../../helper/helper'; +// // eslint-disable-next-line @typescript-eslint/no-var-requires +// const batchSecretRequestWithNoOverride = require('../../../data/batch-secrets-no-override.json'); +// // eslint-disable-next-line @typescript-eslint/no-var-requires +// const batchSecretRequestWithOverrides = require('../../../data/batch-secrets-with-overrides.json'); + +// // eslint-disable-next-line @typescript-eslint/no-var-requires +// const batchSecretRequestWithBadRequest = require('../../../data/batch-create-secrets-with-some-missing-params.json'); + +// let server: any; +// beforeAll(async () => { +// server = await main; +// }); + +// afterAll(async () => { +// server.close(); +// }); + +// describe("GET /api/v2/secrets", () => { +// describe("Get secrets via JTW", () => { +// test("should create secrets and read secrets via jwt", async () => { +// try { +// // get login details +// const loginResponse = await getJWTFromTestUser() + +// // create creates +// const createSecretsResponse = await request(server) +// .post("/api/v2/secrets/batch") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .send({ +// workspaceId: testWorkspaceId, +// environment: "dev", +// requests: batchSecretRequestWithNoOverride +// }) + +// expect(createSecretsResponse.statusCode).toBe(200) + + +// const getSecrets = await request(server) +// .get("/api/v2/secrets") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .query({ +// workspaceId: testWorkspaceId, +// environment: "dev" +// }) + +// expect(getSecrets.statusCode).toBe(200) +// expect(getSecrets.body).toHaveProperty("secrets") +// expect(getSecrets.body.secrets).toHaveLength(3) +// expect(getSecrets.body.secrets).toBeInstanceOf(Array); + +// getSecrets.body.secrets.forEach((secret: any) => { +// expect(secret).toHaveProperty('_id'); +// expect(secret._id).toBeTruthy(); + +// expect(secret).toHaveProperty('version'); +// expect(secret.version).toBeTruthy(); + +// expect(secret).toHaveProperty('workspace'); +// expect(secret.workspace).toBeTruthy(); + +// expect(secret).toHaveProperty('type'); +// expect(secret.type).toBeTruthy(); + +// expect(secret).toHaveProperty('tags'); +// expect(secret.tags).toHaveLength(0); + +// expect(secret).toHaveProperty('environment'); +// expect(secret.environment).toEqual("dev"); + +// expect(secret).toHaveProperty('secretKeyCiphertext'); +// expect(secret.secretKeyCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyIV'); +// expect(secret.secretKeyIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyTag'); +// expect(secret.secretKeyTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueCiphertext'); +// expect(secret.secretValueCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueIV'); +// expect(secret.secretValueIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueTag'); +// expect(secret.secretValueTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentCiphertext'); +// expect(secret.secretCommentCiphertext).toBeFalsy(); + +// expect(secret).toHaveProperty('secretCommentIV'); +// expect(secret.secretCommentIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentTag'); +// expect(secret.secretCommentTag).toBeTruthy(); + +// expect(secret).toHaveProperty('createdAt'); +// expect(secret.createdAt).toBeTruthy(); + +// expect(secret).toHaveProperty('updatedAt'); +// expect(secret.updatedAt).toBeTruthy(); +// }); +// } finally { +// // clean up +// await deleteAllSecrets() +// } +// }) + +// test("Get secrets via jwt when personal overrides exist", async () => { +// try { +// // get login details +// const loginResponse = await getJWTFromTestUser() + +// // create creates +// const createSecretsResponse = await request(server) +// .post("/api/v2/secrets/batch") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .send({ +// workspaceId: testWorkspaceId, +// environment: "dev", +// requests: batchSecretRequestWithOverrides +// }) + +// expect(createSecretsResponse.statusCode).toBe(200) + +// const getSecrets = await request(server) +// .get("/api/v2/secrets") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .query({ +// workspaceId: testWorkspaceId, +// environment: "dev" +// }) + +// expect(getSecrets.statusCode).toBe(200) +// expect(getSecrets.body).toHaveProperty("secrets") +// expect(getSecrets.body.secrets).toHaveLength(2) +// expect(getSecrets.body.secrets).toBeInstanceOf(Array); + +// getSecrets.body.secrets.forEach((secret: any) => { +// expect(secret).toHaveProperty('_id'); +// expect(secret._id).toBeTruthy(); + +// expect(secret).toHaveProperty('version'); +// expect(secret.version).toBeTruthy(); + +// expect(secret).toHaveProperty('workspace'); +// expect(secret.workspace).toBeTruthy(); + +// expect(secret).toHaveProperty('type'); +// expect(secret.type).toBeTruthy(); + +// expect(secret).toHaveProperty('tags'); +// expect(secret.tags).toHaveLength(0); + +// expect(secret).toHaveProperty('environment'); +// expect(secret.environment).toEqual("dev"); + +// expect(secret).toHaveProperty('secretKeyCiphertext'); +// expect(secret.secretKeyCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyIV'); +// expect(secret.secretKeyIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyTag'); +// expect(secret.secretKeyTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueCiphertext'); +// expect(secret.secretValueCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueIV'); +// expect(secret.secretValueIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueTag'); +// expect(secret.secretValueTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentCiphertext'); +// expect(secret.secretCommentCiphertext).toBeFalsy(); + +// expect(secret).toHaveProperty('secretCommentIV'); +// expect(secret.secretCommentIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentTag'); +// expect(secret.secretCommentTag).toBeTruthy(); + +// expect(secret).toHaveProperty('createdAt'); +// expect(secret.createdAt).toBeTruthy(); + +// expect(secret).toHaveProperty('updatedAt'); +// expect(secret.updatedAt).toBeTruthy(); +// }); +// } finally { +// // clean up +// await deleteAllSecrets() +// } +// }) +// }) + +// describe("fetch secrets via service token", () => { +// test("Get secrets via jwt when personal overrides exist", async () => { +// try { +// // get login details +// const loginResponse = await getJWTFromTestUser() + +// // create creates +// const createSecretsResponse = await request(server) +// .post("/api/v2/secrets/batch") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .send({ +// workspaceId: testWorkspaceId, +// environment: "dev", +// requests: batchSecretRequestWithOverrides +// }) + +// expect(createSecretsResponse.statusCode).toBe(200) + +// // now use the service token to fetch secrets +// const serviceToken = await getServiceTokenFromTestUser() + +// const getSecrets = await request(server) +// .get("/api/v2/secrets") +// .set('Authorization', `Bearer ${serviceToken}`) +// .query({ +// workspaceId: testWorkspaceId, +// environment: "dev" +// }) + +// expect(getSecrets.statusCode).toBe(200) +// expect(getSecrets.body).toHaveProperty("secrets") +// expect(getSecrets.body.secrets).toHaveLength(2) +// expect(getSecrets.body.secrets).toBeInstanceOf(Array); + +// getSecrets.body.secrets.forEach((secret: any) => { +// expect(secret).toHaveProperty('_id'); +// expect(secret._id).toBeTruthy(); + +// expect(secret).toHaveProperty('version'); +// expect(secret.version).toBeTruthy(); + +// expect(secret).toHaveProperty('workspace'); +// expect(secret.workspace).toBeTruthy(); + +// expect(secret).toHaveProperty('type'); +// expect(secret.type).toBeTruthy(); + +// expect(secret).toHaveProperty('tags'); +// expect(secret.tags).toHaveLength(0); + +// expect(secret).toHaveProperty('environment'); +// expect(secret.environment).toEqual("dev"); + +// expect(secret).toHaveProperty('secretKeyCiphertext'); +// expect(secret.secretKeyCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyIV'); +// expect(secret.secretKeyIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyTag'); +// expect(secret.secretKeyTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueCiphertext'); +// expect(secret.secretValueCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueIV'); +// expect(secret.secretValueIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueTag'); +// expect(secret.secretValueTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentCiphertext'); +// expect(secret.secretCommentCiphertext).toBeFalsy(); + +// expect(secret).toHaveProperty('secretCommentIV'); +// expect(secret.secretCommentIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentTag'); +// expect(secret.secretCommentTag).toBeTruthy(); + +// expect(secret).toHaveProperty('createdAt'); +// expect(secret.createdAt).toBeTruthy(); + +// expect(secret).toHaveProperty('updatedAt'); +// expect(secret.updatedAt).toBeTruthy(); +// }); +// } finally { +// // clean up +// await deleteAllSecrets() +// } +// }) + +// test("should create secrets and read secrets via service token when no overrides", async () => { +// try { +// // get login details +// const loginResponse = await getJWTFromTestUser() + +// // create secrets +// const createSecretsResponse = await request(server) +// .post("/api/v2/secrets/batch") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .send({ +// workspaceId: testWorkspaceId, +// environment: "dev", +// requests: batchSecretRequestWithNoOverride +// }) + +// expect(createSecretsResponse.statusCode).toBe(200) + + +// // now use the service token to fetch secrets +// const serviceToken = await getServiceTokenFromTestUser() + +// const getSecrets = await request(server) +// .get("/api/v2/secrets") +// .set('Authorization', `Bearer ${serviceToken}`) +// .query({ +// workspaceId: testWorkspaceId, +// environment: "dev" +// }) + +// expect(getSecrets.statusCode).toBe(200) +// expect(getSecrets.body).toHaveProperty("secrets") +// expect(getSecrets.body.secrets).toHaveLength(3) +// expect(getSecrets.body.secrets).toBeInstanceOf(Array); + +// getSecrets.body.secrets.forEach((secret: any) => { +// expect(secret).toHaveProperty('_id'); +// expect(secret._id).toBeTruthy(); + +// expect(secret).toHaveProperty('version'); +// expect(secret.version).toBeTruthy(); + +// expect(secret).toHaveProperty('workspace'); +// expect(secret.workspace).toBeTruthy(); + +// expect(secret).toHaveProperty('type'); +// expect(secret.type).toBeTruthy(); + +// expect(secret).toHaveProperty('tags'); +// expect(secret.tags).toHaveLength(0); + +// expect(secret).toHaveProperty('environment'); +// expect(secret.environment).toEqual("dev"); + +// expect(secret).toHaveProperty('secretKeyCiphertext'); +// expect(secret.secretKeyCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyIV'); +// expect(secret.secretKeyIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretKeyTag'); +// expect(secret.secretKeyTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueCiphertext'); +// expect(secret.secretValueCiphertext).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueIV'); +// expect(secret.secretValueIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretValueTag'); +// expect(secret.secretValueTag).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentCiphertext'); +// expect(secret.secretCommentCiphertext).toBeFalsy(); + +// expect(secret).toHaveProperty('secretCommentIV'); +// expect(secret.secretCommentIV).toBeTruthy(); + +// expect(secret).toHaveProperty('secretCommentTag'); +// expect(secret.secretCommentTag).toBeTruthy(); + +// expect(secret).toHaveProperty('createdAt'); +// expect(secret.createdAt).toBeTruthy(); + +// expect(secret).toHaveProperty('updatedAt'); +// expect(secret.updatedAt).toBeTruthy(); +// }); +// } finally { +// // clean up +// await deleteAllSecrets() +// } +// }) +// }) + +// describe("create secrets via JWT", () => { +// test("Create secrets via jwt when some requests have missing required parameters", async () => { +// // get login details +// const loginResponse = await getJWTFromTestUser() + +// // create creates +// const createSecretsResponse = await request(server) +// .post("/api/v2/secrets/batch") +// .set('Authorization', `Bearer ${loginResponse.token}`) +// .send({ +// workspaceId: testWorkspaceId, +// environment: "dev", +// requests: batchSecretRequestWithBadRequest +// }) + +// const allSecretsInDB = await getAllSecrets() + +// expect(createSecretsResponse.statusCode).toBe(500) // TODO should be set to 400 +// expect(allSecretsInDB).toHaveLength(0) +// }) +// }) +// }) \ No newline at end of file diff --git a/backend/tests/integration-tests/routes/v2/service-tokens.ts b/backend/tests/integration-tests/routes/v2/service-tokens.ts new file mode 100644 index 000000000..b011db36f --- /dev/null +++ b/backend/tests/integration-tests/routes/v2/service-tokens.ts @@ -0,0 +1,58 @@ +import request from 'supertest' +import main from '../../../../src/index' +import { getServiceTokenFromTestUser } from '../../../helper/helper'; +let server: any; + +beforeAll(async () => { + server = await main; +}); + +afterAll(async () => { + server.close(); +}); + +describe("GET /api/v2/service-token", () => { + describe("Get service token details", () => { + test("should respond create and get the details of a service token", async () => { + // generate a service token + const serviceToken = await getServiceTokenFromTestUser() + + // get the service token details + const serviceTokenDetails = await request(server) + .get("/api/v2/service-token") + .set('Authorization', `Bearer ${serviceToken}`) + + expect(serviceTokenDetails.body).toMatchObject({ + _id: expect.any(String), + name: 'test service token', + workspace: '63cefb15c8d3175601cfa989', + environment: 'dev', + user: { + _id: '63cefa6ec8d3175601cfa980', + email: 'test@localhost.local', + firstName: 'Jake', + lastName: 'Moni', + isMfaEnabled: false, + mfaMethods: expect.any(Array), + devices: [ + { + ip: expect.any(String), + userAgent: expect.any(String), + _id: expect.any(String), + }, + ], + createdAt: expect.any(String), + updatedAt: expect.any(String), + }, + lastUsed: expect.any(String), + expiresAt: expect.any(String), + encryptedKey: expect.any(String), + iv: expect.any(String), + tag: expect.any(String), + permissions: ['read'], + createdAt: expect.any(String), + updatedAt: expect.any(String), + }); + }) + }) +}) \ No newline at end of file diff --git a/backend/tests/utils/crypto.test.ts b/backend/tests/unit-tests/utils/crypto.test.ts similarity index 58% rename from backend/tests/utils/crypto.test.ts rename to backend/tests/unit-tests/utils/crypto.test.ts index aea5f5f26..d50b3057c 100644 --- a/backend/tests/utils/crypto.test.ts +++ b/backend/tests/unit-tests/utils/crypto.test.ts @@ -1,10 +1,8 @@ import { describe, test, expect } from '@jest/globals'; import { decryptAsymmetric, - decryptSymmetric, encryptAsymmetric, - encryptSymmetric -} from '../../src/utils/crypto'; +} from '../../../src/utils/crypto'; describe('Crypto', () => { describe('encryptAsymmetric', () => { @@ -28,14 +26,14 @@ describe('Crypto', () => { test('should throw error if publicKey is undefined', () => { expect(() => { encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric encryption'); + }).toThrowError('invalid encoding'); }); test('should throw error if publicKey is empty string', () => { publicKey = ''; expect(() => { encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric encryption'); + }).toThrowError('bad public key size'); }); }); @@ -47,14 +45,14 @@ describe('Crypto', () => { test('should throw error if privateKey is undefined', () => { expect(() => { encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric encryption'); + }).toThrowError('invalid encoding'); }); test('should throw error if privateKey is empty string', () => { privateKey = ''; expect(() => { encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric encryption'); + }).toThrowError('bad secret key size'); }); }); @@ -66,7 +64,7 @@ describe('Crypto', () => { test('should throw error if plaintext is undefined', () => { expect(() => { encryptAsymmetric({ plaintext, publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric encryption'); + }).toThrowError('expected string'); }); test('should encrypt plaintext containing special characters', () => { @@ -130,7 +128,7 @@ describe('Crypto', () => { publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric decryption'); + }).toThrowError('invalid encoding'); }); test('should throw error if nonce is modified', () => { @@ -149,103 +147,8 @@ describe('Crypto', () => { publicKey, privateKey }); - }).toThrowError('Failed to perform asymmetric decryption'); + }).toThrowError('invalid encoding'); }); }); }); - - describe('encryptSymmetric', () => { - let plaintext: string; - const key = '7e8ee7e5cc667b9c1829783ad31f36f4'; - - test('should encrypt plaintext with the given key', () => { - plaintext = 'secret-message'; - const { ciphertext, iv, tag } = encryptSymmetric({ plaintext, key }); - expect(ciphertext).toBeDefined(); - expect(iv).toBeDefined(); - expect(tag).toBeDefined(); - }); - - test('should throw an error when plaintext is undefined', () => { - const invalidKey = 'invalid-key'; - expect(() => { - encryptSymmetric({ plaintext, key: invalidKey }); - }).toThrowError('Failed to perform symmetric encryption'); - }); - - test('should throw an error when invalid key is provided', () => { - plaintext = 'secret-message'; - const invalidKey = 'invalid-key'; - - expect(() => { - encryptSymmetric({ plaintext, key: invalidKey }); - }).toThrowError('Failed to perform symmetric encryption'); - }); - }); - - describe('decryptSymmetric', () => { - const plaintext = 'secret-message'; - const key = '7e8ee7e5cc667b9c1829783ad31f36f4'; - const { ciphertext, iv, tag } = encryptSymmetric({ plaintext, key }); - - test('should decrypt encrypted plaintext', () => { - const result = decryptSymmetric({ - ciphertext, - iv, - tag, - key - }); - - expect(result).toBeDefined(); - expect(result).toEqual(plaintext); - }); - - test('should fail if ciphertext is modified', () => { - const modifieldCiphertext = 'abcdefghijklmnopqrstuvwxyz'; - expect(() => { - decryptSymmetric({ - ciphertext: modifieldCiphertext, - iv, - tag, - key - }); - }).toThrowError('Failed to perform symmetric decryption'); - }); - - test('should fail if iv is modified', () => { - const modifiedIv = 'abcdefghijklmnopqrstuvwxyz'; - expect(() => { - decryptSymmetric({ - ciphertext, - iv: modifiedIv, - tag, - key - }); - }).toThrowError('Failed to perform symmetric decryption'); - }); - - test('should fail if tag is modified', () => { - const modifiedTag = 'abcdefghijklmnopqrstuvwxyz'; - expect(() => { - decryptSymmetric({ - ciphertext, - iv, - tag: modifiedTag, - key - }); - }).toThrowError('Failed to perform symmetric decryption'); - }); - - test('should throw an error when decryption fails', () => { - const invalidKey = 'invalid-key'; - expect(() => { - decryptSymmetric({ - ciphertext, - iv, - tag, - key: invalidKey - }); - }).toThrowError('Failed to perform symmetric decryption'); - }); - }); }); diff --git a/backend/tests/utils/posthog.test.ts b/backend/tests/unit-tests/utils/posthog.test.ts similarity index 93% rename from backend/tests/utils/posthog.test.ts rename to backend/tests/unit-tests/utils/posthog.test.ts index a380060b0..9f202385c 100644 --- a/backend/tests/utils/posthog.test.ts +++ b/backend/tests/unit-tests/utils/posthog.test.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from '@jest/globals'; -import { getChannelFromUserAgent } from '../../src/utils/posthog'; +import { getChannelFromUserAgent } from '../../../src/utils/posthog'; describe('posthog getChannelFromUserAgent', () => { test("should return 'web' when userAgent includes 'mozilla'", () => { diff --git a/cli/.infisicalignore b/cli/.infisicalignore new file mode 100644 index 000000000..e5dfe29bc --- /dev/null +++ b/cli/.infisicalignore @@ -0,0 +1,3 @@ +bea0ff6e05a4de73a5db625d4ae181a015b50855:frontend/components/utilities/attemptLogin.js:stripe-access-token:147 +bea0ff6e05a4de73a5db625d4ae181a015b50855:backend/src/json/integrations.json:generic-api-key:5 +1961b92340e5d2613acae528b886c842427ce5d0:frontend/components/utilities/attemptLogin.js:stripe-access-token:148 diff --git a/cli/config/allowlist.go b/cli/config/allowlist.go new file mode 100644 index 000000000..373325758 --- /dev/null +++ b/cli/config/allowlist.go @@ -0,0 +1,85 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package config + +import ( + "regexp" + "strings" +) + +// Allowlist allows a rule to be ignored for specific +// regexes, paths, and/or commits +type Allowlist struct { + // Short human readable description of the allowlist. + Description string + + // Regexes is slice of content regular expressions that are allowed to be ignored. + Regexes []*regexp.Regexp + + // RegexTarget + RegexTarget string + + // Paths is a slice of path regular expressions that are allowed to be ignored. + Paths []*regexp.Regexp + + // Commits is a slice of commit SHAs that are allowed to be ignored. + Commits []string + + // StopWords is a slice of stop words that are allowed to be ignored. + // This targets the _secret_, not the content of the regex match like the + // Regexes slice. + StopWords []string +} + +// CommitAllowed returns true if the commit is allowed to be ignored. +func (a *Allowlist) CommitAllowed(c string) bool { + if c == "" { + return false + } + for _, commit := range a.Commits { + if commit == c { + return true + } + } + return false +} + +// PathAllowed returns true if the path is allowed to be ignored. +func (a *Allowlist) PathAllowed(path string) bool { + return anyRegexMatch(path, a.Paths) +} + +// RegexAllowed returns true if the regex is allowed to be ignored. +func (a *Allowlist) RegexAllowed(s string) bool { + return anyRegexMatch(s, a.Regexes) +} + +func (a *Allowlist) ContainsStopWord(s string) bool { + s = strings.ToLower(s) + for _, stopWord := range a.StopWords { + if strings.Contains(s, strings.ToLower(stopWord)) { + return true + } + } + return false +} diff --git a/cli/config/allowlist_test.go b/cli/config/allowlist_test.go new file mode 100644 index 000000000..52766e3cd --- /dev/null +++ b/cli/config/allowlist_test.go @@ -0,0 +1,115 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package config + +import ( + "regexp" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCommitAllowed(t *testing.T) { + tests := []struct { + allowlist Allowlist + commit string + commitAllowed bool + }{ + { + allowlist: Allowlist{ + Commits: []string{"commitA"}, + }, + commit: "commitA", + commitAllowed: true, + }, + { + allowlist: Allowlist{ + Commits: []string{"commitB"}, + }, + commit: "commitA", + commitAllowed: false, + }, + { + allowlist: Allowlist{ + Commits: []string{"commitB"}, + }, + commit: "", + commitAllowed: false, + }, + } + for _, tt := range tests { + assert.Equal(t, tt.commitAllowed, tt.allowlist.CommitAllowed(tt.commit)) + } +} + +func TestRegexAllowed(t *testing.T) { + tests := []struct { + allowlist Allowlist + secret string + regexAllowed bool + }{ + { + allowlist: Allowlist{ + Regexes: []*regexp.Regexp{regexp.MustCompile("matchthis")}, + }, + secret: "a secret: matchthis, done", + regexAllowed: true, + }, + { + allowlist: Allowlist{ + Regexes: []*regexp.Regexp{regexp.MustCompile("matchthis")}, + }, + secret: "a secret", + regexAllowed: false, + }, + } + for _, tt := range tests { + assert.Equal(t, tt.regexAllowed, tt.allowlist.RegexAllowed(tt.secret)) + } +} + +func TestPathAllowed(t *testing.T) { + tests := []struct { + allowlist Allowlist + path string + pathAllowed bool + }{ + { + allowlist: Allowlist{ + Paths: []*regexp.Regexp{regexp.MustCompile("path")}, + }, + path: "a path", + pathAllowed: true, + }, + { + allowlist: Allowlist{ + Paths: []*regexp.Regexp{regexp.MustCompile("path")}, + }, + path: "a ???", + pathAllowed: false, + }, + } + for _, tt := range tests { + assert.Equal(t, tt.pathAllowed, tt.allowlist.PathAllowed(tt.path)) + } +} diff --git a/cli/config/config.go b/cli/config/config.go new file mode 100644 index 000000000..b1ce08e2b --- /dev/null +++ b/cli/config/config.go @@ -0,0 +1,279 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package config + +import ( + _ "embed" + "fmt" + "regexp" + "strings" + + "github.com/rs/zerolog/log" + "github.com/spf13/viper" +) + +//go:embed infisical-scan.toml +var DefaultConfig string + +// use to keep track of how many configs we can extend +// yea I know, globals bad +var extendDepth int + +const maxExtendDepth = 2 + +const DefaultScanConfigFileName = ".infisical-scan.toml" +const DefaultScanConfigEnvName = "INFISICAL_SCAN_CONFIG" +const DefaultInfisicalIgnoreFineName = ".infisicalignore" + +// ViperConfig is the config struct used by the Viper config package +// to parse the config file. This struct does not include regular expressions. +// It is used as an intermediary to convert the Viper config to the Config struct. +type ViperConfig struct { + Description string + Extend Extend + Rules []struct { + ID string + Description string + Entropy float64 + SecretGroup int + Regex string + Keywords []string + Path string + Tags []string + + Allowlist struct { + RegexTarget string + Regexes []string + Paths []string + Commits []string + StopWords []string + } + } + Allowlist struct { + RegexTarget string + Regexes []string + Paths []string + Commits []string + StopWords []string + } +} + +// Config is a configuration struct that contains rules and an allowlist if present. +type Config struct { + Extend Extend + Path string + Description string + Rules map[string]Rule + Allowlist Allowlist + Keywords []string + + // used to keep sarif results consistent + orderedRules []string +} + +// Extend is a struct that allows users to define how they want their +// configuration extended by other configuration files. +type Extend struct { + Path string + URL string + UseDefault bool +} + +func (vc *ViperConfig) Translate() (Config, error) { + var ( + keywords []string + orderedRules []string + ) + rulesMap := make(map[string]Rule) + + for _, r := range vc.Rules { + var allowlistRegexes []*regexp.Regexp + for _, a := range r.Allowlist.Regexes { + allowlistRegexes = append(allowlistRegexes, regexp.MustCompile(a)) + } + var allowlistPaths []*regexp.Regexp + for _, a := range r.Allowlist.Paths { + allowlistPaths = append(allowlistPaths, regexp.MustCompile(a)) + } + + if r.Keywords == nil { + r.Keywords = []string{} + } else { + for _, k := range r.Keywords { + keywords = append(keywords, strings.ToLower(k)) + } + } + + if r.Tags == nil { + r.Tags = []string{} + } + + var configRegex *regexp.Regexp + var configPathRegex *regexp.Regexp + if r.Regex == "" { + configRegex = nil + } else { + configRegex = regexp.MustCompile(r.Regex) + } + if r.Path == "" { + configPathRegex = nil + } else { + configPathRegex = regexp.MustCompile(r.Path) + } + r := Rule{ + Description: r.Description, + RuleID: r.ID, + Regex: configRegex, + Path: configPathRegex, + SecretGroup: r.SecretGroup, + Entropy: r.Entropy, + Tags: r.Tags, + Keywords: r.Keywords, + Allowlist: Allowlist{ + RegexTarget: r.Allowlist.RegexTarget, + Regexes: allowlistRegexes, + Paths: allowlistPaths, + Commits: r.Allowlist.Commits, + StopWords: r.Allowlist.StopWords, + }, + } + orderedRules = append(orderedRules, r.RuleID) + + if r.Regex != nil && r.SecretGroup > r.Regex.NumSubexp() { + return Config{}, fmt.Errorf("%s invalid regex secret group %d, max regex secret group %d", r.Description, r.SecretGroup, r.Regex.NumSubexp()) + } + rulesMap[r.RuleID] = r + } + var allowlistRegexes []*regexp.Regexp + for _, a := range vc.Allowlist.Regexes { + allowlistRegexes = append(allowlistRegexes, regexp.MustCompile(a)) + } + var allowlistPaths []*regexp.Regexp + for _, a := range vc.Allowlist.Paths { + allowlistPaths = append(allowlistPaths, regexp.MustCompile(a)) + } + c := Config{ + Description: vc.Description, + Extend: vc.Extend, + Rules: rulesMap, + Allowlist: Allowlist{ + RegexTarget: vc.Allowlist.RegexTarget, + Regexes: allowlistRegexes, + Paths: allowlistPaths, + Commits: vc.Allowlist.Commits, + StopWords: vc.Allowlist.StopWords, + }, + Keywords: keywords, + orderedRules: orderedRules, + } + + if maxExtendDepth != extendDepth { + // disallow both usedefault and path from being set + if c.Extend.Path != "" && c.Extend.UseDefault { + log.Fatal().Msg("unable to load config due to extend.path and extend.useDefault being set") + } + if c.Extend.UseDefault { + c.extendDefault() + } else if c.Extend.Path != "" { + c.extendPath() + } + + } + + return c, nil +} + +func (c *Config) OrderedRules() []Rule { + var orderedRules []Rule + for _, id := range c.orderedRules { + if _, ok := c.Rules[id]; ok { + orderedRules = append(orderedRules, c.Rules[id]) + } + } + return orderedRules +} + +func (c *Config) extendDefault() { + extendDepth++ + viper.SetConfigType("toml") + if err := viper.ReadConfig(strings.NewReader(DefaultConfig)); err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + defaultViperConfig := ViperConfig{} + if err := viper.Unmarshal(&defaultViperConfig); err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + cfg, err := defaultViperConfig.Translate() + if err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + log.Debug().Msg("extending config with default config") + c.extend(cfg) + +} + +func (c *Config) extendPath() { + extendDepth++ + viper.SetConfigFile(c.Extend.Path) + if err := viper.ReadInConfig(); err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + extensionViperConfig := ViperConfig{} + if err := viper.Unmarshal(&extensionViperConfig); err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + cfg, err := extensionViperConfig.Translate() + if err != nil { + log.Fatal().Msgf("failed to load extended config, err: %s", err) + return + } + log.Debug().Msgf("extending config with %s", c.Extend.Path) + c.extend(cfg) +} + +func (c *Config) extendURL() { + // TODO +} + +func (c *Config) extend(extensionConfig Config) { + for ruleID, rule := range extensionConfig.Rules { + if _, ok := c.Rules[ruleID]; !ok { + log.Trace().Msgf("adding %s to base config", ruleID) + c.Rules[ruleID] = rule + c.Keywords = append(c.Keywords, rule.Keywords...) + } + } + + // append allowlists, not attempting to merge + c.Allowlist.Commits = append(c.Allowlist.Commits, + extensionConfig.Allowlist.Commits...) + c.Allowlist.Paths = append(c.Allowlist.Paths, + extensionConfig.Allowlist.Paths...) + c.Allowlist.Regexes = append(c.Allowlist.Regexes, + extensionConfig.Allowlist.Regexes...) +} diff --git a/cli/config/config_test.go b/cli/config/config_test.go new file mode 100644 index 000000000..e8f4d47b1 --- /dev/null +++ b/cli/config/config_test.go @@ -0,0 +1,170 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package config + +import ( + "fmt" + "regexp" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" +) + +const configPath = "../testdata/config/" + +func TestTranslate(t *testing.T) { + tests := []struct { + cfgName string + cfg Config + wantError error + }{ + { + cfgName: "allow_aws_re", + cfg: Config{ + Rules: map[string]Rule{"aws-access-key": { + Description: "AWS Access Key", + Regex: regexp.MustCompile("(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-access-key", + Allowlist: Allowlist{ + Regexes: []*regexp.Regexp{ + regexp.MustCompile("AKIALALEMEL33243OLIA"), + }, + }, + }, + }, + }, + }, + { + cfgName: "allow_commit", + cfg: Config{ + Rules: map[string]Rule{"aws-access-key": { + Description: "AWS Access Key", + Regex: regexp.MustCompile("(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-access-key", + Allowlist: Allowlist{ + Commits: []string{"allowthiscommit"}, + }, + }, + }, + }, + }, + { + cfgName: "allow_path", + cfg: Config{ + Rules: map[string]Rule{"aws-access-key": { + Description: "AWS Access Key", + Regex: regexp.MustCompile("(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-access-key", + Allowlist: Allowlist{ + Paths: []*regexp.Regexp{ + regexp.MustCompile(".go"), + }, + }, + }, + }, + }, + }, + { + cfgName: "entropy_group", + cfg: Config{ + Rules: map[string]Rule{"discord-api-key": { + Description: "Discord API key", + Regex: regexp.MustCompile(`(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]`), + RuleID: "discord-api-key", + Allowlist: Allowlist{}, + Entropy: 3.5, + SecretGroup: 3, + Tags: []string{}, + Keywords: []string{}, + }, + }, + }, + }, + { + cfgName: "bad_entropy_group", + cfg: Config{}, + wantError: fmt.Errorf("Discord API key invalid regex secret group 5, max regex secret group 3"), + }, + { + cfgName: "base", + cfg: Config{ + Rules: map[string]Rule{ + "aws-access-key": { + Description: "AWS Access Key", + Regex: regexp.MustCompile("(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}"), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-access-key", + }, + "aws-secret-key": { + Description: "AWS Secret Key", + Regex: regexp.MustCompile(`(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}`), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-secret-key", + }, + "aws-secret-key-again": { + Description: "AWS Secret Key", + Regex: regexp.MustCompile(`(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}`), + Tags: []string{"key", "AWS"}, + Keywords: []string{}, + RuleID: "aws-secret-key-again", + }, + }, + }, + }, + } + + for _, tt := range tests { + viper.Reset() + viper.AddConfigPath(configPath) + viper.SetConfigName(tt.cfgName) + viper.SetConfigType("toml") + err := viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, err := vc.Translate() + if tt.wantError != nil { + if err == nil { + t.Errorf("expected error") + } + assert.Equal(t, tt.wantError, err) + } + + assert.Equal(t, cfg.Rules, tt.cfg.Rules) + } +} diff --git a/cli/config/infisical-scan.toml b/cli/config/infisical-scan.toml new file mode 100644 index 000000000..193883444 --- /dev/null +++ b/cli/config/infisical-scan.toml @@ -0,0 +1,2803 @@ + +# This file has been auto-generated. Do not edit manually. +# If you would like to contribute new rules, please use +# cmd/generate/config/main.go and follow the contributing guidelines +# at https://github.com/zricethezav/gitleaks/blob/master/CONTRIBUTING.md + +# This is the default gitleaks configuration file. +# Rules and allowlists are defined within this file. +# Rules instruct gitleaks on what should be considered a secret. +# Allowlists instruct gitleaks on what is allowed, i.e. not a secret. + +title = "gitleaks config" + +[allowlist] +description = "global allow lists" +paths = [ + '''infisical-scan.toml''', + '''(.*?)(jpg|gif|doc|docx|zip|xls|pdf|bin|svg|socket)$''', + '''(go.mod|go.sum)$''', + '''gradle.lockfile''', + '''node_modules''', + '''package-lock.json''', + '''pnpm-lock.yaml''', + '''Database.refactorlog''', + '''vendor''', +] + +[[rules]] +description = "Adafruit API Key" +id = "adafruit-api-key" +regex = '''(?i)(?:adafruit)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "adafruit", +] + +[[rules]] +description = "Adobe Client ID (OAuth Web)" +id = "adobe-client-id" +regex = '''(?i)(?:adobe)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "adobe", +] + +[[rules]] +description = "Adobe Client Secret" +id = "adobe-client-secret" +regex = '''(?i)\b((p8e-)(?i)[a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "p8e-", +] + +[[rules]] +description = "Age secret key" +id = "age secret key" +regex = '''AGE-SECRET-KEY-1[QPZRY9X8GF2TVDW0S3JN54KHCE6MUA7L]{58}''' +keywords = [ + "age-secret-key-1", +] + +[[rules]] +description = "Airtable API Key" +id = "airtable-api-key" +regex = '''(?i)(?:airtable)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{17})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "airtable", +] + +[[rules]] +description = "Algolia API Key" +id = "algolia-api-key" +regex = '''(?i)(?:algolia)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "algolia", +] + +[[rules]] +description = "Alibaba AccessKey ID" +id = "alibaba-access-key-id" +regex = '''(?i)\b((LTAI)(?i)[a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "ltai", +] + +[[rules]] +description = "Alibaba Secret Key" +id = "alibaba-secret-key" +regex = '''(?i)(?:alibaba)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "alibaba", +] + +[[rules]] +description = "Asana Client ID" +id = "asana-client-id" +regex = '''(?i)(?:asana)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "asana", +] + +[[rules]] +description = "Asana Client Secret" +id = "asana-client-secret" +regex = '''(?i)(?:asana)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "asana", +] + +[[rules]] +description = "Atlassian API token" +id = "atlassian-api-token" +regex = '''(?i)(?:atlassian|confluence|jira)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "atlassian","confluence","jira", +] + +[[rules]] +description = "Authress Service Client Access Key" +id = "authress-service-client-access-key" +regex = '''(?i)\b((?:sc|ext|scauth|authress)_[a-z0-9]{5,30}\.[a-z0-9]{4,6}\.acc_[a-z0-9-]{10,32}\.[a-z0-9+/_=-]{30,120})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sc_","ext_","scauth_","authress_", +] + +[[rules]] +description = "AWS" +id = "aws-access-token" +regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' +keywords = [ + "akia","agpa","aida","aroa","aipa","anpa","anva","asia", +] + +[[rules]] +description = "Beamer API token" +id = "beamer-api-token" +regex = '''(?i)(?:beamer)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(b_[a-z0-9=_\-]{44})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "beamer", +] + +[[rules]] +description = "Bitbucket Client ID" +id = "bitbucket-client-id" +regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "bitbucket", +] + +[[rules]] +description = "Bitbucket Client Secret" +id = "bitbucket-client-secret" +regex = '''(?i)(?:bitbucket)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "bitbucket", +] + +[[rules]] +description = "Bittrex Access Key" +id = "bittrex-access-key" +regex = '''(?i)(?:bittrex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "bittrex", +] + +[[rules]] +description = "Bittrex Secret Key" +id = "bittrex-secret-key" +regex = '''(?i)(?:bittrex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "bittrex", +] + +[[rules]] +description = "Clojars API token" +id = "clojars-api-token" +regex = '''(?i)(CLOJARS_)[a-z0-9]{60}''' +keywords = [ + "clojars", +] + +[[rules]] +description = "Codecov Access Token" +id = "codecov-access-token" +regex = '''(?i)(?:codecov)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "codecov", +] + +[[rules]] +description = "Coinbase Access Token" +id = "coinbase-access-token" +regex = '''(?i)(?:coinbase)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "coinbase", +] + +[[rules]] +description = "Confluent Access Token" +id = "confluent-access-token" +regex = '''(?i)(?:confluent)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "confluent", +] + +[[rules]] +description = "Confluent Secret Key" +id = "confluent-secret-key" +regex = '''(?i)(?:confluent)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "confluent", +] + +[[rules]] +description = "Contentful delivery API token" +id = "contentful-delivery-api-token" +regex = '''(?i)(?:contentful)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{43})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "contentful", +] + +[[rules]] +description = "Databricks API token" +id = "databricks-api-token" +regex = '''(?i)\b(dapi[a-h0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "dapi", +] + +[[rules]] +description = "Datadog Access Token" +id = "datadog-access-token" +regex = '''(?i)(?:datadog)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "datadog", +] + +[[rules]] +description = "Defined Networking API token" +id = "defined-networking-api-token" +regex = '''(?i)(?:dnkey)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(dnkey-[a-z0-9=_\-]{26}-[a-z0-9=_\-]{52})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "dnkey", +] + +[[rules]] +description = "DigitalOcean OAuth Access Token" +id = "digitalocean-access-token" +regex = '''(?i)\b(doo_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "doo_v1_", +] + +[[rules]] +description = "DigitalOcean Personal Access Token" +id = "digitalocean-pat" +regex = '''(?i)\b(dop_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "dop_v1_", +] + +[[rules]] +description = "DigitalOcean OAuth Refresh Token" +id = "digitalocean-refresh-token" +regex = '''(?i)\b(dor_v1_[a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "dor_v1_", +] + +[[rules]] +description = "Discord API key" +id = "discord-api-token" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "discord", +] + +[[rules]] +description = "Discord client ID" +id = "discord-client-id" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{18})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "discord", +] + +[[rules]] +description = "Discord client secret" +id = "discord-client-secret" +regex = '''(?i)(?:discord)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "discord", +] + +[[rules]] +description = "Doppler API token" +id = "doppler-api-token" +regex = '''(dp\.pt\.)(?i)[a-z0-9]{43}''' +keywords = [ + "doppler", +] + +[[rules]] +description = "Droneci Access Token" +id = "droneci-access-token" +regex = '''(?i)(?:droneci)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "droneci", +] + +[[rules]] +description = "Dropbox API secret" +id = "dropbox-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{15})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "dropbox", +] + +[[rules]] +description = "Dropbox long lived API token" +id = "dropbox-long-lived-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{11}(AAAAAAAAAA)[a-z0-9\-_=]{43})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "dropbox", +] + +[[rules]] +description = "Dropbox short lived API token" +id = "dropbox-short-lived-api-token" +regex = '''(?i)(?:dropbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(sl\.[a-z0-9\-=_]{135})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "dropbox", +] + +[[rules]] +description = "Duffel API token" +id = "duffel-api-token" +regex = '''duffel_(test|live)_(?i)[a-z0-9_\-=]{43}''' +keywords = [ + "duffel", +] + +[[rules]] +description = "Dynatrace API token" +id = "dynatrace-api-token" +regex = '''dt0c01\.(?i)[a-z0-9]{24}\.[a-z0-9]{64}''' +keywords = [ + "dynatrace", +] + +[[rules]] +description = "EasyPost API token" +id = "easypost-api-token" +regex = '''\bEZAK(?i)[a-z0-9]{54}''' +keywords = [ + "ezak", +] + +[[rules]] +description = "EasyPost test API token" +id = "easypost-test-api-token" +regex = '''\bEZTK(?i)[a-z0-9]{54}''' +keywords = [ + "eztk", +] + +[[rules]] +description = "Etsy Access Token" +id = "etsy-access-token" +regex = '''(?i)(?:etsy)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "etsy", +] + +[[rules]] +description = "Facebook Access Token" +id = "facebook" +regex = '''(?i)(?:facebook)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "facebook", +] + +[[rules]] +description = "Fastly API key" +id = "fastly-api-token" +regex = '''(?i)(?:fastly)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "fastly", +] + +[[rules]] +description = "Finicity API token" +id = "finicity-api-token" +regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "finicity", +] + +[[rules]] +description = "Finicity Client Secret" +id = "finicity-client-secret" +regex = '''(?i)(?:finicity)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "finicity", +] + +[[rules]] +description = "Finnhub Access Token" +id = "finnhub-access-token" +regex = '''(?i)(?:finnhub)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{20})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "finnhub", +] + +[[rules]] +description = "Flickr Access Token" +id = "flickr-access-token" +regex = '''(?i)(?:flickr)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "flickr", +] + +[[rules]] +description = "Flutterwave Encryption Key" +id = "flutterwave-encryption-key" +regex = '''FLWSECK_TEST-(?i)[a-h0-9]{12}''' +keywords = [ + "flwseck_test", +] + +[[rules]] +description = "Finicity Public Key" +id = "flutterwave-public-key" +regex = '''FLWPUBK_TEST-(?i)[a-h0-9]{32}-X''' +keywords = [ + "flwpubk_test", +] + +[[rules]] +description = "Flutterwave Secret Key" +id = "flutterwave-secret-key" +regex = '''FLWSECK_TEST-(?i)[a-h0-9]{32}-X''' +keywords = [ + "flwseck_test", +] + +[[rules]] +description = "Frame.io API token" +id = "frameio-api-token" +regex = '''fio-u-(?i)[a-z0-9\-_=]{64}''' +keywords = [ + "fio-u-", +] + +[[rules]] +description = "Freshbooks Access Token" +id = "freshbooks-access-token" +regex = '''(?i)(?:freshbooks)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "freshbooks", +] + +[[rules]] +description = "GCP API key" +id = "gcp-api-key" +regex = '''(?i)\b(AIza[0-9A-Za-z\\-_]{35})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "aiza", +] + +[[rules]] +description = "Generic API Key" +id = "generic-api-key" +regex = '''(?i)(?:key|api|token|secret|client|passwd|password|auth|access)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-z\-_.=]{10,150})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +entropy = 3.5 +keywords = [ + "key","api","token","secret","client","passwd","password","auth","access", +] +[rules.allowlist] +stopwords= [ + "client", + "endpoint", + "vpn", + "_ec2_", + "aws_", + "authorize", + "author", + "define", + "config", + "credential", + "setting", + "sample", + "xxxxxx", + "000000", + "buffer", + "delete", + "aaaaaa", + "fewfwef", + "getenv", + "env_", + "system", + "example", + "ecdsa", + "sha256", + "sha1", + "sha2", + "md5", + "alert", + "wizard", + "target", + "onboard", + "welcome", + "page", + "exploit", + "experiment", + "expire", + "rabbitmq", + "scraper", + "widget", + "music", + "dns_", + "dns-", + "yahoo", + "want", + "json", + "action", + "script", + "fix_", + "fix-", + "develop", + "compas", + "stripe", + "service", + "master", + "metric", + "tech", + "gitignore", + "rich", + "open", + "stack", + "irc_", + "irc-", + "sublime", + "kohana", + "has_", + "has-", + "fabric", + "wordpres", + "role", + "osx_", + "osx-", + "boost", + "addres", + "queue", + "working", + "sandbox", + "internet", + "print", + "vision", + "tracking", + "being", + "generator", + "traffic", + "world", + "pull", + "rust", + "watcher", + "small", + "auth", + "full", + "hash", + "more", + "install", + "auto", + "complete", + "learn", + "paper", + "installer", + "research", + "acces", + "last", + "binding", + "spine", + "into", + "chat", + "algorithm", + "resource", + "uploader", + "video", + "maker", + "next", + "proc", + "lock", + "robot", + "snake", + "patch", + "matrix", + "drill", + "terminal", + "term", + "stuff", + "genetic", + "generic", + "identity", + "audit", + "pattern", + "audio", + "web_", + "web-", + "crud", + "problem", + "statu", + "cms-", + "cms_", + "arch", + "coffee", + "workflow", + "changelog", + "another", + "uiview", + "content", + "kitchen", + "gnu_", + "gnu-", + "gnu.", + "conf", + "couchdb", + "client", + "opencv", + "rendering", + "update", + "concept", + "varnish", + "gui_", + "gui-", + "gui.", + "version", + "shared", + "extra", + "product", + "still", + "not_", + "not-", + "not.", + "drop", + "ring", + "png_", + "png-", + "png.", + "actively", + "import", + "output", + "backup", + "start", + "embedded", + "registry", + "pool", + "semantic", + "instagram", + "bash", + "system", + "ninja", + "drupal", + "jquery", + "polyfill", + "physic", + "league", + "guide", + "pack", + "synopsi", + "sketch", + "injection", + "svg_", + "svg-", + "svg.", + "friendly", + "wave", + "convert", + "manage", + "camera", + "link", + "slide", + "timer", + "wrapper", + "gallery", + "url_", + "url-", + "url.", + "todomvc", + "requirej", + "party", + "http", + "payment", + "async", + "library", + "home", + "coco", + "gaia", + "display", + "universal", + "func", + "metadata", + "hipchat", + "under", + "room", + "config", + "personal", + "realtime", + "resume", + "database", + "testing", + "tiny", + "basic", + "forum", + "meetup", + "yet_", + "yet-", + "yet.", + "cento", + "dead", + "fluentd", + "editor", + "utilitie", + "run_", + "run-", + "run.", + "box_", + "box-", + "box.", + "bot_", + "bot-", + "bot.", + "making", + "sample", + "group", + "monitor", + "ajax", + "parallel", + "cassandra", + "ultimate", + "site", + "get_", + "get-", + "get.", + "gen_", + "gen-", + "gen.", + "gem_", + "gem-", + "gem.", + "extended", + "image", + "knife", + "asset", + "nested", + "zero", + "plugin", + "bracket", + "mule", + "mozilla", + "number", + "act_", + "act-", + "act.", + "map_", + "map-", + "map.", + "micro", + "debug", + "openshift", + "chart", + "expres", + "backend", + "task", + "source", + "translate", + "jbos", + "composer", + "sqlite", + "profile", + "mustache", + "mqtt", + "yeoman", + "have", + "builder", + "smart", + "like", + "oauth", + "school", + "guideline", + "captcha", + "filter", + "bitcoin", + "bridge", + "color", + "toolbox", + "discovery", + "new_", + "new-", + "new.", + "dashboard", + "when", + "setting", + "level", + "post", + "standard", + "port", + "platform", + "yui_", + "yui-", + "yui.", + "grunt", + "animation", + "haskell", + "icon", + "latex", + "cheat", + "lua_", + "lua-", + "lua.", + "gulp", + "case", + "author", + "without", + "simulator", + "wifi", + "directory", + "lisp", + "list", + "flat", + "adventure", + "story", + "storm", + "gpu_", + "gpu-", + "gpu.", + "store", + "caching", + "attention", + "solr", + "logger", + "demo", + "shortener", + "hadoop", + "finder", + "phone", + "pipeline", + "range", + "textmate", + "showcase", + "app_", + "app-", + "app.", + "idiomatic", + "edit", + "our_", + "our-", + "our.", + "out_", + "out-", + "out.", + "sentiment", + "linked", + "why_", + "why-", + "why.", + "local", + "cube", + "gmail", + "job_", + "job-", + "job.", + "rpc_", + "rpc-", + "rpc.", + "contest", + "tcp_", + "tcp-", + "tcp.", + "usage", + "buildout", + "weather", + "transfer", + "automated", + "sphinx", + "issue", + "sas_", + "sas-", + "sas.", + "parallax", + "jasmine", + "addon", + "machine", + "solution", + "dsl_", + "dsl-", + "dsl.", + "episode", + "menu", + "theme", + "best", + "adapter", + "debugger", + "chrome", + "tutorial", + "life", + "step", + "people", + "joomla", + "paypal", + "developer", + "solver", + "team", + "current", + "love", + "visual", + "date", + "data", + "canva", + "container", + "future", + "xml_", + "xml-", + "xml.", + "twig", + "nagio", + "spatial", + "original", + "sync", + "archived", + "refinery", + "science", + "mapping", + "gitlab", + "play", + "ext_", + "ext-", + "ext.", + "session", + "impact", + "set_", + "set-", + "set.", + "see_", + "see-", + "see.", + "migration", + "commit", + "community", + "shopify", + "what'", + "cucumber", + "statamic", + "mysql", + "location", + "tower", + "line", + "code", + "amqp", + "hello", + "send", + "index", + "high", + "notebook", + "alloy", + "python", + "field", + "document", + "soap", + "edition", + "email", + "php_", + "php-", + "php.", + "command", + "transport", + "official", + "upload", + "study", + "secure", + "angularj", + "akka", + "scalable", + "package", + "request", + "con_", + "con-", + "con.", + "flexible", + "security", + "comment", + "module", + "flask", + "graph", + "flash", + "apache", + "change", + "window", + "space", + "lambda", + "sheet", + "bookmark", + "carousel", + "friend", + "objective", + "jekyll", + "bootstrap", + "first", + "article", + "gwt_", + "gwt-", + "gwt.", + "classic", + "media", + "websocket", + "touch", + "desktop", + "real", + "read", + "recorder", + "moved", + "storage", + "validator", + "add-on", + "pusher", + "scs_", + "scs-", + "scs.", + "inline", + "asp_", + "asp-", + "asp.", + "timeline", + "base", + "encoding", + "ffmpeg", + "kindle", + "tinymce", + "pretty", + "jpa_", + "jpa-", + "jpa.", + "used", + "user", + "required", + "webhook", + "download", + "resque", + "espresso", + "cloud", + "mongo", + "benchmark", + "pure", + "cakephp", + "modx", + "mode", + "reactive", + "fuel", + "written", + "flickr", + "mail", + "brunch", + "meteor", + "dynamic", + "neo_", + "neo-", + "neo.", + "new_", + "new-", + "new.", + "net_", + "net-", + "net.", + "typo", + "type", + "keyboard", + "erlang", + "adobe", + "logging", + "ckeditor", + "message", + "iso_", + "iso-", + "iso.", + "hook", + "ldap", + "folder", + "reference", + "railscast", + "www_", + "www-", + "www.", + "tracker", + "azure", + "fork", + "form", + "digital", + "exporter", + "skin", + "string", + "template", + "designer", + "gollum", + "fluent", + "entity", + "language", + "alfred", + "summary", + "wiki", + "kernel", + "calendar", + "plupload", + "symfony", + "foundry", + "remote", + "talk", + "search", + "dev_", + "dev-", + "dev.", + "del_", + "del-", + "del.", + "token", + "idea", + "sencha", + "selector", + "interface", + "create", + "fun_", + "fun-", + "fun.", + "groovy", + "query", + "grail", + "red_", + "red-", + "red.", + "laravel", + "monkey", + "slack", + "supported", + "instant", + "value", + "center", + "latest", + "work", + "but_", + "but-", + "but.", + "bug_", + "bug-", + "bug.", + "virtual", + "tweet", + "statsd", + "studio", + "path", + "real-time", + "frontend", + "notifier", + "coding", + "tool", + "firmware", + "flow", + "random", + "mediawiki", + "bosh", + "been", + "beer", + "lightbox", + "theory", + "origin", + "redmine", + "hub_", + "hub-", + "hub.", + "require", + "pro_", + "pro-", + "pro.", + "ant_", + "ant-", + "ant.", + "any_", + "any-", + "any.", + "recipe", + "closure", + "mapper", + "event", + "todo", + "model", + "redi", + "provider", + "rvm_", + "rvm-", + "rvm.", + "program", + "memcached", + "rail", + "silex", + "foreman", + "activity", + "license", + "strategy", + "batch", + "streaming", + "fast", + "use_", + "use-", + "use.", + "usb_", + "usb-", + "usb.", + "impres", + "academy", + "slider", + "please", + "layer", + "cros", + "now_", + "now-", + "now.", + "miner", + "extension", + "own_", + "own-", + "own.", + "app_", + "app-", + "app.", + "debian", + "symphony", + "example", + "feature", + "serie", + "tree", + "project", + "runner", + "entry", + "leetcode", + "layout", + "webrtc", + "logic", + "login", + "worker", + "toolkit", + "mocha", + "support", + "back", + "inside", + "device", + "jenkin", + "contact", + "fake", + "awesome", + "ocaml", + "bit_", + "bit-", + "bit.", + "drive", + "screen", + "prototype", + "gist", + "binary", + "nosql", + "rest", + "overview", + "dart", + "dark", + "emac", + "mongoid", + "solarized", + "homepage", + "emulator", + "commander", + "django", + "yandex", + "gradle", + "xcode", + "writer", + "crm_", + "crm-", + "crm.", + "jade", + "startup", + "error", + "using", + "format", + "name", + "spring", + "parser", + "scratch", + "magic", + "try_", + "try-", + "try.", + "rack", + "directive", + "challenge", + "slim", + "counter", + "element", + "chosen", + "doc_", + "doc-", + "doc.", + "meta", + "should", + "button", + "packet", + "stream", + "hardware", + "android", + "infinite", + "password", + "software", + "ghost", + "xamarin", + "spec", + "chef", + "interview", + "hubot", + "mvc_", + "mvc-", + "mvc.", + "exercise", + "leaflet", + "launcher", + "air_", + "air-", + "air.", + "photo", + "board", + "boxen", + "way_", + "way-", + "way.", + "computing", + "welcome", + "notepad", + "portfolio", + "cat_", + "cat-", + "cat.", + "can_", + "can-", + "can.", + "magento", + "yaml", + "domain", + "card", + "yii_", + "yii-", + "yii.", + "checker", + "browser", + "upgrade", + "only", + "progres", + "aura", + "ruby_", + "ruby-", + "ruby.", + "polymer", + "util", + "lite", + "hackathon", + "rule", + "log_", + "log-", + "log.", + "opengl", + "stanford", + "skeleton", + "history", + "inspector", + "help", + "soon", + "selenium", + "lab_", + "lab-", + "lab.", + "scheme", + "schema", + "look", + "ready", + "leveldb", + "docker", + "game", + "minimal", + "logstash", + "messaging", + "within", + "heroku", + "mongodb", + "kata", + "suite", + "picker", + "win_", + "win-", + "win.", + "wip_", + "wip-", + "wip.", + "panel", + "started", + "starter", + "front-end", + "detector", + "deploy", + "editing", + "based", + "admin", + "capture", + "spree", + "page", + "bundle", + "goal", + "rpg_", + "rpg-", + "rpg.", + "setup", + "side", + "mean", + "reader", + "cookbook", + "mini", + "modern", + "seed", + "dom_", + "dom-", + "dom.", + "doc_", + "doc-", + "doc.", + "dot_", + "dot-", + "dot.", + "syntax", + "sugar", + "loader", + "website", + "make", + "kit_", + "kit-", + "kit.", + "protocol", + "human", + "daemon", + "golang", + "manager", + "countdown", + "connector", + "swagger", + "map_", + "map-", + "map.", + "mac_", + "mac-", + "mac.", + "man_", + "man-", + "man.", + "orm_", + "orm-", + "orm.", + "org_", + "org-", + "org.", + "little", + "zsh_", + "zsh-", + "zsh.", + "shop", + "show", + "workshop", + "money", + "grid", + "server", + "octopres", + "svn_", + "svn-", + "svn.", + "ember", + "embed", + "general", + "file", + "important", + "dropbox", + "portable", + "public", + "docpad", + "fish", + "sbt_", + "sbt-", + "sbt.", + "done", + "para", + "network", + "common", + "readme", + "popup", + "simple", + "purpose", + "mirror", + "single", + "cordova", + "exchange", + "object", + "design", + "gateway", + "account", + "lamp", + "intellij", + "math", + "mit_", + "mit-", + "mit.", + "control", + "enhanced", + "emitter", + "multi", + "add_", + "add-", + "add.", + "about", + "socket", + "preview", + "vagrant", + "cli_", + "cli-", + "cli.", + "powerful", + "top_", + "top-", + "top.", + "radio", + "watch", + "fluid", + "amazon", + "report", + "couchbase", + "automatic", + "detection", + "sprite", + "pyramid", + "portal", + "advanced", + "plu_", + "plu-", + "plu.", + "runtime", + "git_", + "git-", + "git.", + "uri_", + "uri-", + "uri.", + "haml", + "node", + "sql_", + "sql-", + "sql.", + "cool", + "core", + "obsolete", + "handler", + "iphone", + "extractor", + "array", + "copy", + "nlp_", + "nlp-", + "nlp.", + "reveal", + "pop_", + "pop-", + "pop.", + "engine", + "parse", + "check", + "html", + "nest", + "all_", + "all-", + "all.", + "chinese", + "buildpack", + "what", + "tag_", + "tag-", + "tag.", + "proxy", + "style", + "cookie", + "feed", + "restful", + "compiler", + "creating", + "prelude", + "context", + "java", + "rspec", + "mock", + "backbone", + "light", + "spotify", + "flex", + "related", + "shell", + "which", + "clas", + "webapp", + "swift", + "ansible", + "unity", + "console", + "tumblr", + "export", + "campfire", + "conway'", + "made", + "riak", + "hero", + "here", + "unix", + "unit", + "glas", + "smtp", + "how_", + "how-", + "how.", + "hot_", + "hot-", + "hot.", + "debug", + "release", + "diff", + "player", + "easy", + "right", + "old_", + "old-", + "old.", + "animate", + "time", + "push", + "explorer", + "course", + "training", + "nette", + "router", + "draft", + "structure", + "note", + "salt", + "where", + "spark", + "trello", + "power", + "method", + "social", + "via_", + "via-", + "via.", + "vim_", + "vim-", + "vim.", + "select", + "webkit", + "github", + "ftp_", + "ftp-", + "ftp.", + "creator", + "mongoose", + "led_", + "led-", + "led.", + "movie", + "currently", + "pdf_", + "pdf-", + "pdf.", + "load", + "markdown", + "phalcon", + "input", + "custom", + "atom", + "oracle", + "phonegap", + "ubuntu", + "great", + "rdf_", + "rdf-", + "rdf.", + "popcorn", + "firefox", + "zip_", + "zip-", + "zip.", + "cuda", + "dotfile", + "static", + "openwrt", + "viewer", + "powered", + "graphic", + "les_", + "les-", + "les.", + "doe_", + "doe-", + "doe.", + "maven", + "word", + "eclipse", + "lab_", + "lab-", + "lab.", + "hacking", + "steam", + "analytic", + "option", + "abstract", + "archive", + "reality", + "switcher", + "club", + "write", + "kafka", + "arduino", + "angular", + "online", + "title", + "don't", + "contao", + "notice", + "analyzer", + "learning", + "zend", + "external", + "staging", + "busines", + "tdd_", + "tdd-", + "tdd.", + "scanner", + "building", + "snippet", + "modular", + "bower", + "stm_", + "stm-", + "stm.", + "lib_", + "lib-", + "lib.", + "alpha", + "mobile", + "clean", + "linux", + "nginx", + "manifest", + "some", + "raspberry", + "gnome", + "ide_", + "ide-", + "ide.", + "block", + "statistic", + "info", + "drag", + "youtube", + "koan", + "facebook", + "paperclip", + "art_", + "art-", + "art.", + "quality", + "tab_", + "tab-", + "tab.", + "need", + "dojo", + "shield", + "computer", + "stat", + "state", + "twitter", + "utility", + "converter", + "hosting", + "devise", + "liferay", + "updated", + "force", + "tip_", + "tip-", + "tip.", + "behavior", + "active", + "call", + "answer", + "deck", + "better", + "principle", + "ches", + "bar_", + "bar-", + "bar.", + "reddit", + "three", + "haxe", + "just", + "plug-in", + "agile", + "manual", + "tetri", + "super", + "beta", + "parsing", + "doctrine", + "minecraft", + "useful", + "perl", + "sharing", + "agent", + "switch", + "view", + "dash", + "channel", + "repo", + "pebble", + "profiler", + "warning", + "cluster", + "running", + "markup", + "evented", + "mod_", + "mod-", + "mod.", + "share", + "csv_", + "csv-", + "csv.", + "response", + "good", + "house", + "connect", + "built", + "build", + "find", + "ipython", + "webgl", + "big_", + "big-", + "big.", + "google", + "scala", + "sdl_", + "sdl-", + "sdl.", + "sdk_", + "sdk-", + "sdk.", + "native", + "day_", + "day-", + "day.", + "puppet", + "text", + "routing", + "helper", + "linkedin", + "crawler", + "host", + "guard", + "merchant", + "poker", + "over", + "writing", + "free", + "classe", + "component", + "craft", + "nodej", + "phoenix", + "longer", + "quick", + "lazy", + "memory", + "clone", + "hacker", + "middleman", + "factory", + "motion", + "multiple", + "tornado", + "hack", + "ssh_", + "ssh-", + "ssh.", + "review", + "vimrc", + "driver", + "driven", + "blog", + "particle", + "table", + "intro", + "importer", + "thrift", + "xmpp", + "framework", + "refresh", + "react", + "font", + "librarie", + "variou", + "formatter", + "analysi", + "karma", + "scroll", + "tut_", + "tut-", + "tut.", + "apple", + "tag_", + "tag-", + "tag.", + "tab_", + "tab-", + "tab.", + "category", + "ionic", + "cache", + "homebrew", + "reverse", + "english", + "getting", + "shipping", + "clojure", + "boot", + "book", + "branch", + "combination", + "combo", +] +[[rules]] +description = "GitHub App Token" +id = "github-app-token" +regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}''' +keywords = [ + "ghu_","ghs_", +] + +[[rules]] +description = "GitHub Fine-Grained Personal Access Token" +id = "github-fine-grained-pat" +regex = '''github_pat_[0-9a-zA-Z_]{82}''' +keywords = [ + "github_pat_", +] + +[[rules]] +description = "GitHub OAuth Access Token" +id = "github-oauth" +regex = '''gho_[0-9a-zA-Z]{36}''' +keywords = [ + "gho_", +] + +[[rules]] +description = "GitHub Personal Access Token" +id = "github-pat" +regex = '''ghp_[0-9a-zA-Z]{36}''' +keywords = [ + "ghp_", +] + +[[rules]] +description = "GitHub Refresh Token" +id = "github-refresh-token" +regex = '''ghr_[0-9a-zA-Z]{36}''' +keywords = [ + "ghr_", +] + +[[rules]] +description = "GitLab Personal Access Token" +id = "gitlab-pat" +regex = '''glpat-[0-9a-zA-Z\-\_]{20}''' +keywords = [ + "glpat-", +] + +[[rules]] +description = "GitLab Pipeline Trigger Token" +id = "gitlab-ptt" +regex = '''glptt-[0-9a-f]{40}''' +keywords = [ + "glptt-", +] + +[[rules]] +description = "GitLab Runner Registration Token" +id = "gitlab-rrt" +regex = '''GR1348941[0-9a-zA-Z\-\_]{20}''' +keywords = [ + "gr1348941", +] + +[[rules]] +description = "Gitter Access Token" +id = "gitter-access-token" +regex = '''(?i)(?:gitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "gitter", +] + +[[rules]] +description = "GoCardless API token" +id = "gocardless-api-token" +regex = '''(?i)(?:gocardless)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(live_(?i)[a-z0-9\-_=]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "live_","gocardless", +] + +[[rules]] +description = "Grafana api key (or Grafana cloud api key)" +id = "grafana-api-key" +regex = '''(?i)\b(eyJrIjoi[A-Za-z0-9]{70,400}={0,2})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "eyjrijoi", +] + +[[rules]] +description = "Grafana cloud api token" +id = "grafana-cloud-api-token" +regex = '''(?i)\b(glc_[A-Za-z0-9+/]{32,400}={0,2})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "glc_", +] + +[[rules]] +description = "Grafana service account token" +id = "grafana-service-account-token" +regex = '''(?i)\b(glsa_[A-Za-z0-9]{32}_[A-Fa-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "glsa_", +] + +[[rules]] +description = "HashiCorp Terraform user/org API token" +id = "hashicorp-tf-api-token" +regex = '''(?i)[a-z0-9]{14}\.atlasv1\.[a-z0-9\-_=]{60,70}''' +keywords = [ + "atlasv1", +] + +[[rules]] +description = "Heroku API Key" +id = "heroku-api-key" +regex = '''(?i)(?:heroku)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "heroku", +] + +[[rules]] +description = "HubSpot API Token" +id = "hubspot-api-key" +regex = '''(?i)(?:hubspot)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "hubspot", +] + +[[rules]] +description = "Intercom API Token" +id = "intercom-api-key" +regex = '''(?i)(?:intercom)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{60})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "intercom", +] + +[[rules]] +description = "JSON Web Token" +id = "jwt" +regex = '''(?i)\b(ey[0-9a-z]{30,34}\.ey[0-9a-z-\/_]{30,500}\.[0-9a-zA-Z-\/_]{10,200}={0,2})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "ey", +] + +[[rules]] +description = "Kraken Access Token" +id = "kraken-access-token" +regex = '''(?i)(?:kraken)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9\/=_\+\-]{80,90})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "kraken", +] + +[[rules]] +description = "Kucoin Access Token" +id = "kucoin-access-token" +regex = '''(?i)(?:kucoin)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "kucoin", +] + +[[rules]] +description = "Kucoin Secret Key" +id = "kucoin-secret-key" +regex = '''(?i)(?:kucoin)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "kucoin", +] + +[[rules]] +description = "Launchdarkly Access Token" +id = "launchdarkly-access-token" +regex = '''(?i)(?:launchdarkly)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "launchdarkly", +] + +[[rules]] +description = "Linear API Token" +id = "linear-api-key" +regex = '''lin_api_(?i)[a-z0-9]{40}''' +keywords = [ + "lin_api_", +] + +[[rules]] +description = "Linear Client Secret" +id = "linear-client-secret" +regex = '''(?i)(?:linear)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "linear", +] + +[[rules]] +description = "LinkedIn Client ID" +id = "linkedin-client-id" +regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{14})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "linkedin","linked-in", +] + +[[rules]] +description = "LinkedIn Client secret" +id = "linkedin-client-secret" +regex = '''(?i)(?:linkedin|linked-in)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "linkedin","linked-in", +] + +[[rules]] +description = "Lob API Key" +id = "lob-api-key" +regex = '''(?i)(?:lob)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((live|test)_[a-f0-9]{35})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "test_","live_", +] + +[[rules]] +description = "Lob Publishable API Key" +id = "lob-pub-api-key" +regex = '''(?i)(?:lob)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}((test|live)_pub_[a-f0-9]{31})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "test_pub","live_pub","_pub", +] + +[[rules]] +description = "Mailchimp API key" +id = "mailchimp-api-key" +regex = '''(?i)(?:mailchimp)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{32}-us20)(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mailchimp", +] + +[[rules]] +description = "Mailgun private API token" +id = "mailgun-private-api-token" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(key-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mailgun", +] + +[[rules]] +description = "Mailgun public validation key" +id = "mailgun-pub-key" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pubkey-[a-f0-9]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mailgun", +] + +[[rules]] +description = "Mailgun webhook signing key" +id = "mailgun-signing-key" +regex = '''(?i)(?:mailgun)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-h0-9]{32}-[a-h0-9]{8}-[a-h0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mailgun", +] + +[[rules]] +description = "MapBox API token" +id = "mapbox-api-token" +regex = '''(?i)(?:mapbox)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(pk\.[a-z0-9]{60}\.[a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mapbox", +] + +[[rules]] +description = "Mattermost Access Token" +id = "mattermost-access-token" +regex = '''(?i)(?:mattermost)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{26})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "mattermost", +] + +[[rules]] +description = "MessageBird API token" +id = "messagebird-api-token" +regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "messagebird","message-bird","message_bird", +] + +[[rules]] +description = "MessageBird client ID" +id = "messagebird-client-id" +regex = '''(?i)(?:messagebird|message-bird|message_bird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "messagebird","message-bird","message_bird", +] + +[[rules]] +description = "Microsoft Teams Webhook" +id = "microsoft-teams-webhook" +regex = '''https:\/\/[a-z0-9]+\.webhook\.office\.com\/webhookb2\/[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}@[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\/IncomingWebhook\/[a-z0-9]{32}\/[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}''' +keywords = [ + "webhook.office.com","webhookb2","incomingwebhook", +] + +[[rules]] +description = "Netlify Access Token" +id = "netlify-access-token" +regex = '''(?i)(?:netlify)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{40,46})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "netlify", +] + +[[rules]] +description = "New Relic ingest browser API token" +id = "new-relic-browser-api-token" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRJS-[a-f0-9]{19})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "nrjs-", +] + +[[rules]] +description = "New Relic user API ID" +id = "new-relic-user-api-id" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "new-relic","newrelic","new_relic", +] + +[[rules]] +description = "New Relic user API Key" +id = "new-relic-user-api-key" +regex = '''(?i)(?:new-relic|newrelic|new_relic)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(NRAK-[a-z0-9]{27})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "nrak", +] + +[[rules]] +description = "npm access token" +id = "npm-access-token" +regex = '''(?i)\b(npm_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "npm_", +] + +[[rules]] +description = "Nytimes Access Token" +id = "nytimes-access-token" +regex = '''(?i)(?:nytimes|new-york-times,|newyorktimes)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{32})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "nytimes","new-york-times","newyorktimes", +] + +[[rules]] +description = "Okta Access Token" +id = "okta-access-token" +regex = '''(?i)(?:okta)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9=_\-]{42})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "okta", +] + +[[rules]] +description = "Plaid API Token" +id = "plaid-api-token" +regex = '''(?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(access-(?:sandbox|development|production)-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "plaid", +] + +[[rules]] +description = "Plaid Client ID" +id = "plaid-client-id" +regex = '''(?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{24})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "plaid", +] + +[[rules]] +description = "Plaid Secret key" +id = "plaid-secret-key" +regex = '''(?i)(?:plaid)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "plaid", +] + +[[rules]] +description = "PlanetScale API token" +id = "planetscale-api-token" +regex = '''(?i)\b(pscale_tkn_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pscale_tkn_", +] + +[[rules]] +description = "PlanetScale OAuth token" +id = "planetscale-oauth-token" +regex = '''(?i)\b(pscale_oauth_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pscale_oauth_", +] + +[[rules]] +description = "PlanetScale password" +id = "planetscale-password" +regex = '''(?i)\b(pscale_pw_(?i)[a-z0-9=\-_\.]{32,64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pscale_pw_", +] + +[[rules]] +description = "Postman API token" +id = "postman-api-token" +regex = '''(?i)\b(PMAK-(?i)[a-f0-9]{24}\-[a-f0-9]{34})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pmak-", +] + +[[rules]] +description = "Prefect API token" +id = "prefect-api-token" +regex = '''(?i)\b(pnu_[a-z0-9]{36})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pnu_", +] + +[[rules]] +description = "Private Key" +id = "private-key" +regex = '''(?i)-----BEGIN[ A-Z0-9_-]{0,100}PRIVATE KEY( BLOCK)?-----[\s\S-]*KEY( BLOCK)?----''' +keywords = [ + "-----begin", +] + +[[rules]] +description = "Pulumi API token" +id = "pulumi-api-token" +regex = '''(?i)\b(pul-[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "pul-", +] + +[[rules]] +description = "PyPI upload token" +id = "pypi-upload-token" +regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}''' +keywords = [ + "pypi-ageichlwas5vcmc", +] + +[[rules]] +description = "RapidAPI Access Token" +id = "rapidapi-access-token" +regex = '''(?i)(?:rapidapi)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9_-]{50})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "rapidapi", +] + +[[rules]] +description = "Readme API token" +id = "readme-api-token" +regex = '''(?i)\b(rdme_[a-z0-9]{70})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "rdme_", +] + +[[rules]] +description = "Rubygem API token" +id = "rubygems-api-token" +regex = '''(?i)\b(rubygems_[a-f0-9]{48})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "rubygems_", +] + +[[rules]] +description = "Sendbird Access ID" +id = "sendbird-access-id" +regex = '''(?i)(?:sendbird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sendbird", +] + +[[rules]] +description = "Sendbird Access Token" +id = "sendbird-access-token" +regex = '''(?i)(?:sendbird)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sendbird", +] + +[[rules]] +description = "SendGrid API token" +id = "sendgrid-api-token" +regex = '''(?i)\b(SG\.(?i)[a-z0-9=_\-\.]{66})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sg.", +] + +[[rules]] +description = "Sendinblue API token" +id = "sendinblue-api-token" +regex = '''(?i)\b(xkeysib-[a-f0-9]{64}\-(?i)[a-z0-9]{16})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "xkeysib-", +] + +[[rules]] +description = "Sentry Access Token" +id = "sentry-access-token" +regex = '''(?i)(?:sentry)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sentry", +] + +[[rules]] +description = "Shippo API token" +id = "shippo-api-token" +regex = '''(?i)\b(shippo_(live|test)_[a-f0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "shippo_", +] + +[[rules]] +description = "Shopify access token" +id = "shopify-access-token" +regex = '''shpat_[a-fA-F0-9]{32}''' +keywords = [ + "shpat_", +] + +[[rules]] +description = "Shopify custom access token" +id = "shopify-custom-access-token" +regex = '''shpca_[a-fA-F0-9]{32}''' +keywords = [ + "shpca_", +] + +[[rules]] +description = "Shopify private app access token" +id = "shopify-private-app-access-token" +regex = '''shppa_[a-fA-F0-9]{32}''' +keywords = [ + "shppa_", +] + +[[rules]] +description = "Shopify shared secret" +id = "shopify-shared-secret" +regex = '''shpss_[a-fA-F0-9]{32}''' +keywords = [ + "shpss_", +] + +[[rules]] +description = "Sidekiq Secret" +id = "sidekiq-secret" +regex = '''(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "bundle_enterprise__contribsys__com","bundle_gems__contribsys__com", +] + +[[rules]] +description = "Sidekiq Sensitive URL" +id = "sidekiq-sensitive-url" +regex = '''(?i)\b(http(?:s??):\/\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\/|\#|\?|:]|$)''' +secretGroup = 2 +keywords = [ + "gems.contribsys.com","enterprise.contribsys.com", +] + +[[rules]] +description = "Slack token" +id = "slack-access-token" +regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})''' +keywords = [ + "xoxb","xoxa","xoxp","xoxr","xoxs", +] + +[[rules]] +description = "Slack Webhook" +id = "slack-web-hook" +regex = '''https:\/\/hooks.slack.com\/(services|workflows)\/[A-Za-z0-9+\/]{44,46}''' +keywords = [ + "hooks.slack.com", +] + +[[rules]] +description = "Square Access Token" +id = "square-access-token" +regex = '''(?i)\b(sq0atp-[0-9A-Za-z\-_]{22})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "sq0atp-", +] + +[[rules]] +description = "Squarespace Access Token" +id = "squarespace-access-token" +regex = '''(?i)(?:squarespace)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "squarespace", +] + +[[rules]] +description = "Stripe Access Token" +id = "stripe-access-token" +regex = '''(?i)(sk|pk)_(test|live)_[0-9a-z]{10,32}''' +keywords = [ + "sk_test","pk_test","sk_live","pk_live", +] + +[[rules]] +description = "SumoLogic Access ID" +id = "sumologic-access-id" +regex = '''(?i)(?:sumo)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{14})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sumo", +] + +[[rules]] +description = "SumoLogic Access Token" +id = "sumologic-access-token" +regex = '''(?i)(?:sumo)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{64})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "sumo", +] + +[[rules]] +description = "Telegram Bot API Token" +id = "telegram-bot-api-token" +regex = '''(?i)(?:^|[^0-9])([0-9]{5,16}:A[a-zA-Z0-9_\-]{34})(?:$|[^a-zA-Z0-9_\-])''' +secretGroup = 1 +keywords = [ + "telegram","api","bot","token","url", +] + +[[rules]] +description = "Travis CI Access Token" +id = "travisci-access-token" +regex = '''(?i)(?:travis)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{22})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "travis", +] + +[[rules]] +description = "Twilio API Key" +id = "twilio-api-key" +regex = '''SK[0-9a-fA-F]{32}''' +keywords = [ + "twilio", +] + +[[rules]] +description = "Twitch API token" +id = "twitch-api-token" +regex = '''(?i)(?:twitch)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{30})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitch", +] + +[[rules]] +description = "Twitter Access Secret" +id = "twitter-access-secret" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{45})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitter", +] + +[[rules]] +description = "Twitter Access Token" +id = "twitter-access-token" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([0-9]{15,25}-[a-zA-Z0-9]{20,40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitter", +] + +[[rules]] +description = "Twitter API Key" +id = "twitter-api-key" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{25})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitter", +] + +[[rules]] +description = "Twitter API Secret" +id = "twitter-api-secret" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{50})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitter", +] + +[[rules]] +description = "Twitter Bearer Token" +id = "twitter-bearer-token" +regex = '''(?i)(?:twitter)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(A{22}[a-zA-Z0-9%]{80,100})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "twitter", +] + +[[rules]] +description = "Typeform API token" +id = "typeform-api-token" +regex = '''(?i)(?:typeform)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(tfp_[a-z0-9\-_\.=]{59})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "tfp_", +] + +[[rules]] +description = "Vault Batch Token" +id = "vault-batch-token" +regex = '''(?i)\b(hvb\.[a-z0-9_-]{138,212})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "hvb", +] + +[[rules]] +description = "Vault Service Token" +id = "vault-service-token" +regex = '''(?i)\b(hvs\.[a-z0-9_-]{90,100})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +keywords = [ + "hvs", +] + +[[rules]] +description = "Yandex Access Token" +id = "yandex-access-token" +regex = '''(?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(t1\.[A-Z0-9a-z_-]+[=]{0,2}\.[A-Z0-9a-z_-]{86}[=]{0,2})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "yandex", +] + +[[rules]] +description = "Yandex API Key" +id = "yandex-api-key" +regex = '''(?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(AQVN[A-Za-z0-9_\-]{35,38})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "yandex", +] + +[[rules]] +description = "Yandex AWS Access Token" +id = "yandex-aws-access-token" +regex = '''(?i)(?:yandex)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}(YC[a-zA-Z0-9_\-]{38})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "yandex", +] + +[[rules]] +description = "Zendesk Secret Key" +id = "zendesk-secret-key" +regex = '''(?i)(?:zendesk)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-z0-9]{40})(?:['|\"|\n|\r|\s|\x60|;]|$)''' +secretGroup = 1 +keywords = [ + "zendesk", +] + + diff --git a/cli/config/rule.go b/cli/config/rule.go new file mode 100644 index 000000000..b7c8c1518 --- /dev/null +++ b/cli/config/rule.go @@ -0,0 +1,43 @@ +package config + +import ( + "regexp" +) + +// Rules contain information that define details on how to detect secrets +type Rule struct { + // Description is the description of the rule. + Description string + + // RuleID is a unique identifier for this rule + RuleID string + + // Entropy is a float representing the minimum shannon + // entropy a regex group must have to be considered a secret. + Entropy float64 + + // SecretGroup is an int used to extract secret from regex + // match and used as the group that will have its entropy + // checked if `entropy` is set. + SecretGroup int + + // Regex is a golang regular expression used to detect secrets. + Regex *regexp.Regexp + + // Path is a golang regular expression used to + // filter secrets by path + Path *regexp.Regexp + + // Tags is an array of strings used for metadata + // and reporting purposes. + Tags []string + + // Keywords are used for pre-regex check filtering. Rules that contain + // keywords will perform a quick string compare check to make sure the + // keyword(s) are in the content being scanned. + Keywords []string + + // Allowlist allows a rule to be ignored for specific + // regexes, paths, and/or commits + Allowlist Allowlist +} diff --git a/cli/config/utils.go b/cli/config/utils.go new file mode 100644 index 000000000..ada6ff0fe --- /dev/null +++ b/cli/config/utils.go @@ -0,0 +1,24 @@ +package config + +import ( + "regexp" +) + +func anyRegexMatch(f string, res []*regexp.Regexp) bool { + for _, re := range res { + if regexMatched(f, re) { + return true + } + } + return false +} + +func regexMatched(f string, re *regexp.Regexp) bool { + if re == nil { + return false + } + if re.FindString(f) != "" { + return true + } + return false +} diff --git a/cli/detect/baseline.go b/cli/detect/baseline.go new file mode 100644 index 000000000..bd4c25665 --- /dev/null +++ b/cli/detect/baseline.go @@ -0,0 +1,87 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + "encoding/json" + "fmt" + "io" + "os" + + "github.com/rs/zerolog/log" + + "github.com/Infisical/infisical-merge/report" +) + +func IsNew(finding report.Finding, baseline []report.Finding) bool { + // Explicitly testing each property as it gives significantly better performance in comparison to cmp.Equal(). Drawback is that + // the code requires maintanance if/when the Finding struct changes + for _, b := range baseline { + + if finding.Author == b.Author && + finding.Commit == b.Commit && + finding.Date == b.Date && + finding.Description == b.Description && + finding.Email == b.Email && + finding.EndColumn == b.EndColumn && + finding.EndLine == b.EndLine && + finding.Entropy == b.Entropy && + finding.File == b.File && + // Omit checking finding.Fingerprint - if the format of the fingerprint changes, the users will see unexpected behaviour + finding.Match == b.Match && + finding.Message == b.Message && + finding.RuleID == b.RuleID && + finding.Secret == b.Secret && + finding.StartColumn == b.StartColumn && + finding.StartLine == b.StartLine { + return false + } + } + return true +} + +func LoadBaseline(baselinePath string) ([]report.Finding, error) { + var previousFindings []report.Finding + jsonFile, err := os.Open(baselinePath) + if err != nil { + return nil, fmt.Errorf("could not open %s", baselinePath) + } + + defer func() { + if cerr := jsonFile.Close(); cerr != nil { + log.Warn().Err(cerr).Msg("problem closing jsonFile handle") + } + }() + + bytes, err := io.ReadAll(jsonFile) + if err != nil { + return nil, fmt.Errorf("could not read data from the file %s", baselinePath) + } + + err = json.Unmarshal(bytes, &previousFindings) + if err != nil { + return nil, fmt.Errorf("the format of the file %s is not supported", baselinePath) + } + + return previousFindings, nil +} diff --git a/cli/detect/baseline_test.go b/cli/detect/baseline_test.go new file mode 100644 index 000000000..91d2eb72e --- /dev/null +++ b/cli/detect/baseline_test.go @@ -0,0 +1,160 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + "errors" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/Infisical/infisical-merge/report" +) + +func TestIsNew(t *testing.T) { + tests := []struct { + findings report.Finding + baseline []report.Finding + expect bool + }{ + { + findings: report.Finding{ + Author: "a", + Commit: "0000", + }, + baseline: []report.Finding{ + { + Author: "a", + Commit: "0000", + }, + }, + expect: false, + }, + { + findings: report.Finding{ + Author: "a", + Commit: "0000", + }, + baseline: []report.Finding{ + { + Author: "a", + Commit: "0002", + }, + }, + expect: true, + }, + { + findings: report.Finding{ + Author: "a", + Commit: "0000", + Tags: []string{"a", "b"}, + }, + baseline: []report.Finding{ + { + Author: "a", + Commit: "0000", + Tags: []string{"a", "c"}, + }, + }, + expect: false, // Updated tags doesn't make it a new finding + }, + } + for _, test := range tests { + assert.Equal(t, test.expect, IsNew(test.findings, test.baseline)) + } +} + +func TestFileLoadBaseline(t *testing.T) { + tests := []struct { + Filename string + ExpectedError error + }{ + { + Filename: "../testdata/baseline/baseline.csv", + ExpectedError: errors.New("the format of the file ../testdata/baseline/baseline.csv is not supported"), + }, + { + Filename: "../testdata/baseline/baseline.sarif", + ExpectedError: errors.New("the format of the file ../testdata/baseline/baseline.sarif is not supported"), + }, + { + Filename: "../testdata/baseline/notfound.json", + ExpectedError: errors.New("could not open ../testdata/baseline/notfound.json"), + }, + } + + for _, test := range tests { + _, err := LoadBaseline(test.Filename) + assert.Equal(t, test.ExpectedError.Error(), err.Error()) + } +} + +func TestIgnoreIssuesInBaseline(t *testing.T) { + tests := []struct { + findings []report.Finding + baseline []report.Finding + expectCount int + }{ + { + findings: []report.Finding{ + { + Author: "a", + Commit: "5", + }, + }, + baseline: []report.Finding{ + { + Author: "a", + Commit: "5", + }, + }, + expectCount: 0, + }, + { + findings: []report.Finding{ + { + Author: "a", + Commit: "5", + Fingerprint: "a", + }, + }, + baseline: []report.Finding{ + { + Author: "a", + Commit: "5", + Fingerprint: "b", + }, + }, + expectCount: 0, + }, + } + + for _, test := range tests { + d, _ := NewDetectorDefaultConfig() + d.baseline = test.baseline + for _, finding := range test.findings { + d.addFinding(finding) + } + assert.Equal(t, test.expectCount, len(d.findings)) + } +} diff --git a/cli/detect/detect.go b/cli/detect/detect.go new file mode 100644 index 000000000..84f058d4b --- /dev/null +++ b/cli/detect/detect.go @@ -0,0 +1,652 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + "bufio" + "context" + "fmt" + "io" + "io/fs" + "os" + "path/filepath" + "regexp" + "strings" + "sync" + + "github.com/h2non/filetype" + + "github.com/Infisical/infisical-merge/config" + "github.com/Infisical/infisical-merge/detect/git" + "github.com/Infisical/infisical-merge/report" + + "github.com/fatih/semgroup" + "github.com/gitleaks/go-gitdiff/gitdiff" + ahocorasick "github.com/petar-dambovaliev/aho-corasick" + "github.com/rs/zerolog/log" + "github.com/spf13/viper" +) + +// Type used to differentiate between git scan types: +// $ gitleaks detect +// $ gitleaks protect +// $ gitleaks protect staged +type GitScanType int + +const ( + DetectType GitScanType = iota + ProtectType + ProtectStagedType + + gitleaksAllowSignature = "infisical-scan:ignore" +) + +// Detector is the main detector struct +type Detector struct { + // Config is the configuration for the detector + Config config.Config + + // Redact is a flag to redact findings. This is exported + // so users using gitleaks as a library can set this flag + // without calling `detector.Start(cmd *cobra.Command)` + Redact bool + + // verbose is a flag to print findings + Verbose bool + + // files larger than this will be skipped + MaxTargetMegaBytes int + + // followSymlinks is a flag to enable scanning symlink files + FollowSymlinks bool + + // NoColor is a flag to disable color output + NoColor bool + + // commitMap is used to keep track of commits that have been scanned. + // This is only used for logging purposes and git scans. + commitMap map[string]bool + + // findingMutex is to prevent concurrent access to the + // findings slice when adding findings. + findingMutex *sync.Mutex + + // findings is a slice of report.Findings. This is the result + // of the detector's scan which can then be used to generate a + // report. + findings []report.Finding + + // prefilter is a ahocorasick struct used for doing efficient string + // matching given a set of words (keywords from the rules in the config) + prefilter ahocorasick.AhoCorasick + + // a list of known findings that should be ignored + baseline []report.Finding + + // path to baseline + baselinePath string + + // gitleaksIgnore + gitleaksIgnore map[string]bool +} + +// Fragment contains the data to be scanned +type Fragment struct { + // Raw is the raw content of the fragment + Raw string + + // FilePath is the path to the file if applicable + FilePath string + SymlinkFile string + + // CommitSHA is the SHA of the commit if applicable + CommitSHA string + + // newlineIndices is a list of indices of newlines in the raw content. + // This is used to calculate the line location of a finding + newlineIndices [][]int + + // keywords is a map of all the keywords contain within the contents + // of this fragment + keywords map[string]bool +} + +// NewDetector creates a new detector with the given config +func NewDetector(cfg config.Config) *Detector { + builder := ahocorasick.NewAhoCorasickBuilder(ahocorasick.Opts{ + AsciiCaseInsensitive: true, + MatchOnlyWholeWords: false, + MatchKind: ahocorasick.LeftMostLongestMatch, + DFA: true, + }) + + return &Detector{ + commitMap: make(map[string]bool), + gitleaksIgnore: make(map[string]bool), + findingMutex: &sync.Mutex{}, + findings: make([]report.Finding, 0), + Config: cfg, + prefilter: builder.Build(cfg.Keywords), + } +} + +// NewDetectorDefaultConfig creates a new detector with the default config +func NewDetectorDefaultConfig() (*Detector, error) { + viper.SetConfigType("toml") + err := viper.ReadConfig(strings.NewReader(config.DefaultConfig)) + if err != nil { + return nil, err + } + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + return nil, err + } + cfg, err := vc.Translate() + if err != nil { + return nil, err + } + return NewDetector(cfg), nil +} + +func (d *Detector) AddGitleaksIgnore(gitleaksIgnorePath string) error { + log.Debug().Msg("found .gitleaksignore file") + file, err := os.Open(gitleaksIgnorePath) + + if err != nil { + return err + } + + // https://github.com/securego/gosec/issues/512 + defer func() { + if err := file.Close(); err != nil { + log.Warn().Msgf("Error closing .gitleaksignore file: %s\n", err) + } + }() + scanner := bufio.NewScanner(file) + + for scanner.Scan() { + d.gitleaksIgnore[scanner.Text()] = true + } + return nil +} + +func (d *Detector) AddBaseline(baselinePath string, source string) error { + if baselinePath != "" { + absoluteSource, err := filepath.Abs(source) + if err != nil { + return err + } + + absoluteBaseline, err := filepath.Abs(baselinePath) + if err != nil { + return err + } + + relativeBaseline, err := filepath.Rel(absoluteSource, absoluteBaseline) + if err != nil { + return err + } + + baseline, err := LoadBaseline(baselinePath) + if err != nil { + return err + } + + d.baseline = baseline + baselinePath = relativeBaseline + + } + + d.baselinePath = baselinePath + return nil +} + +// DetectBytes scans the given bytes and returns a list of findings +func (d *Detector) DetectBytes(content []byte) []report.Finding { + return d.DetectString(string(content)) +} + +// DetectString scans the given string and returns a list of findings +func (d *Detector) DetectString(content string) []report.Finding { + return d.Detect(Fragment{ + Raw: content, + }) +} + +// detectRule scans the given fragment for the given rule and returns a list of findings +func (d *Detector) detectRule(fragment Fragment, rule config.Rule) []report.Finding { + var findings []report.Finding + + // check if filepath or commit is allowed for this rule + if rule.Allowlist.CommitAllowed(fragment.CommitSHA) || + rule.Allowlist.PathAllowed(fragment.FilePath) { + return findings + } + + if rule.Path != nil && rule.Regex == nil { + // Path _only_ rule + if rule.Path.Match([]byte(fragment.FilePath)) { + finding := report.Finding{ + Description: rule.Description, + File: fragment.FilePath, + SymlinkFile: fragment.SymlinkFile, + RuleID: rule.RuleID, + Match: fmt.Sprintf("file detected: %s", fragment.FilePath), + Tags: rule.Tags, + } + return append(findings, finding) + } + } else if rule.Path != nil { + // if path is set _and_ a regex is set, then we need to check both + // so if the path does not match, then we should return early and not + // consider the regex + if !rule.Path.Match([]byte(fragment.FilePath)) { + return findings + } + } + + // if path only rule, skip content checks + if rule.Regex == nil { + return findings + } + + // If flag configure and raw data size bigger then the flag + if d.MaxTargetMegaBytes > 0 { + rawLength := len(fragment.Raw) / 1000000 + if rawLength > d.MaxTargetMegaBytes { + log.Debug().Msgf("skipping file: %s scan due to size: %d", fragment.FilePath, rawLength) + return findings + } + } + + matchIndices := rule.Regex.FindAllStringIndex(fragment.Raw, -1) + for _, matchIndex := range matchIndices { + // extract secret from match + secret := strings.Trim(fragment.Raw[matchIndex[0]:matchIndex[1]], "\n") + + // determine location of match. Note that the location + // in the finding will be the line/column numbers of the _match_ + // not the _secret_, which will be different if the secretGroup + // value is set for this rule + loc := location(fragment, matchIndex) + + if matchIndex[1] > loc.endLineIndex { + loc.endLineIndex = matchIndex[1] + } + + finding := report.Finding{ + Description: rule.Description, + File: fragment.FilePath, + SymlinkFile: fragment.SymlinkFile, + RuleID: rule.RuleID, + StartLine: loc.startLine, + EndLine: loc.endLine, + StartColumn: loc.startColumn, + EndColumn: loc.endColumn, + Secret: secret, + Match: secret, + Tags: rule.Tags, + Line: fragment.Raw[loc.startLineIndex:loc.endLineIndex], + } + + if strings.Contains(fragment.Raw[loc.startLineIndex:loc.endLineIndex], + gitleaksAllowSignature) { + continue + } + + // extract secret from secret group if set + if rule.SecretGroup != 0 { + groups := rule.Regex.FindStringSubmatch(secret) + if len(groups) <= rule.SecretGroup || len(groups) == 0 { + // Config validation should prevent this + continue + } + secret = groups[rule.SecretGroup] + finding.Secret = secret + } + + // check if the regexTarget is defined in the allowlist "regexes" entry + allowlistTarget := finding.Secret + switch rule.Allowlist.RegexTarget { + case "match": + allowlistTarget = finding.Match + case "line": + allowlistTarget = finding.Line + } + + globalAllowlistTarget := finding.Secret + switch d.Config.Allowlist.RegexTarget { + case "match": + globalAllowlistTarget = finding.Match + case "line": + globalAllowlistTarget = finding.Line + } + if rule.Allowlist.RegexAllowed(allowlistTarget) || + d.Config.Allowlist.RegexAllowed(globalAllowlistTarget) { + continue + } + + // check if the secret is in the list of stopwords + if rule.Allowlist.ContainsStopWord(finding.Secret) || + d.Config.Allowlist.ContainsStopWord(finding.Secret) { + continue + } + + // check entropy + entropy := shannonEntropy(finding.Secret) + finding.Entropy = float32(entropy) + if rule.Entropy != 0.0 { + if entropy <= rule.Entropy { + // entropy is too low, skip this finding + continue + } + // NOTE: this is a goofy hack to get around the fact there golang's regex engine + // does not support positive lookaheads. Ideally we would want to add a + // restriction on generic rules regex that requires the secret match group + // contains both numbers and alphabetical characters, not just alphabetical characters. + // What this bit of code does is check if the ruleid is prepended with "generic" and enforces the + // secret contains both digits and alphabetical characters. + // TODO: this should be replaced with stop words + if strings.HasPrefix(rule.RuleID, "generic") { + if !containsDigit(secret) { + continue + } + } + } + + findings = append(findings, finding) + } + return findings +} + +// GitScan accepts a *gitdiff.File channel which contents a git history generated from +// the output of `git log -p ...`. startGitScan will look at each file (patch) in the history +// and determine if the patch contains any findings. +func (d *Detector) DetectGit(source string, logOpts string, gitScanType GitScanType) ([]report.Finding, error) { + var ( + gitdiffFiles <-chan *gitdiff.File + err error + ) + switch gitScanType { + case DetectType: + gitdiffFiles, err = git.GitLog(source, logOpts) + if err != nil { + return d.findings, err + } + case ProtectType: + gitdiffFiles, err = git.GitDiff(source, false) + if err != nil { + return d.findings, err + } + case ProtectStagedType: + gitdiffFiles, err = git.GitDiff(source, true) + if err != nil { + return d.findings, err + } + } + + s := semgroup.NewGroup(context.Background(), 4) + + for gitdiffFile := range gitdiffFiles { + gitdiffFile := gitdiffFile + + // skip binary files + if gitdiffFile.IsBinary || gitdiffFile.IsDelete { + continue + } + + // Check if commit is allowed + commitSHA := "" + if gitdiffFile.PatchHeader != nil { + commitSHA = gitdiffFile.PatchHeader.SHA + if d.Config.Allowlist.CommitAllowed(gitdiffFile.PatchHeader.SHA) { + continue + } + } + d.addCommit(commitSHA) + + s.Go(func() error { + for _, textFragment := range gitdiffFile.TextFragments { + if textFragment == nil { + return nil + } + + fragment := Fragment{ + Raw: textFragment.Raw(gitdiff.OpAdd), + CommitSHA: commitSHA, + FilePath: gitdiffFile.NewName, + } + + for _, finding := range d.Detect(fragment) { + d.addFinding(augmentGitFinding(finding, textFragment, gitdiffFile)) + } + } + return nil + }) + } + + if err := s.Wait(); err != nil { + return d.findings, err + } + log.Info().Msgf("%d commits scanned.", len(d.commitMap)) + log.Debug().Msg("Note: this number might be smaller than expected due to commits with no additions") + if git.ErrEncountered { + return d.findings, fmt.Errorf("%s", "git error encountered, see logs") + } + return d.findings, nil +} + +type scanTarget struct { + Path string + Symlink string +} + +// DetectFiles accepts a path to a source directory or file and begins a scan of the +// file or directory. +func (d *Detector) DetectFiles(source string) ([]report.Finding, error) { + s := semgroup.NewGroup(context.Background(), 4) + paths := make(chan scanTarget) + s.Go(func() error { + defer close(paths) + return filepath.Walk(source, + func(path string, fInfo os.FileInfo, err error) error { + if err != nil { + return err + } + if fInfo.Name() == ".git" && fInfo.IsDir() { + return filepath.SkipDir + } + if fInfo.Size() == 0 { + return nil + } + if fInfo.Mode().IsRegular() { + paths <- scanTarget{ + Path: path, + Symlink: "", + } + } + if fInfo.Mode().Type() == fs.ModeSymlink && d.FollowSymlinks { + realPath, err := filepath.EvalSymlinks(path) + if err != nil { + return err + } + realPathFileInfo, _ := os.Stat(realPath) + if realPathFileInfo.IsDir() { + log.Debug().Msgf("found symlinked directory: %s -> %s [skipping]", path, realPath) + return nil + } + paths <- scanTarget{ + Path: realPath, + Symlink: path, + } + } + return nil + }) + }) + for pa := range paths { + p := pa + s.Go(func() error { + b, err := os.ReadFile(p.Path) + if err != nil { + return err + } + + mimetype, err := filetype.Match(b) + if err != nil { + return err + } + if mimetype.MIME.Type == "application" { + return nil // skip binary files + } + + fragment := Fragment{ + Raw: string(b), + FilePath: p.Path, + } + if p.Symlink != "" { + fragment.SymlinkFile = p.Symlink + } + for _, finding := range d.Detect(fragment) { + // need to add 1 since line counting starts at 1 + finding.EndLine++ + finding.StartLine++ + d.addFinding(finding) + } + + return nil + }) + } + + if err := s.Wait(); err != nil { + return d.findings, err + } + + return d.findings, nil +} + +// DetectReader accepts an io.Reader and a buffer size for the reader in KB +func (d *Detector) DetectReader(r io.Reader, bufSize int) ([]report.Finding, error) { + reader := bufio.NewReader(r) + buf := make([]byte, 0, 1000*bufSize) + findings := []report.Finding{} + + for { + n, err := reader.Read(buf[:cap(buf)]) + buf = buf[:n] + if err != nil { + if err != io.EOF { + return findings, err + } + break + } + + fragment := Fragment{ + Raw: string(buf), + } + for _, finding := range d.Detect(fragment) { + findings = append(findings, finding) + if d.Verbose { + printFinding(finding, d.NoColor) + } + } + } + + return findings, nil +} + +// Detect scans the given fragment and returns a list of findings +func (d *Detector) Detect(fragment Fragment) []report.Finding { + var findings []report.Finding + + // initiate fragment keywords + fragment.keywords = make(map[string]bool) + + // check if filepath is allowed + if fragment.FilePath != "" && (d.Config.Allowlist.PathAllowed(fragment.FilePath) || + fragment.FilePath == d.Config.Path || (d.baselinePath != "" && fragment.FilePath == d.baselinePath)) { + return findings + } + + // add newline indices for location calculation in detectRule + fragment.newlineIndices = regexp.MustCompile("\n").FindAllStringIndex(fragment.Raw, -1) + + // build keyword map for prefiltering rules + normalizedRaw := strings.ToLower(fragment.Raw) + matches := d.prefilter.FindAll(normalizedRaw) + for _, m := range matches { + fragment.keywords[normalizedRaw[m.Start():m.End()]] = true + } + + for _, rule := range d.Config.Rules { + if len(rule.Keywords) == 0 { + // if not keywords are associated with the rule always scan the + // fragment using the rule + findings = append(findings, d.detectRule(fragment, rule)...) + continue + } + fragmentContainsKeyword := false + // check if keywords are in the fragment + for _, k := range rule.Keywords { + if _, ok := fragment.keywords[strings.ToLower(k)]; ok { + fragmentContainsKeyword = true + } + } + if fragmentContainsKeyword { + findings = append(findings, d.detectRule(fragment, rule)...) + } + } + return filter(findings, d.Redact) +} + +// addFinding synchronously adds a finding to the findings slice +func (d *Detector) addFinding(finding report.Finding) { + if finding.Commit == "" { + finding.Fingerprint = fmt.Sprintf("%s:%s:%d", finding.File, finding.RuleID, finding.StartLine) + } else { + finding.Fingerprint = fmt.Sprintf("%s:%s:%s:%d", finding.Commit, finding.File, finding.RuleID, finding.StartLine) + } + // check if we should ignore this finding + if _, ok := d.gitleaksIgnore[finding.Fingerprint]; ok { + log.Debug().Msgf("ignoring finding with Fingerprint %s", + finding.Fingerprint) + return + } + + if d.baseline != nil && !IsNew(finding, d.baseline) { + log.Debug().Msgf("baseline duplicate -- ignoring finding with Fingerprint %s", finding.Fingerprint) + return + } + + d.findingMutex.Lock() + d.findings = append(d.findings, finding) + if d.Verbose { + printFinding(finding, d.NoColor) + } + d.findingMutex.Unlock() +} + +// addCommit synchronously adds a commit to the commit slice +func (d *Detector) addCommit(commit string) { + d.commitMap[commit] = true +} diff --git a/cli/detect/detect_test.go b/cli/detect/detect_test.go new file mode 100644 index 000000000..5a0f50828 --- /dev/null +++ b/cli/detect/detect_test.go @@ -0,0 +1,754 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + "fmt" + "os" + "path/filepath" + "testing" + + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + + "github.com/Infisical/infisical-merge/config" + "github.com/Infisical/infisical-merge/report" +) + +const configPath = "../testdata/config/" +const repoBasePath = "../testdata/repos/" + +func TestDetect(t *testing.T) { + tests := []struct { + cfgName string + baselinePath string + fragment Fragment + // NOTE: for expected findings, all line numbers will be 0 + // because line deltas are added _after_ the finding is created. + // I.e, if the finding is from a --no-git file, the line number will be + // increase by 1 in DetectFromFiles(). If the finding is from git, + // the line number will be increased by the patch delta. + expectedFindings []report.Finding + wantError error + }{ + { + cfgName: "simple", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OKIA\ // infisical-scan:ignore"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `awsToken := \ + + \"AKIALALEMEL33243OKIA\ // infisical-scan:ignore" + + `, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OKIA\" + + // infisical-scan:ignore" + + `, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + Secret: "AKIALALEMEL33243OKIA", + Match: "AKIALALEMEL33243OKIA", + File: "tmp.go", + Line: `awsToken := \"AKIALALEMEL33243OKIA\"`, + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + StartLine: 0, + EndLine: 0, + StartColumn: 15, + EndColumn: 34, + Entropy: 3.1464393, + }, + }, + }, + { + cfgName: "escaped_character_group", + fragment: Fragment{ + Raw: `pypi-AgEIcHlwaS5vcmcAAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAAB`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{ + { + Description: "PyPI upload token", + Secret: "pypi-AgEIcHlwaS5vcmcAAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAAB", + Match: "pypi-AgEIcHlwaS5vcmcAAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAAB", + Line: `pypi-AgEIcHlwaS5vcmcAAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAA-AAAAAAAAAAB`, + File: "tmp.go", + RuleID: "pypi-upload-token", + Tags: []string{"key", "pypi"}, + StartLine: 0, + EndLine: 0, + StartColumn: 1, + EndColumn: 86, + Entropy: 1.9606875, + }, + }, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + Secret: "AKIALALEMEL33243OLIA", + Match: "AKIALALEMEL33243OLIA", + Line: `awsToken := \"AKIALALEMEL33243OLIA\"`, + File: "tmp.go", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + StartLine: 0, + EndLine: 0, + StartColumn: 15, + EndColumn: 34, + Entropy: 3.0841837, + }, + }, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef;`, + FilePath: "tmp.sh", + }, + expectedFindings: []report.Finding{ + { + Description: "Sidekiq Secret", + Match: "BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef;", + Secret: "cafebabe:deadbeef", + Line: `export BUNDLE_ENTERPRISE__CONTRIBSYS__COM=cafebabe:deadbeef;`, + File: "tmp.sh", + RuleID: "sidekiq-secret", + Tags: []string{}, + Entropy: 2.6098502, + StartLine: 0, + EndLine: 0, + StartColumn: 8, + EndColumn: 60, + }, + }, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `echo hello1; export BUNDLE_ENTERPRISE__CONTRIBSYS__COM="cafebabe:deadbeef" && echo hello2`, + FilePath: "tmp.sh", + }, + expectedFindings: []report.Finding{ + { + Description: "Sidekiq Secret", + Match: "BUNDLE_ENTERPRISE__CONTRIBSYS__COM=\"cafebabe:deadbeef\"", + Secret: "cafebabe:deadbeef", + File: "tmp.sh", + Line: `echo hello1; export BUNDLE_ENTERPRISE__CONTRIBSYS__COM="cafebabe:deadbeef" && echo hello2`, + RuleID: "sidekiq-secret", + Tags: []string{}, + Entropy: 2.6098502, + StartLine: 0, + EndLine: 0, + StartColumn: 21, + EndColumn: 74, + }, + }, + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `url = "http://cafeb4b3:d3adb33f@enterprise.contribsys.com:80/path?param1=true¶m2=false#heading1"`, + FilePath: "tmp.sh", + }, + expectedFindings: []report.Finding{ + { + Description: "Sidekiq Sensitive URL", + Match: "http://cafeb4b3:d3adb33f@enterprise.contribsys.com:", + Secret: "cafeb4b3:d3adb33f", + File: "tmp.sh", + Line: `url = "http://cafeb4b3:d3adb33f@enterprise.contribsys.com:80/path?param1=true¶m2=false#heading1"`, + RuleID: "sidekiq-sensitive-url", + Tags: []string{}, + Entropy: 2.984234, + StartLine: 0, + EndLine: 0, + StartColumn: 8, + EndColumn: 58, + }, + }, + }, + { + cfgName: "allow_aws_re", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "allow_path", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "allow_commit", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: "tmp.go", + CommitSHA: "allowthiscommit", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "entropy_group", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{ + { + Description: "Discord API key", + Match: "Discord_Public_Key = \"e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5\"", + Secret: "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5", + Line: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + File: "tmp.go", + RuleID: "discord-api-key", + Tags: []string{}, + Entropy: 3.7906237, + StartLine: 0, + EndLine: 0, + StartColumn: 7, + EndColumn: 93, + }, + }, + }, + { + cfgName: "generic_with_py_path", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "generic_with_py_path", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.py", + }, + expectedFindings: []report.Finding{ + { + Description: "Generic API Key", + Match: "Key = \"e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5\"", + Secret: "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5", + Line: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + File: "tmp.py", + RuleID: "generic-api-key", + Tags: []string{}, + Entropy: 3.7906237, + StartLine: 0, + EndLine: 0, + StartColumn: 22, + EndColumn: 93, + }, + }, + }, + { + cfgName: "path_only", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.py", + }, + expectedFindings: []report.Finding{ + { + Description: "Python Files", + Match: "file detected: tmp.py", + File: "tmp.py", + RuleID: "python-files-only", + Tags: []string{}, + }, + }, + }, + { + cfgName: "bad_entropy_group", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + wantError: fmt.Errorf("Discord API key invalid regex secret group 5, max regex secret group 3"), + }, + { + cfgName: "simple", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: filepath.Join(configPath, "simple.toml"), + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "allow_global_aws_re", + fragment: Fragment{ + Raw: `awsToken := \"AKIALALEMEL33243OLIA\"`, + FilePath: "tmp.go", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "generic_with_py_path", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "load2523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: "tmp.py", + }, + expectedFindings: []report.Finding{}, + }, + { + cfgName: "path_only", + baselinePath: ".baseline.json", + fragment: Fragment{ + Raw: `const Discord_Public_Key = "e7322523fb86ed64c836a979cf8465fbd436378c653c1db38f9ae87bc62a6fd5"`, + FilePath: ".baseline.json", + }, + expectedFindings: []report.Finding{}, + }, + } + + for _, tt := range tests { + viper.Reset() + viper.AddConfigPath(configPath) + viper.SetConfigName(tt.cfgName) + viper.SetConfigType("toml") + err := viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, err := vc.Translate() + cfg.Path = filepath.Join(configPath, tt.cfgName+".toml") + if tt.wantError != nil { + if err == nil { + t.Errorf("expected error") + } + assert.Equal(t, tt.wantError, err) + } + d := NewDetector(cfg) + d.baselinePath = tt.baselinePath + + findings := d.Detect(tt.fragment) + assert.ElementsMatch(t, tt.expectedFindings, findings) + } +} + +// TestFromGit tests the FromGit function +func TestFromGit(t *testing.T) { + tests := []struct { + cfgName string + source string + logOpts string + expectedFindings []report.Finding + }{ + { + source: filepath.Join(repoBasePath, "small"), + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + StartLine: 20, + EndLine: 20, + StartColumn: 19, + EndColumn: 38, + Line: "\n awsToken := \"AKIALALEMEL33243OLIA\"", + Secret: "AKIALALEMEL33243OLIA", + Match: "AKIALALEMEL33243OLIA", + File: "main.go", + Date: "2021-11-02T23:37:53Z", + Commit: "1b6da43b82b22e4eaa10bcf8ee591e91abbfc587", + Author: "Zachary Rice", + Email: "zricer@protonmail.com", + Message: "Accidentally add a secret", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + Entropy: 3.0841837, + Fingerprint: "1b6da43b82b22e4eaa10bcf8ee591e91abbfc587:main.go:aws-access-key:20", + }, + { + Description: "AWS Access Key", + StartLine: 9, + EndLine: 9, + StartColumn: 17, + EndColumn: 36, + Secret: "AKIALALEMEL33243OLIA", + Match: "AKIALALEMEL33243OLIA", + Line: "\n\taws_token := \"AKIALALEMEL33243OLIA\"", + File: "foo/foo.go", + Date: "2021-11-02T23:48:06Z", + Commit: "491504d5a31946ce75e22554cc34203d8e5ff3ca", + Author: "Zach Rice", + Email: "zricer@protonmail.com", + Message: "adding foo package with secret", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + Entropy: 3.0841837, + Fingerprint: "491504d5a31946ce75e22554cc34203d8e5ff3ca:foo/foo.go:aws-access-key:9", + }, + }, + }, + { + source: filepath.Join(repoBasePath, "small"), + logOpts: "--all foo...", + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + StartLine: 9, + EndLine: 9, + StartColumn: 17, + EndColumn: 36, + Secret: "AKIALALEMEL33243OLIA", + Line: "\n\taws_token := \"AKIALALEMEL33243OLIA\"", + Match: "AKIALALEMEL33243OLIA", + Date: "2021-11-02T23:48:06Z", + File: "foo/foo.go", + Commit: "491504d5a31946ce75e22554cc34203d8e5ff3ca", + Author: "Zach Rice", + Email: "zricer@protonmail.com", + Message: "adding foo package with secret", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + Entropy: 3.0841837, + Fingerprint: "491504d5a31946ce75e22554cc34203d8e5ff3ca:foo/foo.go:aws-access-key:9", + }, + }, + }, + } + + err := moveDotGit("dotGit", ".git") + if err != nil { + t.Fatal(err) + } + defer func() { + if err := moveDotGit(".git", "dotGit"); err != nil { + t.Error(err) + } + }() + + for _, tt := range tests { + + viper.AddConfigPath(configPath) + viper.SetConfigName("simple") + viper.SetConfigType("toml") + err = viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, err := vc.Translate() + if err != nil { + t.Error(err) + } + detector := NewDetector(cfg) + findings, err := detector.DetectGit(tt.source, tt.logOpts, DetectType) + if err != nil { + t.Error(err) + } + + for _, f := range findings { + f.Match = "" // remove lines cause copying and pasting them has some wack formatting + } + assert.ElementsMatch(t, tt.expectedFindings, findings) + } +} +func TestFromGitStaged(t *testing.T) { + tests := []struct { + cfgName string + source string + logOpts string + expectedFindings []report.Finding + }{ + { + source: filepath.Join(repoBasePath, "staged"), + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + StartLine: 7, + EndLine: 7, + StartColumn: 18, + EndColumn: 37, + Line: "\n\taws_token2 := \"AKIALALEMEL33243OLIA\" // this one is not", + Match: "AKIALALEMEL33243OLIA", + Secret: "AKIALALEMEL33243OLIA", + File: "api/api.go", + SymlinkFile: "", + Commit: "", + Entropy: 3.0841837, + Author: "", + Email: "", + Date: "0001-01-01T00:00:00Z", + Message: "", + Tags: []string{ + "key", + "AWS", + }, + RuleID: "aws-access-key", + Fingerprint: "api/api.go:aws-access-key:7", + }, + }, + }, + } + + err := moveDotGit("dotGit", ".git") + if err != nil { + t.Fatal(err) + } + defer func() { + if err := moveDotGit(".git", "dotGit"); err != nil { + t.Error(err) + } + }() + + for _, tt := range tests { + + viper.AddConfigPath(configPath) + viper.SetConfigName("simple") + viper.SetConfigType("toml") + err = viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, err := vc.Translate() + if err != nil { + t.Error(err) + } + detector := NewDetector(cfg) + detector.AddGitleaksIgnore(filepath.Join(tt.source, ".gitleaksignore")) + findings, err := detector.DetectGit(tt.source, tt.logOpts, ProtectStagedType) + if err != nil { + t.Error(err) + } + + for _, f := range findings { + f.Match = "" // remove lines cause copying and pasting them has some wack formatting + } + assert.ElementsMatch(t, tt.expectedFindings, findings) + } +} + +// TestFromFiles tests the FromFiles function +func TestFromFiles(t *testing.T) { + tests := []struct { + cfgName string + source string + expectedFindings []report.Finding + }{ + { + source: filepath.Join(repoBasePath, "nogit"), + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + StartLine: 20, + EndLine: 20, + StartColumn: 16, + EndColumn: 35, + Match: "AKIALALEMEL33243OLIA", + Secret: "AKIALALEMEL33243OLIA", + Line: "\n\tawsToken := \"AKIALALEMEL33243OLIA\"", + File: "../testdata/repos/nogit/main.go", + SymlinkFile: "", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + Entropy: 3.0841837, + Fingerprint: "../testdata/repos/nogit/main.go:aws-access-key:20", + }, + }, + }, + { + source: filepath.Join(repoBasePath, "nogit", "main.go"), + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "AWS Access Key", + StartLine: 20, + EndLine: 20, + StartColumn: 16, + EndColumn: 35, + Match: "AKIALALEMEL33243OLIA", + Secret: "AKIALALEMEL33243OLIA", + Line: "\n\tawsToken := \"AKIALALEMEL33243OLIA\"", + File: "../testdata/repos/nogit/main.go", + RuleID: "aws-access-key", + Tags: []string{"key", "AWS"}, + Entropy: 3.0841837, + Fingerprint: "../testdata/repos/nogit/main.go:aws-access-key:20", + }, + }, + }, + } + + for _, tt := range tests { + viper.AddConfigPath(configPath) + viper.SetConfigName("simple") + viper.SetConfigType("toml") + err := viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, _ := vc.Translate() + detector := NewDetector(cfg) + detector.FollowSymlinks = true + findings, err := detector.DetectFiles(tt.source) + if err != nil { + t.Error(err) + } + + assert.ElementsMatch(t, tt.expectedFindings, findings) + } +} + +func TestDetectWithSymlinks(t *testing.T) { + tests := []struct { + cfgName string + source string + expectedFindings []report.Finding + }{ + { + source: filepath.Join(repoBasePath, "symlinks/file_symlink"), + cfgName: "simple", + expectedFindings: []report.Finding{ + { + Description: "Asymmetric Private Key", + StartLine: 1, + EndLine: 1, + StartColumn: 1, + EndColumn: 35, + Match: "-----BEGIN OPENSSH PRIVATE KEY-----", + Secret: "-----BEGIN OPENSSH PRIVATE KEY-----", + Line: "-----BEGIN OPENSSH PRIVATE KEY-----", + File: "../testdata/repos/symlinks/source_file/id_ed25519", + SymlinkFile: "../testdata/repos/symlinks/file_symlink/symlinked_id_ed25519", + RuleID: "apkey", + Tags: []string{"key", "AsymmetricPrivateKey"}, + Entropy: 3.587164, + Fingerprint: "../testdata/repos/symlinks/source_file/id_ed25519:apkey:1", + }, + }, + }, + } + + for _, tt := range tests { + viper.AddConfigPath(configPath) + viper.SetConfigName("simple") + viper.SetConfigType("toml") + err := viper.ReadInConfig() + if err != nil { + t.Error(err) + } + + var vc config.ViperConfig + err = viper.Unmarshal(&vc) + if err != nil { + t.Error(err) + } + cfg, _ := vc.Translate() + detector := NewDetector(cfg) + detector.FollowSymlinks = true + findings, err := detector.DetectFiles(tt.source) + if err != nil { + t.Error(err) + } + assert.ElementsMatch(t, tt.expectedFindings, findings) + } +} + +func moveDotGit(from, to string) error { + repoDirs, err := os.ReadDir("../testdata/repos") + if err != nil { + return err + } + for _, dir := range repoDirs { + if to == ".git" { + _, err := os.Stat(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), "dotGit")) + if os.IsNotExist(err) { + // dont want to delete the only copy of .git accidentally + continue + } + os.RemoveAll(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), ".git")) + } + if !dir.IsDir() { + continue + } + _, err := os.Stat(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), from)) + if os.IsNotExist(err) { + continue + } + + err = os.Rename(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), from), + fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), to)) + if err != nil { + return err + } + } + return nil +} diff --git a/cli/detect/git/git.go b/cli/detect/git/git.go new file mode 100644 index 000000000..6eb5e9d6d --- /dev/null +++ b/cli/detect/git/git.go @@ -0,0 +1,143 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package git + +import ( + "bufio" + "io" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/gitleaks/go-gitdiff/gitdiff" + "github.com/rs/zerolog/log" +) + +var ErrEncountered bool + +// GitLog returns a channel of gitdiff.File objects from the +// git log -p command for the given source. +func GitLog(source string, logOpts string) (<-chan *gitdiff.File, error) { + sourceClean := filepath.Clean(source) + var cmd *exec.Cmd + if logOpts != "" { + args := []string{"-C", sourceClean, "log", "-p", "-U0"} + args = append(args, strings.Split(logOpts, " ")...) + cmd = exec.Command("git", args...) + } else { + cmd = exec.Command("git", "-C", sourceClean, "log", "-p", "-U0", + "--full-history", "--all") + } + + log.Debug().Msgf("executing: %s", cmd.String()) + + stdout, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + stderr, err := cmd.StderrPipe() + if err != nil { + return nil, err + } + + go listenForStdErr(stderr) + + if err := cmd.Start(); err != nil { + return nil, err + } + // HACK: to avoid https://github.com/zricethezav/gitleaks/issues/722 + time.Sleep(50 * time.Millisecond) + + return gitdiff.Parse(cmd, stdout) +} + +// GitDiff returns a channel of gitdiff.File objects from +// the git diff command for the given source. +func GitDiff(source string, staged bool) (<-chan *gitdiff.File, error) { + sourceClean := filepath.Clean(source) + var cmd *exec.Cmd + cmd = exec.Command("git", "-C", sourceClean, "diff", "-U0", ".") + if staged { + cmd = exec.Command("git", "-C", sourceClean, "diff", "-U0", + "--staged", ".") + } + log.Debug().Msgf("executing: %s", cmd.String()) + + stdout, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + stderr, err := cmd.StderrPipe() + if err != nil { + return nil, err + } + + go listenForStdErr(stderr) + + if err := cmd.Start(); err != nil { + return nil, err + } + // HACK: to avoid https://github.com/zricethezav/gitleaks/issues/722 + time.Sleep(50 * time.Millisecond) + + return gitdiff.Parse(cmd, stdout) +} + +// listenForStdErr listens for stderr output from git and prints it to stdout +// then exits with exit code 1 +func listenForStdErr(stderr io.ReadCloser) { + scanner := bufio.NewScanner(stderr) + for scanner.Scan() { + // if git throws one of the following errors: + // + // exhaustive rename detection was skipped due to too many files. + // you may want to set your diff.renameLimit variable to at least + // (some large number) and retry the command. + // + // inexact rename detection was skipped due to too many files. + // you may want to set your diff.renameLimit variable to at least + // (some large number) and retry the command. + // + // we skip exiting the program as git log -p/git diff will continue + // to send data to stdout and finish executing. This next bit of + // code prevents gitleaks from stopping mid scan if this error is + // encountered + if strings.Contains(scanner.Text(), + "exhaustive rename detection was skipped") || + strings.Contains(scanner.Text(), + "inexact rename detection was skipped") || + strings.Contains(scanner.Text(), + "you may want to set your diff.renameLimit") { + log.Warn().Msg(scanner.Text()) + } else { + log.Error().Msgf("[git] %s", scanner.Text()) + + // asynchronously set this error flag to true so that we can + // capture a log message and exit with a non-zero exit code + // This value should get set before the `git` command exits so it's + // safe-ish, although I know I know, bad practice. + ErrEncountered = true + } + } +} diff --git a/cli/detect/git/git_test.go b/cli/detect/git/git_test.go new file mode 100644 index 000000000..3a2ea9c35 --- /dev/null +++ b/cli/detect/git/git_test.go @@ -0,0 +1,158 @@ +package git_test + +// TODO: commenting out this test for now because it's flaky. Alternatives to consider to get this working: +// -- use `git stash` instead of `restore()` + +// const repoBasePath = "../../testdata/repos/" + +// const expectPath = "../../testdata/expected/" + +// func TestGitLog(t *testing.T) { +// tests := []struct { +// source string +// logOpts string +// expected string +// }{ +// { +// source: filepath.Join(repoBasePath, "small"), +// expected: filepath.Join(expectPath, "git", "small.txt"), +// }, +// { +// source: filepath.Join(repoBasePath, "small"), +// expected: filepath.Join(expectPath, "git", "small-branch-foo.txt"), +// logOpts: "--all foo...", +// }, +// } + +// err := moveDotGit("dotGit", ".git") +// if err != nil { +// t.Fatal(err) +// } +// defer func() { +// if err = moveDotGit(".git", "dotGit"); err != nil { +// t.Fatal(err) +// } +// }() + +// for _, tt := range tests { +// files, err := git.GitLog(tt.source, tt.logOpts) +// if err != nil { +// t.Error(err) +// } + +// var diffSb strings.Builder +// for f := range files { +// for _, tf := range f.TextFragments { +// diffSb.WriteString(tf.Raw(gitdiff.OpAdd)) +// } +// } + +// expectedBytes, err := os.ReadFile(tt.expected) +// if err != nil { +// t.Error(err) +// } +// expected := string(expectedBytes) +// if expected != diffSb.String() { +// // write string builder to .got file using os.Create +// err = os.WriteFile(strings.Replace(tt.expected, ".txt", ".got.txt", 1), []byte(diffSb.String()), 0644) +// if err != nil { +// t.Error(err) +// } +// t.Error("expected: ", expected, "got: ", diffSb.String()) +// } +// } +// } + +// func TestGitDiff(t *testing.T) { +// tests := []struct { +// source string +// expected string +// additions string +// target string +// }{ +// { +// source: filepath.Join(repoBasePath, "small"), +// expected: "this line is added\nand another one", +// additions: "this line is added\nand another one", +// target: filepath.Join(repoBasePath, "small", "main.go"), +// }, +// } + +// err := moveDotGit("dotGit", ".git") +// if err != nil { +// t.Fatal(err) +// } +// defer func() { +// if err = moveDotGit(".git", "dotGit"); err != nil { +// t.Fatal(err) +// } +// }() + +// for _, tt := range tests { +// noChanges, err := os.ReadFile(tt.target) +// if err != nil { +// t.Error(err) +// } +// err = os.WriteFile(tt.target, []byte(tt.additions), 0644) +// if err != nil { +// restore(tt.target, noChanges, t) +// t.Error(err) +// } + +// files, err := git.GitDiff(tt.source, false) +// if err != nil { +// restore(tt.target, noChanges, t) +// t.Error(err) +// } + +// for f := range files { +// sb := strings.Builder{} +// for _, tf := range f.TextFragments { +// sb.WriteString(tf.Raw(gitdiff.OpAdd)) +// } +// if sb.String() != tt.expected { +// restore(tt.target, noChanges, t) +// t.Error("expected: ", tt.expected, "got: ", sb.String()) +// } +// } +// restore(tt.target, noChanges, t) +// } +// } + +// func restore(path string, data []byte, t *testing.T) { +// err := os.WriteFile(path, data, 0644) +// if err != nil { +// t.Fatal(err) +// } +// } + +// func moveDotGit(from, to string) error { +// repoDirs, err := os.ReadDir("../../testdata/repos") +// if err != nil { +// return err +// } +// for _, dir := range repoDirs { +// if to == ".git" { +// _, err := os.Stat(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), "dotGit")) +// if os.IsNotExist(err) { +// // dont want to delete the only copy of .git accidentally +// continue +// } +// os.RemoveAll(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), ".git")) +// } +// if !dir.IsDir() { +// continue +// } +// _, err := os.Stat(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), from)) +// if os.IsNotExist(err) { +// continue +// } + +// err = os.Rename(fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), from), +// fmt.Sprintf("%s/%s/%s", repoBasePath, dir.Name(), to)) +// if err != nil { +// return err +// } +// } +// return nil +// } diff --git a/cli/detect/location.go b/cli/detect/location.go new file mode 100644 index 000000000..418af83f6 --- /dev/null +++ b/cli/detect/location.go @@ -0,0 +1,101 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +// Location represents a location in a file +type Location struct { + startLine int + endLine int + startColumn int + endColumn int + startLineIndex int + endLineIndex int +} + +func location(fragment Fragment, matchIndex []int) Location { + var ( + prevNewLine int + location Location + lineSet bool + _lineNum int + ) + + start := matchIndex[0] + end := matchIndex[1] + + // default startLineIndex to 0 + location.startLineIndex = 0 + + // Fixes: https://github.com/zricethezav/gitleaks/issues/1037 + // When a fragment does NOT have any newlines, a default "newline" + // will be counted to make the subsequent location calculation logic work + // for fragments will no newlines. + if len(fragment.newlineIndices) == 0 { + fragment.newlineIndices = [][]int{ + {len(fragment.Raw), len(fragment.Raw) + 1}, + } + } + + for lineNum, pair := range fragment.newlineIndices { + _lineNum = lineNum + newLineByteIndex := pair[0] + if prevNewLine <= start && start < newLineByteIndex { + lineSet = true + location.startLine = lineNum + location.endLine = lineNum + location.startColumn = (start - prevNewLine) + 1 // +1 because counting starts at 1 + location.startLineIndex = prevNewLine + location.endLineIndex = newLineByteIndex + } + if prevNewLine < end && end <= newLineByteIndex { + location.endLine = lineNum + location.endColumn = (end - prevNewLine) + location.endLineIndex = newLineByteIndex + } + prevNewLine = pair[0] + } + + if !lineSet { + // if lines never get set then that means the secret is most likely + // on the last line of the diff output and the diff output does not have + // a newline + location.startColumn = (start - prevNewLine) + 1 // +1 because counting starts at 1 + location.endColumn = (end - prevNewLine) + location.startLine = _lineNum + 1 + location.endLine = _lineNum + 1 + + // search for new line byte index + i := 0 + for end+i < len(fragment.Raw) { + if fragment.Raw[end+i] == '\n' { + break + } + if fragment.Raw[end+i] == '\r' { + break + } + i++ + } + location.endLineIndex = end + i + } + return location +} diff --git a/cli/detect/location_test.go b/cli/detect/location_test.go new file mode 100644 index 000000000..f76a6f814 --- /dev/null +++ b/cli/detect/location_test.go @@ -0,0 +1,82 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + "testing" +) + +// TestGetLocation tests the getLocation function. +func TestGetLocation(t *testing.T) { + tests := []struct { + linePairs [][]int + start int + end int + wantLocation Location + }{ + { + linePairs: [][]int{ + {0, 39}, + {40, 55}, + {56, 57}, + }, + start: 35, + end: 38, + wantLocation: Location{ + startLine: 1, + startColumn: 36, + endLine: 1, + endColumn: 38, + startLineIndex: 0, + endLineIndex: 40, + }, + }, + { + linePairs: [][]int{ + {0, 39}, + {40, 55}, + {56, 57}, + }, + start: 40, + end: 44, + wantLocation: Location{ + startLine: 2, + startColumn: 1, + endLine: 2, + endColumn: 4, + startLineIndex: 40, + endLineIndex: 56, + }, + }, + } + + for _, test := range tests { + loc := location(Fragment{newlineIndices: test.linePairs}, []int{test.start, test.end}) + if loc != test.wantLocation { + t.Errorf("\nstartLine %d\nstartColumn: %d\nendLine: %d\nendColumn: %d\nstartLineIndex: %d\nendlineIndex %d", + loc.startLine, loc.startColumn, loc.endLine, loc.endColumn, loc.startLineIndex, loc.endLineIndex) + + t.Error("got", loc, "want", test.wantLocation) + } + } +} diff --git a/cli/detect/utils.go b/cli/detect/utils.go new file mode 100644 index 000000000..462716239 --- /dev/null +++ b/cli/detect/utils.go @@ -0,0 +1,211 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package detect + +import ( + // "encoding/json" + "fmt" + "math" + "strings" + "time" + + "github.com/charmbracelet/lipgloss" + + "github.com/Infisical/infisical-merge/report" + + "github.com/gitleaks/go-gitdiff/gitdiff" + "github.com/rs/zerolog/log" +) + +// augmentGitFinding updates the start and end line numbers of a finding to include the +// delta from the git diff +func augmentGitFinding(finding report.Finding, textFragment *gitdiff.TextFragment, f *gitdiff.File) report.Finding { + if !strings.HasPrefix(finding.Match, "file detected") { + finding.StartLine += int(textFragment.NewPosition) + finding.EndLine += int(textFragment.NewPosition) + } + + if f.PatchHeader != nil { + finding.Commit = f.PatchHeader.SHA + finding.Message = f.PatchHeader.Message() + if f.PatchHeader.Author != nil { + finding.Author = f.PatchHeader.Author.Name + finding.Email = f.PatchHeader.Author.Email + } + finding.Date = f.PatchHeader.AuthorDate.UTC().Format(time.RFC3339) + } + return finding +} + +// shannonEntropy calculates the entropy of data using the formula defined here: +// https://en.wiktionary.org/wiki/Shannon_entropy +// Another way to think about what this is doing is calculating the number of bits +// needed to on average encode the data. So, the higher the entropy, the more random the data, the +// more bits needed to encode that data. +func shannonEntropy(data string) (entropy float64) { + if data == "" { + return 0 + } + + charCounts := make(map[rune]int) + for _, char := range data { + charCounts[char]++ + } + + invLength := 1.0 / float64(len(data)) + for _, count := range charCounts { + freq := float64(count) * invLength + entropy -= freq * math.Log2(freq) + } + + return entropy +} + +// filter will dedupe and redact findings +func filter(findings []report.Finding, redact bool) []report.Finding { + var retFindings []report.Finding + for _, f := range findings { + include := true + if strings.Contains(strings.ToLower(f.RuleID), "generic") { + for _, fPrime := range findings { + if f.StartLine == fPrime.StartLine && + f.Commit == fPrime.Commit && + f.RuleID != fPrime.RuleID && + strings.Contains(fPrime.Secret, f.Secret) && + !strings.Contains(strings.ToLower(fPrime.RuleID), "generic") { + + genericMatch := strings.Replace(f.Match, f.Secret, "REDACTED", -1) + betterMatch := strings.Replace(fPrime.Match, fPrime.Secret, "REDACTED", -1) + log.Trace().Msgf("skipping %s finding (%s), %s rule takes precendence (%s)", f.RuleID, genericMatch, fPrime.RuleID, betterMatch) + include = false + break + } + } + } + + if redact { + f.Redact() + } + if include { + retFindings = append(retFindings, f) + } + } + return retFindings +} + +func printFinding(f report.Finding, noColor bool) { + // trim all whitespace and tabs + f.Line = strings.TrimSpace(f.Line) + f.Secret = strings.TrimSpace(f.Secret) + f.Match = strings.TrimSpace(f.Match) + + isFileMatch := strings.HasPrefix(f.Match, "file detected:") + skipColor := noColor + finding := "" + var secret lipgloss.Style + + // Matches from filenames do not have a |line| or |secret| + if !isFileMatch { + matchInLineIDX := strings.Index(f.Line, f.Match) + secretInMatchIdx := strings.Index(f.Match, f.Secret) + + skipColor = false + + if matchInLineIDX == -1 || noColor { + skipColor = true + matchInLineIDX = 0 + } + + start := f.Line[0:matchInLineIDX] + startMatchIdx := 0 + if matchInLineIDX > 20 { + startMatchIdx = matchInLineIDX - 20 + start = "..." + f.Line[startMatchIdx:matchInLineIDX] + } + + matchBeginning := lipgloss.NewStyle().SetString(f.Match[0:secretInMatchIdx]).Foreground(lipgloss.Color("#f5d445")) + secret = lipgloss.NewStyle().SetString(f.Secret). + Bold(true). + Italic(true). + Foreground(lipgloss.Color("#f05c07")) + matchEnd := lipgloss.NewStyle().SetString(f.Match[secretInMatchIdx+len(f.Secret):]).Foreground(lipgloss.Color("#f5d445")) + + lineEndIdx := matchInLineIDX + len(f.Match) + if len(f.Line)-1 <= lineEndIdx { + lineEndIdx = len(f.Line) - 1 + } + + lineEnd := f.Line[lineEndIdx:] + + if len(f.Secret) > 100 { + secret = lipgloss.NewStyle().SetString(f.Secret[0:100] + "..."). + Bold(true). + Italic(true). + Foreground(lipgloss.Color("#f05c07")) + } + if len(lineEnd) > 20 { + lineEnd = lineEnd[0:20] + "..." + } + + finding = fmt.Sprintf("%s%s%s%s%s\n", strings.TrimPrefix(strings.TrimLeft(start, " "), "\n"), matchBeginning, secret, matchEnd, lineEnd) + } + + if skipColor || isFileMatch { + fmt.Printf("%-12s %s\n", "Finding:", f.Match) + fmt.Printf("%-12s %s\n", "Secret:", f.Secret) + } else { + fmt.Printf("%-12s %s", "Finding:", finding) + fmt.Printf("%-12s %s\n", "Secret:", secret) + } + + fmt.Printf("%-12s %s\n", "RuleID:", f.RuleID) + fmt.Printf("%-12s %f\n", "Entropy:", f.Entropy) + if f.File == "" { + fmt.Println("") + return + } + fmt.Printf("%-12s %s\n", "File:", f.File) + fmt.Printf("%-12s %d\n", "Line:", f.StartLine) + if f.Commit == "" { + fmt.Printf("%-12s %s\n", "Fingerprint:", f.Fingerprint) + fmt.Println("") + return + } + fmt.Printf("%-12s %s\n", "Commit:", f.Commit) + fmt.Printf("%-12s %s\n", "Author:", f.Author) + fmt.Printf("%-12s %s\n", "Email:", f.Email) + fmt.Printf("%-12s %s\n", "Date:", f.Date) + fmt.Printf("%-12s %s\n", "Fingerprint:", f.Fingerprint) + fmt.Println("") +} + +func containsDigit(s string) bool { + for _, c := range s { + switch c { + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + return true + } + + } + return false +} diff --git a/cli/go.mod b/cli/go.mod index d1aadd208..640e6dc0c 100644 --- a/cli/go.mod +++ b/cli/go.mod @@ -4,12 +4,20 @@ go 1.19 require ( github.com/99designs/keyring v1.2.2 + github.com/charmbracelet/lipgloss v0.5.0 + github.com/fatih/semgroup v1.2.0 + github.com/gitleaks/go-gitdiff v0.8.0 + github.com/h2non/filetype v1.1.3 github.com/mattn/go-isatty v0.0.14 github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a github.com/muesli/mango-cobra v1.2.0 github.com/muesli/reflow v0.3.0 github.com/muesli/roff v0.1.0 + github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 + github.com/rs/zerolog v1.26.1 github.com/spf13/cobra v1.6.1 + github.com/spf13/viper v1.8.1 + github.com/stretchr/testify v1.8.0 golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d golang.org/x/term v0.5.0 ) @@ -19,22 +27,42 @@ require ( github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef // indirect github.com/chzyer/readline v1.5.1 // indirect github.com/danieljoos/wincred v1.1.2 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/denisbrodbeck/machineid v1.0.1 // indirect github.com/dvsekhvalnov/jose2go v1.5.0 // indirect + github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-openapi/errors v0.20.2 // indirect github.com/go-openapi/strfmt v0.21.3 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect + github.com/magiconair/properties v1.8.5 // indirect github.com/mattn/go-colorable v0.1.9 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mitchellh/mapstructure v1.3.3 // indirect + github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/mtibben/percent v0.2.1 // indirect github.com/muesli/mango v0.1.0 // indirect github.com/muesli/mango-pflag v0.1.0 // indirect + github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 // indirect github.com/oklog/ulid v1.3.1 // indirect + github.com/pelletier/go-toml v1.9.3 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a // indirect github.com/rivo/uniseg v0.2.0 // indirect + github.com/spf13/afero v1.6.0 // indirect + github.com/spf13/cast v1.3.1 // indirect + github.com/spf13/jwalterweatherman v1.1.0 // indirect + github.com/subosito/gotenv v1.2.0 // indirect + github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect go.mongodb.org/mongo-driver v1.10.0 // indirect golang.org/x/net v0.7.0 // indirect + golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect golang.org/x/sys v0.5.0 // indirect + golang.org/x/text v0.7.0 // indirect + gopkg.in/ini.v1 v1.62.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) require ( @@ -43,6 +71,5 @@ require ( github.com/inconshreveable/mousetrap v1.0.1 // indirect github.com/jedib0t/go-pretty v4.3.0+incompatible github.com/manifoldco/promptui v0.9.0 - github.com/sirupsen/logrus v1.9.0 github.com/spf13/pflag v1.0.5 // indirect ) diff --git a/cli/go.sum b/cli/go.sum index 2b514ea6e..574452d45 100644 --- a/cli/go.sum +++ b/cli/go.sum @@ -1,9 +1,59 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= +cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= +cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= +cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= +cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= +cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= +cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= +cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= +cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= +cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= +cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= +cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= +cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= +cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= +cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= +cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= +cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= +cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= +cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= +cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= +cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= +cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= +cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= +cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= +cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= +cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= +cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= +cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= +cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= +cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= +cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= +cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= +cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= +cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= +cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= +cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 h1:/vQbFIOMbk2FiG/kXiLl8BRyzTWDw7gX/Hz7Dd5eDMs= github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4/go.mod h1:hN7oaIRCjzsZ2dE+yG5k+rsdt3qcwykqK6HVGcKwsw4= github.com/99designs/keyring v1.2.2 h1:pZd3neh/EmUzWONb35LxQfvuY7kiSXAq3HQd97+XBn0= github.com/99designs/keyring v1.2.2/go.mod h1:wes/FrByc8j7lFOAGLGSNEg8f/PaI3cgTBqhFkHUrPk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= +github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef h1:46PFijGLmAjMPwCCCo7Jf0W6f9slllCkkv7vyc1yOSg= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= +github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -13,6 +63,13 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= +github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= @@ -20,10 +77,30 @@ github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnG github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisbrodbeck/machineid v1.0.1 h1:geKr9qtkB876mXguW2X6TU4ZynleN6ezuMSRhl4D7AQ= +github.com/denisbrodbeck/machineid v1.0.1/go.mod h1:dJUwb7PTidGDeYyUBmXZ2GphQBbjJCrnectwCyxcUSI= github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= +github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= +github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= +github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/fatih/semgroup v1.2.0 h1:h/OLXwEM+3NNyAdZEpMiH1OzfplU09i2qXPVThGZvyg= +github.com/fatih/semgroup v1.2.0/go.mod h1:1KAD4iIYfXjE4U13B48VM4z9QUwV5Tt8O4rS879kgm8= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gitleaks/go-gitdiff v0.8.0 h1:7aExTZm+K/M/EQKOyYcub8rIAdWK6ONxPGuRzxmWW+0= +github.com/gitleaks/go-gitdiff v0.8.0/go.mod h1:pKz0X4YzCKZs30BL+weqBIG7mx0jl4tF1uXV9ZyNvrA= +github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= +github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-openapi/errors v0.20.2 h1:dxy7PGTqEh94zj2E3h1cUmQQWiM1+aeCROfAr02EmK8= github.com/go-openapi/errors v0.20.2/go.mod h1:cM//ZKUKyO06HSwqAelJ5NsEMMcpa6VpXe8DOa1Mi1M= github.com/go-openapi/strfmt v0.21.3 h1:xwhj5X6CjXEZZHMWy1zKJxvW9AfHC9pkyUjLvHtKG7o= @@ -32,35 +109,153 @@ github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPr github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 h1:ZpnhV/YsD2/4cESfV5+Hoeu/iUR3ruzNvZ+yQfO03a0= github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= +github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= +github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= +github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= +github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= +github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU= github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0= +github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg= +github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY= +github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= +github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/inconshreveable/mousetrap v1.0.1 h1:U3uMjPSQEBMNp1lFxmllqCPM6P5u/Xq7Pgzkat/bFNc= github.com/inconshreveable/mousetrap v1.0.1/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jedib0t/go-pretty v4.3.0+incompatible h1:CGs8AVhEKg/n9YbUenWmNStRW2PHJzaeDodcfvRAbIo= github.com/jedib0t/go-pretty v4.3.0+incompatible/go.mod h1:XemHduiw8R651AF9Pt4FwCTKeG3oo7hrHJAoznj9nag= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= +github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= +github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= +github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U= github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/mtibben/percent v0.2.1 h1:5gssi8Nqo8QU/r2pynCm+hBQHpkB/uNK7BJCFogWdzs= github.com/mtibben/percent v0.2.1/go.mod h1:KG9uO+SZkUp+VkRHsCdYQV3XSZrrSpR3O9ibNBTZrns= @@ -72,75 +267,465 @@ github.com/muesli/mango-cobra v1.2.0 h1:DQvjzAM0PMZr85Iv9LIMaYISpTOliMEg+uMFtNbY github.com/muesli/mango-cobra v1.2.0/go.mod h1:vMJL54QytZAJhCT13LPVDfkvCUJ5/4jNUKF/8NC2UjA= github.com/muesli/mango-pflag v0.1.0 h1:UADqbYgpUyRoBja3g6LUL+3LErjpsOwaC9ywvBWe7Sg= github.com/muesli/mango-pflag v0.1.0/go.mod h1:YEQomTxaCUp8PrbhFh10UfbhbQrM/xJ4i2PB8VTLLW0= +github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/roff v0.1.0 h1:YD0lalCotmYuF5HhZliKWlIx7IEhiXeSfq7hNjFqGF8= github.com/muesli/roff v0.1.0/go.mod h1:pjAHQM9hdUUwm/krAfrLGgJkXJ+YuhtsfZ42kieB2Ig= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0 h1:STjmj0uFfRryL9fzRA/OupNppeAID6QJYPMavTL7jtY= +github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pelletier/go-toml v1.9.3 h1:zeC5b1GviRUyKYd6OJPvBU/mcVDVoL1OhT17FCt5dSQ= +github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= +github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9 h1:lL+y4Xv20pVlCGyLzNHRC0I0rIHhIL1lTvHizoS/dU8= +github.com/petar-dambovaliev/aho-corasick v0.0.0-20211021192214-5ab2d9280aa9/go.mod h1:EHPiTAKtiFmrMldLUNswFwfZ2eJIYBHktdaUTZxYWRw= +github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a h1:Ey0XWvrg6u6hyIn1Kd/jCCmL+bMv9El81tvuGBbxZGg= +github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a/go.mod h1:oa2sAs9tGai3VldabTV0eWejt/O4/OOD7azP8GaikqU= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= -github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= +github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA= github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY= +github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= +github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.8.1 h1:Kq1fyeebqsBfbjZj4EL7gj2IO0mMaiyjYUWcUsl2O44= +github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= +github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g= github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= +github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= +go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= +go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.mongodb.org/mongo-driver v1.10.0 h1:UtV6N5k14upNp4LTduX0QCufG124fSu25Wz9tu94GLg= go.mongodb.org/mongo-driver v1.10.0/go.mod h1:wsihk0Kdgv8Kqu1Anit4sfK+22vSFbUrAVEYRhCXrA8= +go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= +go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= +go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d h1:sK3txAijHtOK88l68nt020reeT1ZdKLIYetKl95FzVY= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= +golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= +golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= +golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= +golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= +golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= +golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= +golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= +golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= +golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= +golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= +golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= +google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= +google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= +google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= +google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= +google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= +google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= +google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= +google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= +google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= +google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= +google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= +google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= +google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= +google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= +google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= +google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= +google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= +google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= +google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= +google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= +google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= +google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= +google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= +google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= +gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= diff --git a/cli/main.go b/cli/main.go index a51661ff6..75152ffc4 100644 --- a/cli/main.go +++ b/cli/main.go @@ -3,8 +3,15 @@ Copyright (c) 2023 Infisical Inc. */ package main -import "github.com/Infisical/infisical-merge/packages/cmd" +import ( + "os" + + "github.com/Infisical/infisical-merge/packages/cmd" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) cmd.Execute() } diff --git a/cli/packages/api/api.go b/cli/packages/api/api.go index f0a347800..5f8bc7aae 100644 --- a/cli/packages/api/api.go +++ b/cli/packages/api/api.go @@ -5,7 +5,7 @@ import ( "github.com/Infisical/infisical-merge/packages/config" "github.com/go-resty/resty/v2" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" ) const USER_AGENT = "cli" @@ -222,7 +222,7 @@ func CallIsAuthenticated(httpClient *resty.Client) bool { } if response.IsError() { - log.Debugln(fmt.Errorf("CallIsAuthenticated: Unsuccessful response: [response=%v]", response)) + log.Debug().Msgf("CallIsAuthenticated: Unsuccessful response: [response=%v]", response) return false } diff --git a/cli/packages/api/model.go b/cli/packages/api/model.go index af8dbc5b4..71354c84c 100644 --- a/cli/packages/api/model.go +++ b/cli/packages/api/model.go @@ -230,19 +230,10 @@ type GetEncryptedSecretsV2Response struct { } type GetServiceTokenDetailsResponse struct { - ID string `json:"_id"` - Name string `json:"name"` - Workspace string `json:"workspace"` - Environment string `json:"environment"` - User struct { - ID string `json:"_id"` - Email string `json:"email"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - V int `json:"__v"` - FirstName string `json:"firstName"` - LastName string `json:"lastName"` - } `json:"user"` + ID string `json:"_id"` + Name string `json:"name"` + Workspace string `json:"workspace"` + Environment string `json:"environment"` ExpiresAt time.Time `json:"expiresAt"` EncryptedKey string `json:"encryptedKey"` Iv string `json:"iv"` diff --git a/cli/packages/cmd/export.go b/cli/packages/cmd/export.go index 07512798b..453d1b75c 100644 --- a/cli/packages/cmd/export.go +++ b/cli/packages/cmd/export.go @@ -11,7 +11,8 @@ import ( "github.com/Infisical/infisical-merge/packages/models" "github.com/Infisical/infisical-merge/packages/util" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -30,11 +31,6 @@ var exportCmd = &cobra.Command{ DisableFlagsInUseLine: true, Example: "infisical export --env=prod --format=json > secrets.json", Args: cobra.NoArgs, - PreRun: func(cmd *cobra.Command, args []string) { - toggleDebug(cmd, args) - // util.RequireLogin() - // util.RequireLocalWorkspaceFile() - }, Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") if !cmd.Flags().Changed("env") { @@ -100,6 +96,8 @@ var exportCmd = &cobra.Command{ } fmt.Print(output) + + Telemetry.CaptureEvent("cli-command:export", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("version", util.CLI_VERSION)) }, } @@ -175,8 +173,7 @@ func formatAsJson(envs []models.SingleEnvironmentVariable) string { // Dump as a json array json, err := json.Marshal(envs) if err != nil { - log.Errorln("Unable to marshal environment variables to JSON") - log.Debugln(err) + log.Err(err).Msgf("Unable to marshal environment variables to JSON") return "" } return string(json) diff --git a/cli/packages/cmd/init.go b/cli/packages/cmd/init.go index 1562f6856..64387a837 100644 --- a/cli/packages/cmd/init.go +++ b/cli/packages/cmd/init.go @@ -12,14 +12,15 @@ import ( "github.com/Infisical/infisical-merge/packages/util" "github.com/go-resty/resty/v2" "github.com/manifoldco/promptui" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) // runCmd represents the run command var initCmd = &cobra.Command{ Use: "init", - Short: "Used to initialize your project with Infisical", + Short: "Used to connect your local project with Infisical project", DisableFlagsInUseLine: true, Example: "infisical init", Args: cobra.ExactArgs(0), @@ -30,8 +31,8 @@ var initCmd = &cobra.Command{ if util.WorkspaceConfigFileExistsInCurrentPath() { shouldOverride, err := shouldOverrideWorkspacePrompt() if err != nil { - log.Errorln("Unable to parse your answer") - log.Debug(err) + log.Error().Msg("Unable to parse your answer") + log.Debug().Err(err) return } @@ -78,6 +79,9 @@ var initCmd = &cobra.Command{ if err != nil { util.HandleError(err) } + + Telemetry.CaptureEvent("cli-command:init", posthog.NewProperties().Set("version", util.CLI_VERSION)) + }, } diff --git a/cli/packages/cmd/logging.go b/cli/packages/cmd/logging.go deleted file mode 100644 index db1afa34f..000000000 --- a/cli/packages/cmd/logging.go +++ /dev/null @@ -1,27 +0,0 @@ -package cmd - -import ( - "fmt" - - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" -) - -var debugLogging bool - -type PlainFormatter struct { -} - -func (f *PlainFormatter) Format(entry *log.Entry) ([]byte, error) { - return []byte(fmt.Sprintf("%s\n", entry.Message)), nil -} -func toggleDebug(cmd *cobra.Command, args []string) { - if debugLogging { - log.Info("Debug logs enabled") - log.SetLevel(log.DebugLevel) - log.SetFormatter(&log.TextFormatter{}) - } else { - plainFormatter := new(PlainFormatter) - log.SetFormatter(plainFormatter) - } -} diff --git a/cli/packages/cmd/login.go b/cli/packages/cmd/login.go index c93af44f5..f20a17853 100644 --- a/cli/packages/cmd/login.go +++ b/cli/packages/cmd/login.go @@ -10,9 +10,11 @@ import ( "errors" "fmt" + "net/url" "regexp" "github.com/Infisical/infisical-merge/packages/api" + "github.com/Infisical/infisical-merge/packages/config" "github.com/Infisical/infisical-merge/packages/crypto" "github.com/Infisical/infisical-merge/packages/models" "github.com/Infisical/infisical-merge/packages/srp" @@ -20,7 +22,8 @@ import ( "github.com/fatih/color" "github.com/go-resty/resty/v2" "github.com/manifoldco/promptui" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "golang.org/x/crypto/argon2" ) @@ -33,23 +36,26 @@ type params struct { keyLength uint32 } +const ADD_USER = "Add a new account login" +const REPLACE_USER = "Override current logged in user" +const EXIT_USER_MENU = "Exit" + // loginCmd represents the login command var loginCmd = &cobra.Command{ Use: "login", Short: "Login into your Infisical account", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Run: func(cmd *cobra.Command, args []string) { currentLoggedInUserDetails, err := util.GetCurrentLoggedInUserDetails() // if the key can't be found or there is an error getting current credentials from key ring, allow them to override if err != nil && (strings.Contains(err.Error(), "The specified item could not be found in the keyring") || strings.Contains(err.Error(), "unable to get key from Keyring") || strings.Contains(err.Error(), "GetUserCredsFromKeyRing")) { - log.Debug(err) + log.Debug().Err(err) } else if err != nil { util.HandleError(err) } if currentLoggedInUserDetails.IsUserLoggedIn && !currentLoggedInUserDetails.LoginExpired && len(currentLoggedInUserDetails.UserCredentials.PrivateKey) != 0 { - shouldOverride, err := shouldOverrideLoginPrompt(currentLoggedInUserDetails.UserCredentials.Email) + shouldOverride, err := userLoginMenu(currentLoggedInUserDetails.UserCredentials.Email) if err != nil { util.HandleError(err) } @@ -59,6 +65,31 @@ var loginCmd = &cobra.Command{ } } + //override domain + domainQuery := true + if config.INFISICAL_URL_MANUAL_OVERRIDE != "" && config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL { + overrideDomain, err := DomainOverridePrompt() + if err != nil { + util.HandleError(err) + } + + //if not override set INFISICAL_URL to exported var + //set domainQuery to false + if !overrideDomain { + domainQuery = false + config.INFISICAL_URL = config.INFISICAL_URL_MANUAL_OVERRIDE + } + + } + + //prompt user to select domain between Infisical cloud and self hosting + if domainQuery { + err = askForDomain() + if err != nil { + util.HandleError(err, "Unable to parse domain url") + } + } + email, password, err := askForLoginCredentials() if err != nil { util.HandleError(err, "Unable to parse email and password for authentication") @@ -66,8 +97,8 @@ var loginCmd = &cobra.Command{ loginOneResponse, loginTwoResponse, err := getFreshUserCredentials(email, password) if err != nil { - log.Infoln("Unable to authenticate with the provided credentials, please try again") - log.Debugln(err) + fmt.Println("Unable to authenticate with the provided credentials, please try again") + log.Debug().Err(err) return } @@ -121,7 +152,7 @@ var loginCmd = &cobra.Command{ var decryptedPrivateKey []byte if loginTwoResponse.EncryptionVersion == 1 { - log.Debug("Login version 1") + log.Debug().Msg("Login version 1") encryptedPrivateKey, _ := base64.StdEncoding.DecodeString(loginTwoResponse.EncryptedPrivateKey) tag, err := base64.StdEncoding.DecodeString(loginTwoResponse.Tag) if err != nil { @@ -144,7 +175,7 @@ var loginCmd = &cobra.Command{ decryptedPrivateKey = computedDecryptedPrivateKey } else if loginTwoResponse.EncryptionVersion == 2 { - log.Debug("Login version 2") + log.Debug().Msg("Login version 2") protectedKey, err := base64.StdEncoding.DecodeString(loginTwoResponse.ProtectedKey) if err != nil { util.HandleError(err) @@ -208,7 +239,7 @@ var loginCmd = &cobra.Command{ } if string(decryptedPrivateKey) == "" || email == "" || loginTwoResponse.Token == "" { - log.Debugf("[decryptedPrivateKey=%s] [email=%s] [loginTwoResponse.Token=%s]", string(decryptedPrivateKey), email, loginTwoResponse.Token) + log.Debug().Msgf("[decryptedPrivateKey=%s] [email=%s] [loginTwoResponse.Token=%s]", string(decryptedPrivateKey), email, loginTwoResponse.Token) util.PrintErrorMessageAndExit("We were unable to fetch required details to complete your login. Run with -d to see more info") } @@ -221,9 +252,9 @@ var loginCmd = &cobra.Command{ err = util.StoreUserCredsInKeyRing(userCredentialsToBeStored) if err != nil { currentVault, _ := util.GetCurrentVaultBackend() - log.Errorf("Unable to store your credentials in system vault [%s]. Rerun with flag -d to see full logs", currentVault) - log.Errorln("To trouble shoot further, read https://infisical.com/docs/cli/faq") - log.Debugln(err) + log.Error().Msgf("Unable to store your credentials in system vault [%s]. Rerun with flag -d to see full logs", currentVault) + log.Error().Msgf("\nTo trouble shoot further, read https://infisical.com/docs/cli/faq") + log.Debug().Err(err) return } @@ -245,6 +276,7 @@ var loginCmd = &cobra.Command{ plainBold.Println("\nQuick links") fmt.Println("- Learn to inject secrets into your application at https://infisical.com/docs/cli/usage") fmt.Println("- Stuck? Join our slack for quick support https://infisical.com/slack") + Telemetry.CaptureEvent("cli-command:login", posthog.NewProperties().Set("infisical-backend", config.INFISICAL_URL).Set("version", util.CLI_VERSION)) }, } @@ -252,6 +284,77 @@ func init() { rootCmd.AddCommand(loginCmd) } +func DomainOverridePrompt() (bool, error) { + const ( + PRESET = "Use Domain" + OVERRIDE = "Change Domain" + ) + + options := []string{PRESET, OVERRIDE} + optionsPrompt := promptui.Select{ + Label: fmt.Sprintf("Current INFISICAL_API_URL Domain Override: %s", config.INFISICAL_URL_MANUAL_OVERRIDE), + Items: options, + Size: 2, + } + + _, selectedOption, err := optionsPrompt.Run() + if err != nil { + return false, err + } + + return selectedOption == OVERRIDE, err +} + +func askForDomain() error { + //query user to choose between Infisical cloud or self hosting + const ( + INFISICAL_CLOUD = "Infisical Cloud" + SELF_HOSTING = "Self Hosting" + ) + + options := []string{INFISICAL_CLOUD, SELF_HOSTING} + optionsPrompt := promptui.Select{ + Label: "Select your hosting option", + Items: options, + Size: 2, + } + + _, selectedHostingOption, err := optionsPrompt.Run() + if err != nil { + return err + } + + if selectedHostingOption == INFISICAL_CLOUD { + //cloud option + config.INFISICAL_URL = util.INFISICAL_DEFAULT_API_URL + return nil + } + + urlValidation := func(input string) error { + _, err := url.ParseRequestURI(input) + if err != nil { + return errors.New("this is an invalid url") + } + return nil + } + + domainPrompt := promptui.Prompt{ + Label: "Domain", + Validate: urlValidation, + Default: "Example - https://my-self-hosted-instance.com/api", + } + + domain, err := domainPrompt.Run() + if err != nil { + return err + } + + //set api url + config.INFISICAL_URL = domain + //return nil + return nil +} + func askForLoginCredentials() (email string, password string, err error) { validateEmail := func(input string) error { matched, err := regexp.MatchString("^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+$", input) @@ -295,7 +398,7 @@ func askForLoginCredentials() (email string, password string, err error) { } func getFreshUserCredentials(email string, password string) (*api.GetLoginOneV2Response, *api.GetLoginTwoV2Response, error) { - log.Debugln("getFreshUserCredentials:", "email", email, "password", password) + log.Debug().Msg(fmt.Sprint("getFreshUserCredentials: ", "email", email, "password: ", password)) httpClient := resty.New() httpClient.SetRetryCount(5) @@ -342,16 +445,18 @@ func getFreshUserCredentials(email string, password string) (*api.GetLoginOneV2R return &loginOneResponseResult, &loginTwoResponseResult, nil } -func shouldOverrideLoginPrompt(currentLoggedInUserEmail string) (bool, error) { +func userLoginMenu(currentLoggedInUserEmail string) (bool, error) { + label := fmt.Sprintf("Current logged in user email: %s on domain: %s", currentLoggedInUserEmail, config.INFISICAL_URL) + prompt := promptui.Select{ - Label: fmt.Sprintf("There seems to be a user already logged in with the email: %s. Would you like to override that login? Select[Yes/No]", currentLoggedInUserEmail), - Items: []string{"No", "Yes"}, + Label: label, + Items: []string{ADD_USER, REPLACE_USER, EXIT_USER_MENU}, } _, result, err := prompt.Run() if err != nil { return false, err } - return result == "Yes", err + return result != EXIT_USER_MENU, err } func generateFromPassword(password string, salt []byte, p *params) (hash []byte, err error) { diff --git a/cli/packages/cmd/pre-commit-script/pre-commit-without-bang.sh b/cli/packages/cmd/pre-commit-script/pre-commit-without-bang.sh new file mode 100644 index 000000000..e47643cc9 --- /dev/null +++ b/cli/packages/cmd/pre-commit-script/pre-commit-without-bang.sh @@ -0,0 +1,20 @@ + + +# MANAGED BY INFISICAL CLI (Do not modify): START +infisicalScanEnabled=$(git config --bool hooks.infisical-scan) + +if [ "$infisicalScanEnabled" != "false" ]; then + infisical scan git-changes -v --staged + exitCode=$? + if [ $exitCode -eq 1 ]; then + echo "Commit blocked: Infisical scan has uncovered secrets in your git commit" + echo "To disable the Infisical scan precommit hook run the following command:" + echo "" + echo " git config hooks.infisical-scan false" + echo "" + exit 1 + fi +else + echo 'Warning: infisical scan precommit disabled' +fi +# MANAGED BY INFISICAL CLI (Do not modify): END \ No newline at end of file diff --git a/cli/packages/cmd/pre-commit-script/pre-commit.sh b/cli/packages/cmd/pre-commit-script/pre-commit.sh new file mode 100644 index 000000000..f899a1a51 --- /dev/null +++ b/cli/packages/cmd/pre-commit-script/pre-commit.sh @@ -0,0 +1,20 @@ +#!/bin/sh + +# MANAGED BY INFISICAL CLI (Do not modify): START +infisicalScanEnabled=$(git config --bool hooks.infisical-scan) + +if [ "$infisicalScanEnabled" != "false" ]; then + infisical scan git-changes -v --staged + exitCode=$? + if [ $exitCode -eq 1 ]; then + echo "Commit blocked: Infisical scan has uncovered secrets in your git commit" + echo "To disable the Infisical scan precommit hook run the following command:" + echo "" + echo " git config hooks.infisical-scan false" + echo "" + exit 1 + fi +else + echo 'Warning: infisical scan precommit disabled' +fi +# MANAGED BY INFISICAL CLI (Do not modify): END \ No newline at end of file diff --git a/cli/packages/cmd/reset.go b/cli/packages/cmd/reset.go index 6c378fd4c..0007f2687 100644 --- a/cli/packages/cmd/reset.go +++ b/cli/packages/cmd/reset.go @@ -7,18 +7,16 @@ import ( "os" "github.com/Infisical/infisical-merge/packages/util" + "github.com/posthog/posthog-go" "github.com/spf13/cobra" ) var resetCmd = &cobra.Command{ Use: "reset", - Short: "Used delete all Infisical related data on your machine", + Short: "Used to delete all Infisical related data on your machine", DisableFlagsInUseLine: true, Example: "infisical reset", Args: cobra.NoArgs, - PreRun: func(cmd *cobra.Command, args []string) { - toggleDebug(cmd, args) - }, Run: func(cmd *cobra.Command, args []string) { // delete config _, pathToDir, err := util.GetFullConfigFilePath() @@ -40,6 +38,7 @@ var resetCmd = &cobra.Command{ util.DeleteBackupSecrets() util.PrintSuccessMessage("Reset successful") + Telemetry.CaptureEvent("cli-command:reset", posthog.NewProperties().Set("version", util.CLI_VERSION)) }, } diff --git a/cli/packages/cmd/root.go b/cli/packages/cmd/root.go index ac827feb3..9c7814ecc 100644 --- a/cli/packages/cmd/root.go +++ b/cli/packages/cmd/root.go @@ -5,13 +5,19 @@ package cmd import ( "os" + "strings" + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" "github.com/Infisical/infisical-merge/packages/config" + "github.com/Infisical/infisical-merge/packages/telemetry" "github.com/Infisical/infisical-merge/packages/util" ) +var Telemetry *telemetry.Telemetry + var rootCmd = &cobra.Command{ Use: "infisical", Short: "Infisical CLI is used to inject environment variables into any process", @@ -30,11 +36,14 @@ func Execute() { } func init() { - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") - rootCmd.PersistentFlags().BoolVarP(&debugLogging, "debug", "d", false, "Enable verbose logging") + cobra.OnInitialize(initLog) + rootCmd.PersistentFlags().StringP("log-level", "l", "info", "log level (trace, debug, info, warn, error, fatal)") + rootCmd.PersistentFlags().Bool("telemetry", true, "Infisical collects non-sensitive telemetry data to enhance features and improve user experience. Participation is voluntary") rootCmd.PersistentFlags().StringVar(&config.INFISICAL_URL, "domain", util.INFISICAL_DEFAULT_API_URL, "Point the CLI to your own backend [can also set via environment variable name: INFISICAL_API_URL]") rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { - util.CheckForUpdate() + if !util.IsRunningInDocker() { + util.CheckForUpdate() + } } // if config.INFISICAL_URL is set to the default value, check if INFISICAL_URL is set in the environment @@ -45,4 +54,30 @@ func init() { } } + isTelemetryOn, _ := rootCmd.PersistentFlags().GetBool("telemetry") + Telemetry = telemetry.NewTelemetry(isTelemetryOn) +} + +func initLog() { + zerolog.SetGlobalLevel(zerolog.InfoLevel) + ll, err := rootCmd.Flags().GetString("log-level") + if err != nil { + log.Fatal().Msg(err.Error()) + } + switch strings.ToLower(ll) { + case "trace": + zerolog.SetGlobalLevel(zerolog.TraceLevel) + case "debug": + zerolog.SetGlobalLevel(zerolog.DebugLevel) + case "info": + zerolog.SetGlobalLevel(zerolog.InfoLevel) + case "warn": + zerolog.SetGlobalLevel(zerolog.WarnLevel) + case "err", "error": + zerolog.SetGlobalLevel(zerolog.ErrorLevel) + case "fatal": + zerolog.SetGlobalLevel(zerolog.FatalLevel) + default: + zerolog.SetGlobalLevel(zerolog.InfoLevel) + } } diff --git a/cli/packages/cmd/run.go b/cli/packages/cmd/run.go index ba60c9fec..afce399d5 100644 --- a/cli/packages/cmd/run.go +++ b/cli/packages/cmd/run.go @@ -15,7 +15,8 @@ import ( "github.com/Infisical/infisical-merge/packages/models" "github.com/Infisical/infisical-merge/packages/util" "github.com/fatih/color" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -28,7 +29,6 @@ var runCmd = &cobra.Command{ Use: "run [any infisical run command flags] -- [your application start command]", Short: "Used to inject environments variables into your application process", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: func(cmd *cobra.Command, args []string) error { // Check if the --command flag has been set commandFlagSet := cmd.Flags().Changed("command") @@ -124,7 +124,9 @@ var runCmd = &cobra.Command{ env = append(env, s) } - log.Debugf("injecting the following environment variables into shell: %v", env) + log.Debug().Msgf("injecting the following environment variables into shell: %v", env) + + Telemetry.CaptureEvent("cli-command:run", posthog.NewProperties().Set("secretsCount", len(secrets)).Set("environment", environmentName).Set("isUsingServiceToken", infisicalToken != "").Set("single-command", strings.Join(args, " ")).Set("multi-command", cmd.Flag("command").Value.String()).Set("version", util.CLI_VERSION)) if cmd.Flags().Changed("command") { command := cmd.Flag("command").Value.String() @@ -217,7 +219,7 @@ func executeMultipleCommandWithEnvs(fullCommand string, secretsCount int, env [] cmd.Env = env color.Green("Injecting %v Infisical secrets into your application process", secretsCount) - log.Debugf("executing command: %s %s %s \n", shell[0], shell[1], fullCommand) + log.Debug().Msgf("executing command: %s %s %s \n", shell[0], shell[1], fullCommand) return execCmd(cmd) } diff --git a/cli/packages/cmd/scan.go b/cli/packages/cmd/scan.go new file mode 100644 index 000000000..1226e3319 --- /dev/null +++ b/cli/packages/cmd/scan.go @@ -0,0 +1,586 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package cmd + +import ( + _ "embed" + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "time" + + "github.com/Infisical/infisical-merge/config" + "github.com/Infisical/infisical-merge/detect" + "github.com/Infisical/infisical-merge/packages/util" + "github.com/Infisical/infisical-merge/report" + "github.com/manifoldco/promptui" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +const configDescription = `config file path +order of precedence: +1. --config flag +2. env var INFISICAL_SCAN_CONFIG +3. (--source/-s)/.infisical-scan.toml +If none of the three options are used, then Infisical will use the default scan config` + +//go:embed pre-commit-script/pre-commit.sh +var preCommitTemplate []byte + +//go:embed pre-commit-script/pre-commit-without-bang.sh +var preCommitTemplateAppend []byte + +const ( + defaultHooksPath = ".git/hooks/" + preCommitFile = "pre-commit" +) + +func init() { + // scan flag for only scan command + scanCmd.Flags().String("log-opts", "", "git log options") + scanCmd.Flags().Bool("no-git", false, "treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set") + scanCmd.Flags().Bool("pipe", false, "scan input from stdin, ex: `cat some_file | infisical scan --pipe`") + scanCmd.Flags().Bool("follow-symlinks", false, "scan files that are symlinks to other files") + + // global scan flags + scanCmd.PersistentFlags().StringP("config", "c", "", configDescription) + scanCmd.PersistentFlags().Int("exit-code", 1, "exit code when leaks have been encountered") + scanCmd.PersistentFlags().StringP("source", "s", ".", "path to source") + scanCmd.PersistentFlags().StringP("report-path", "r", "", "report file") + scanCmd.PersistentFlags().StringP("report-format", "f", "json", "output format (json, csv, sarif)") + scanCmd.PersistentFlags().StringP("baseline-path", "b", "", "path to baseline with issues that can be ignored") + scanCmd.PersistentFlags().BoolP("verbose", "v", false, "show verbose output from scan (which file, where in the file, what secret)") + scanCmd.PersistentFlags().BoolP("no-color", "", false, "turn off color for verbose output") + scanCmd.PersistentFlags().Int("max-target-megabytes", 0, "files larger than this will be skipped") + scanCmd.PersistentFlags().Bool("redact", false, "redact secrets from logs and stdout") + + // scan git changes command flags + scanGitChangesCmd.Flags().Bool("staged", false, "detect secrets in a --staged state") + scanGitChangesCmd.Flags().String("log-opts", "", "git log options") + + // find config source + err := viper.BindPFlag("config", scanCmd.PersistentFlags().Lookup("config")) + if err != nil { + log.Fatal().Msgf("err binding config %s", err.Error()) + } + + // add flags to main + scanCmd.AddCommand(scanGitChangesCmd) + rootCmd.AddCommand(scanCmd) + + installCmd.Flags().Bool("pre-commit-hook", false, "installs pre commit hook for Git repository") + scanCmd.AddCommand(installCmd) +} + +func initScanConfig(cmd *cobra.Command) { + cfgPath, err := cmd.Flags().GetString("config") + if err != nil { + log.Fatal().Msg(err.Error()) + } + + if cfgPath != "" { + viper.SetConfigFile(cfgPath) + log.Debug().Msgf("using scan config %s from `--config`", cfgPath) + } else if os.Getenv(config.DefaultScanConfigEnvName) != "" { + envPath := os.Getenv(config.DefaultScanConfigEnvName) + viper.SetConfigFile(envPath) + log.Debug().Msgf("using scan config from %s env var: %s", config.DefaultScanConfigEnvName, envPath) + } else { + source, err := cmd.Flags().GetString("source") + if err != nil { + log.Fatal().Msg(err.Error()) + } + fileInfo, err := os.Stat(source) + if err != nil { + log.Fatal().Msg(err.Error()) + } + + if !fileInfo.IsDir() { + log.Debug().Msgf("unable to load scan config from %s since --source=%s is a file, using default config", + filepath.Join(source, config.DefaultScanConfigFileName), source) + viper.SetConfigType("toml") + if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil { + log.Fatal().Msgf("err reading toml %s", err.Error()) + } + return + } + + if _, err := os.Stat(filepath.Join(source, config.DefaultScanConfigFileName)); os.IsNotExist(err) { + log.Debug().Msgf("no scan config found in path %s, using default scan config", filepath.Join(source, config.DefaultScanConfigFileName)) + viper.SetConfigType("toml") + if err = viper.ReadConfig(strings.NewReader(config.DefaultConfig)); err != nil { + log.Fatal().Msgf("err reading default scan config toml %s", err.Error()) + } + return + } else { + log.Debug().Msgf("using existing scan config %s from `(--source)/%s`", filepath.Join(source, config.DefaultScanConfigFileName), config.DefaultScanConfigFileName) + } + + viper.AddConfigPath(source) + viper.SetConfigName(config.DefaultScanConfigFileName) + viper.SetConfigType("toml") + } + if err := viper.ReadInConfig(); err != nil { + log.Fatal().Msgf("unable to load scan config, err: %s", err) + } +} + +var installCmd = &cobra.Command{ + Use: "install", + Short: "Install scanning scripts and tools. Use --help flag to see all options", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + installPrecommit := cmd.Flags().Changed("pre-commit-hook") + if installPrecommit { + hooksPath, err := getHooksPath() + if err != nil { + fmt.Printf("Error: %s\n", err) + return + } + + if hooksPath != ".git/hooks" { + defaultHookOverride, err := overrideDefaultHooksPath(hooksPath) + if err != nil { + fmt.Printf("Error: %s\n", err) + } + + if defaultHookOverride { + ConfigureGitHooksPath() + + log.Info().Msgf("To switch back previous githooks manager run: git config core.hooksPath %s\n", hooksPath) + return + } else { + log.Warn().Msgf("To automatically configure this hook, you need to switch the path of the Hooks. Alternatively, you can manually configure this hook by setting your pre-commit script to run command [infisical scan git-changes -v --staged].\n") + return + } + } + + err = createOrUpdatePreCommitFile(hooksPath) + if err != nil { + fmt.Printf("Error: %s\n", err) + return + } + + log.Info().Msgf("Pre-commit hook successfully added. Infisical scan should now run on each commit you make\n") + + Telemetry.CaptureEvent("cli-command:install --pre-commit-hook", posthog.NewProperties().Set("version", util.CLI_VERSION)) + + return + } + }} + +var scanCmd = &cobra.Command{ + Use: "scan", + Short: "Scan for leaked secrets in git history, directories, and files", + Run: func(cmd *cobra.Command, args []string) { + initScanConfig(cmd) + + var ( + vc config.ViperConfig + findings []report.Finding + err error + ) + + // Load config + if err = viper.Unmarshal(&vc); err != nil { + log.Fatal().Err(err).Msg("Failed to load config") + } + cfg, err := vc.Translate() + if err != nil { + log.Fatal().Err(err).Msg("Failed to load config") + } + cfg.Path, _ = cmd.Flags().GetString("config") + + // start timer + start := time.Now() + + // Setup detector + detector := detect.NewDetector(cfg) + detector.Config.Path, err = cmd.Flags().GetString("config") + if err != nil { + log.Fatal().Err(err).Msg("") + } + source, err := cmd.Flags().GetString("source") + if err != nil { + log.Fatal().Err(err).Msg("") + } + // if config path is not set, then use the {source}/.infisical-scan.toml path. + // note that there may not be a `{source}/.infisical-scan.toml` file, this is ok. + if detector.Config.Path == "" { + detector.Config.Path = filepath.Join(source, config.DefaultScanConfigFileName) + } + // set verbose flag + if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil { + log.Fatal().Err(err).Msg("") + } + // set redact flag + if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil { + log.Fatal().Err(err).Msg("") + } + if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil { + log.Fatal().Err(err).Msg("") + } + // set color flag + if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil { + log.Fatal().Err(err).Msg("") + } + + if fileExists(filepath.Join(source, config.DefaultInfisicalIgnoreFineName)) { + if err = detector.AddGitleaksIgnore(filepath.Join(source, config.DefaultInfisicalIgnoreFineName)); err != nil { + log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore") + } + } + + // ignore findings from the baseline (an existing report in json format generated earlier) + baselinePath, _ := cmd.Flags().GetString("baseline-path") + if baselinePath != "" { + err = detector.AddBaseline(baselinePath, source) + if err != nil { + log.Error().Msgf("Could not load baseline. The path must point to report generated by `infisical scan` using the default format: %s", err) + } + } + + // set follow symlinks flag + if detector.FollowSymlinks, err = cmd.Flags().GetBool("follow-symlinks"); err != nil { + log.Fatal().Err(err).Msg("") + } + + // set exit code + exitCode, err := cmd.Flags().GetInt("exit-code") + if err != nil { + log.Fatal().Err(err).Msg("could not get exit code") + } + + // determine what type of scan: + // - git: scan the history of the repo + // - no-git: scan files by treating the repo as a plain directory + noGit, err := cmd.Flags().GetBool("no-git") + if err != nil { + log.Fatal().Err(err).Msg("could not call GetBool() for no-git") + } + fromPipe, err := cmd.Flags().GetBool("pipe") + if err != nil { + log.Fatal().Err(err) + } + + log.Info().Msgf("scanning for exposed secrets...") + + // start the detector scan + if noGit { + findings, err = detector.DetectFiles(source) + if err != nil { + // don't exit on error, just log it + log.Error().Err(err).Msg("") + } + } else if fromPipe { + findings, err = detector.DetectReader(os.Stdin, 10) + if err != nil { + // log fatal to exit, no need to continue since a report + // will not be generated when scanning from a pipe...for now + log.Fatal().Err(err).Msg("") + } + } else { + var logOpts string + logOpts, err = cmd.Flags().GetString("log-opts") + if err != nil { + log.Fatal().Err(err).Msg("") + } + findings, err = detector.DetectGit(source, logOpts, detect.DetectType) + if err != nil { + // don't exit on error, just log it + log.Error().Err(err).Msg("") + } + } + + // log info about the scan + if err == nil { + log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start))) + if len(findings) != 0 { + log.Warn().Msgf("leaks found: %d", len(findings)) + } else { + log.Info().Msg("no leaks found") + } + } else { + log.Warn().Msgf("partial scan completed in %s", FormatDuration(time.Since(start))) + if len(findings) != 0 { + log.Warn().Msgf("%d leaks found in partial scan", len(findings)) + } else { + log.Warn().Msg("no leaks found in partial scan") + } + } + + Telemetry.CaptureEvent("cli-command:scan", posthog.NewProperties().Set("risks", len(findings)).Set("version", util.CLI_VERSION)) + + // write report if desired + reportPath, _ := cmd.Flags().GetString("report-path") + ext, _ := cmd.Flags().GetString("report-format") + if reportPath != "" { + if err := report.Write(findings, cfg, ext, reportPath); err != nil { + log.Fatal().Err(err).Msg("could not write") + } + } + + if err != nil { + os.Exit(1) + } + + if len(findings) != 0 { + os.Exit(exitCode) + } + }, +} + +var scanGitChangesCmd = &cobra.Command{ + Use: "git-changes", + Short: "Scan for secrets in uncommitted changes in a git repo", + Run: func(cmd *cobra.Command, args []string) { + initScanConfig(cmd) + + var vc config.ViperConfig + + if err := viper.Unmarshal(&vc); err != nil { + log.Fatal().Err(err).Msg("Failed to load config") + } + cfg, err := vc.Translate() + if err != nil { + log.Fatal().Err(err).Msg("Failed to load config") + } + + cfg.Path, _ = cmd.Flags().GetString("config") + exitCode, _ := cmd.Flags().GetInt("exit-code") + staged, _ := cmd.Flags().GetBool("staged") + start := time.Now() + + // Setup detector + detector := detect.NewDetector(cfg) + detector.Config.Path, err = cmd.Flags().GetString("config") + if err != nil { + log.Fatal().Err(err).Msg("") + } + source, err := cmd.Flags().GetString("source") + if err != nil { + log.Fatal().Err(err).Msg("") + } + // if config path is not set, then use the {source}/.infisical-scan.toml path. + // note that there may not be a `{source}/.infisical-scan.toml` file, this is ok. + if detector.Config.Path == "" { + detector.Config.Path = filepath.Join(source, config.DefaultScanConfigFileName) + } + // set verbose flag + if detector.Verbose, err = cmd.Flags().GetBool("verbose"); err != nil { + log.Fatal().Err(err).Msg("") + } + // set redact flag + if detector.Redact, err = cmd.Flags().GetBool("redact"); err != nil { + log.Fatal().Err(err).Msg("") + } + if detector.MaxTargetMegaBytes, err = cmd.Flags().GetInt("max-target-megabytes"); err != nil { + log.Fatal().Err(err).Msg("") + } + // set color flag + if detector.NoColor, err = cmd.Flags().GetBool("no-color"); err != nil { + log.Fatal().Err(err).Msg("") + } + + if fileExists(filepath.Join(source, config.DefaultInfisicalIgnoreFineName)) { + if err = detector.AddGitleaksIgnore(filepath.Join(source, config.DefaultInfisicalIgnoreFineName)); err != nil { + log.Fatal().Err(err).Msg("could not call AddInfisicalIgnore") + } + } + + // get log options for git scan + logOpts, err := cmd.Flags().GetString("log-opts") + if err != nil { + log.Fatal().Err(err).Msg("") + } + + log.Info().Msgf("scanning for exposed secrets...") + + // start git scan + var findings []report.Finding + if staged { + findings, err = detector.DetectGit(source, logOpts, detect.ProtectStagedType) + } else { + findings, err = detector.DetectGit(source, logOpts, detect.ProtectType) + } + if err != nil { + // don't exit on error, just log it + log.Error().Err(err).Msg("") + } + + // log info about the scan + log.Info().Msgf("scan completed in %s", FormatDuration(time.Since(start))) + if len(findings) != 0 { + log.Warn().Msgf("leaks found: %d", len(findings)) + } else { + log.Info().Msg("no leaks found") + } + + Telemetry.CaptureEvent("cli-command:scan git-changes", posthog.NewProperties().Set("risks", len(findings)).Set("version", util.CLI_VERSION)) + + reportPath, _ := cmd.Flags().GetString("report-path") + ext, _ := cmd.Flags().GetString("report-format") + if reportPath != "" { + if err = report.Write(findings, cfg, ext, reportPath); err != nil { + log.Fatal().Err(err).Msg("") + } + } + if len(findings) != 0 { + os.Exit(exitCode) + } + }, +} + +func fileExists(fileName string) bool { + // check for a .infisicalignore file + info, err := os.Stat(fileName) + if err != nil && !os.IsNotExist(err) { + return false + } + + if info != nil && err == nil { + if !info.IsDir() { + return true + } + } + return false +} + +func FormatDuration(d time.Duration) string { + scale := 100 * time.Second + // look for the max scale that is smaller than d + for scale > d { + scale = scale / 10 + } + return d.Round(scale / 100).String() +} + +func overrideDefaultHooksPath(managedHook string) (bool, error) { + YES := "Yes" + NO := "No" + + options := []string{YES, NO} + optionsPrompt := promptui.Select{ + Label: fmt.Sprintf("Your hooks path is set to [%s] but needs to be [.git/hooks] for automatic configuration. Would you like to switch? ", managedHook), + Items: options, + Size: 2, + } + + _, selectedOption, err := optionsPrompt.Run() + if err != nil { + return false, err + } + + return selectedOption == YES, err +} + +func ConfigureGitHooksPath() { + cmd := exec.Command("git", "config", "core.hooksPath", ".git/hooks") + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + log.Fatal().Msgf("Failed to configure git hooks path: %v", err) + } +} + +// GetGitRoot returns the root directory of the current Git repository. +func GetGitRoot() (string, error) { + cmd := exec.Command("git", "rev-parse", "--show-toplevel") + output, err := cmd.Output() + + if err != nil { + return "", fmt.Errorf("failed to get git root directory: %w", err) + } + + gitRoot := strings.TrimSpace(string(output)) // Remove any trailing newline + return gitRoot, nil +} + +func getHooksPath() (string, error) { + out, err := exec.Command("git", "config", "core.hooksPath").Output() + if err != nil { + if len(out) == 0 { + out = []byte(".git/hooks") // set the default hook + } else { + log.Error().Msgf("Failed to get Git hooks path: %s\nOutput: %s\n", err, out) + } + } + + hooksPath := strings.TrimSpace(string(out)) + return hooksPath, nil +} + +func createOrUpdatePreCommitFile(hooksPath string) error { + // File doesn't exist, create a new one + rootGitRepoPath, err := GetGitRoot() + if err != nil { + return err + } + + filePath := fmt.Sprintf("%s/%s/%s", rootGitRepoPath, hooksPath, preCommitFile) + + _, err = os.Stat(filePath) + if err == nil { + // File already exists, check if it contains the managed comments + content, err := ioutil.ReadFile(filePath) + if err != nil { + return fmt.Errorf("failed to read pre-commit file: %s", err) + } + + if strings.Contains(string(content), "# MANAGED BY INFISICAL CLI (Do not modify): START") && + strings.Contains(string(content), "# MANAGED BY INFISICAL CLI (Do not modify): END") { + return nil + } + + // File already exists, append the template content + file, err := os.OpenFile(filePath, os.O_APPEND|os.O_WRONLY, 0755) + if err != nil { + return fmt.Errorf("failed to open pre-commit file: %s", err) + } + + defer file.Close() + + _, err = file.Write(preCommitTemplateAppend) + if err != nil { + return fmt.Errorf("failed to append to pre-commit file: %s", err) + } + + } else if os.IsNotExist(err) { + err = os.WriteFile(filePath, preCommitTemplate, 0755) + if err != nil { + return fmt.Errorf("failed to create pre-commit file: %s", err) + } + } else { + // Error occurred while checking file status + return fmt.Errorf("failed to check pre-commit file status: %s", err) + } + + return nil +} diff --git a/cli/packages/cmd/secrets.go b/cli/packages/cmd/secrets.go index 69a4539a6..26835eff1 100644 --- a/cli/packages/cmd/secrets.go +++ b/cli/packages/cmd/secrets.go @@ -19,7 +19,8 @@ import ( "github.com/Infisical/infisical-merge/packages/util" "github.com/Infisical/infisical-merge/packages/visualize" "github.com/go-resty/resty/v2" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -28,7 +29,6 @@ var secretsCmd = &cobra.Command{ Short: "Used to create, read update and delete secrets", Use: "secrets", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") @@ -64,6 +64,7 @@ var secretsCmd = &cobra.Command{ } visualize.PrintAllSecretDetails(secrets) + Telemetry.CaptureEvent("cli-command:secrets", posthog.NewProperties().Set("secretCount", len(secrets)).Set("version", util.CLI_VERSION)) }, } @@ -73,7 +74,6 @@ var secretsGetCmd = &cobra.Command{ Use: "get [secrets]", DisableFlagsInUseLine: true, Args: cobra.MinimumNArgs(1), - PreRun: toggleDebug, Run: getSecretsByNames, } @@ -83,7 +83,6 @@ var secretsGenerateExampleEnvCmd = &cobra.Command{ Use: "generate-example-env", DisableFlagsInUseLine: true, Args: cobra.NoArgs, - PreRun: toggleDebug, Run: generateExampleEnv, } @@ -92,7 +91,6 @@ var secretsSetCmd = &cobra.Command{ Short: "Used set secrets", Use: "set [secrets]", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { util.RequireLocalWorkspaceFile() @@ -134,7 +132,7 @@ var secretsSetCmd = &cobra.Command{ currentUsersPrivateKey, _ := base64.StdEncoding.DecodeString(loggedInUserDetails.UserCredentials.PrivateKey) if len(currentUsersPrivateKey) == 0 || len(encryptedWorkspaceKeySenderPublicKey) == 0 { - log.Debugf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) + log.Debug().Msgf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) util.PrintErrorMessageAndExit("Some required user credentials are missing to generate your [plainTextEncryptionKey]. Please run [infisical login] then try again") } @@ -270,6 +268,8 @@ var secretsSetCmd = &cobra.Command{ } visualize.Table(headers, rows) + + Telemetry.CaptureEvent("cli-command:secrets set", posthog.NewProperties().Set("version", util.CLI_VERSION)) }, } @@ -278,7 +278,6 @@ var secretsDeleteCmd = &cobra.Command{ Short: "Used to delete secrets by name", Use: "delete [secrets]", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { environmentName, _ := cmd.Flags().GetString("env") @@ -338,6 +337,7 @@ var secretsDeleteCmd = &cobra.Command{ fmt.Printf("secret name(s) [%v] have been deleted from your project \n", strings.Join(args, ", ")) + Telemetry.CaptureEvent("cli-command:secrets delete", posthog.NewProperties().Set("secretCount", len(secrets)).Set("version", util.CLI_VERSION)) }, } @@ -382,6 +382,7 @@ func getSecretsByNames(cmd *cobra.Command, args []string) { } visualize.PrintAllSecretDetails(requestedSecrets) + Telemetry.CaptureEvent("cli-command:secrets get", posthog.NewProperties().Set("secretCount", len(secrets)).Set("version", util.CLI_VERSION)) } func generateExampleEnv(cmd *cobra.Command, args []string) { @@ -570,6 +571,8 @@ func generateExampleEnv(cmd *cobra.Command, args []string) { fmt.Println(strings.Join(dashedList, "")) } fmt.Println(strings.Join(fullyGeneratedDocuments, "")) + + Telemetry.CaptureEvent("cli-command:generate-example-env", posthog.NewProperties().Set("secretCount", len(secrets)).Set("version", util.CLI_VERSION)) } func CenterString(s string, numStars int) string { diff --git a/cli/packages/cmd/user.go b/cli/packages/cmd/user.go new file mode 100644 index 000000000..0d8f1b214 --- /dev/null +++ b/cli/packages/cmd/user.go @@ -0,0 +1,255 @@ +package cmd + +import ( + "errors" + "net/url" + + "github.com/Infisical/infisical-merge/packages/config" + "github.com/Infisical/infisical-merge/packages/models" + "github.com/Infisical/infisical-merge/packages/util" + "github.com/manifoldco/promptui" + "github.com/posthog/posthog-go" + "github.com/spf13/cobra" +) + +var userCmd = &cobra.Command{ + Use: "user", + Short: "Used to manage user credentials", + DisableFlagsInUseLine: true, + Example: "infisical user", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +var switchCmd = &cobra.Command{ + Use: "switch", + Short: "Used to switch between Infisical profiles", + DisableFlagsInUseLine: true, + Example: "infisical switch", + Args: cobra.ExactArgs(0), + PreRun: func(cmd *cobra.Command, args []string) { + util.RequireLogin() + }, + Run: func(cmd *cobra.Command, args []string) { + //get previous logged in profiles + loggedInProfiles, err := getLoggedInUsers() + if err != nil { + util.HandleError(err, "[infisical user switch]: Unable to get logged Profiles") + } + + //prompt user + profile, err := LoggedInUsersPrompt(loggedInProfiles) + if err != nil { + util.HandleError(err, "[infisical user switch]: Prompt error") + } + + //write to config file + configFile, err := util.GetConfigFile() + if err != nil { + util.HandleError(err, "[infisical user switch]: Unable to get config file") + } + + configFile.LoggedInUserEmail = profile + + //set logged in user domain + ok := util.ConfigContainsEmail(configFile.LoggedInUsers, profile) + + if !ok { + //profile not in loggedInUsers + configFile.LoggedInUsers = append(configFile.LoggedInUsers, models.LoggedInUser{ + Email: profile, + Domain: config.INFISICAL_URL, + }) + //set logged in user domain + configFile.LoggedInUserDomain = config.INFISICAL_URL + + } else { + //exists, set logged in user domain + for _, v := range configFile.LoggedInUsers { + if profile == v.Email { + configFile.LoggedInUserDomain = v.Domain + break + } + } + } + + err = util.WriteConfigFile(&configFile) + if err != nil { + util.HandleError(err, "") + } + + Telemetry.CaptureEvent("cli-command:user switch", posthog.NewProperties().Set("numberOfLoggedInProfiles", len(loggedInProfiles)).Set("version", util.CLI_VERSION)) + }, +} + +var updateCmd = &cobra.Command{ + Use: "update", + Short: "Used to update properties of an Infisical profile", + DisableFlagsInUseLine: true, + Example: "infisical user update", + Args: cobra.ExactArgs(0), + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +var domainCmd = &cobra.Command{ + Use: "domain", + Short: "Used to update the domain of an Infisical profile", + DisableFlagsInUseLine: true, + Example: "infisical user update domain", + Args: cobra.ExactArgs(0), + PreRun: func(cmd *cobra.Command, args []string) { + util.RequireLogin() + }, + Run: func(cmd *cobra.Command, args []string) { + //prompt for profiles selection + loggedInProfiles, err := getLoggedInUsers() + if err != nil { + util.HandleError(err, "[infisical user update domain]: Unable to get logged Profiles") + } + + //prompt user + profile, err := LoggedInUsersPrompt(loggedInProfiles) + if err != nil { + util.HandleError(err, "[infisical user update domain]: Prompt error") + } + + domain := "" + domainQuery := true + if config.INFISICAL_URL_MANUAL_OVERRIDE != util.INFISICAL_DEFAULT_API_URL { + + override, err := DomainOverridePrompt() + if err != nil { + util.HandleError(err, "[infisical user update domain]: Domain override prompt error") + } + + if !override { + domainQuery = false + domain = config.INFISICAL_URL_MANUAL_OVERRIDE + } + + } + + if domainQuery { + //prompt to update domain + domain, err = NewDomainPrompt() + if err != nil { + util.HandleError(err, "[infisical user update domain]: Prompt error") + } + } + + //write to config file + configFile, err := util.GetConfigFile() + if err != nil { + util.HandleError(err, "[infisical user update domain]: Unable to get config file") + } + + //check if profile in logged in profiles + + //if not add new profile loggedInUsers + //else update profile from loggedinUsers slice + ok := util.ConfigContainsEmail(configFile.LoggedInUsers, profile) + if !ok { + configFile.LoggedInUsers = append(configFile.LoggedInUsers, models.LoggedInUser{ + Email: profile, + Domain: domain, + }) + } else { + //exists, set logged in user domain + for idx, v := range configFile.LoggedInUsers { + if profile == v.Email { + configFile.LoggedInUsers[idx].Domain = domain //inplace + break + } + } + + } + //check if current loggedinuser is selected profile + //if yes set current domain to changed domain + if configFile.LoggedInUserEmail == profile { + configFile.LoggedInUserDomain = domain + } + + err = util.WriteConfigFile(&configFile) + if err != nil { + util.HandleError(err, "") + } + Telemetry.CaptureEvent("cli-command:user domain", posthog.NewProperties().Set("version", util.CLI_VERSION)) + }, +} + +func init() { + updateCmd.AddCommand(domainCmd) + userCmd.AddCommand(updateCmd) + userCmd.AddCommand(switchCmd) + rootCmd.AddCommand(userCmd) +} + +// This returns all logged in user emails from the config file. +// If none, it returns the current logged in user in a slice +func getLoggedInUsers() ([]string, error) { + loggedInProfiles := []string{} + + if util.ConfigFileExists() { + configFile, err := util.GetConfigFile() + if err != nil { + return loggedInProfiles, err + } + + //get logged in profiles + // + if len(configFile.LoggedInUsers) > 0 { + for _, v := range configFile.LoggedInUsers { + loggedInProfiles = append(loggedInProfiles, v.Email) + } + } else { + + loggedInProfiles = append(loggedInProfiles, configFile.LoggedInUserEmail) + } + return loggedInProfiles, nil + } else { + //empty + return loggedInProfiles, errors.New("couldn't retrieve config file") + } +} + +func NewDomainPrompt() (string, error) { + urlValidation := func(input string) error { + _, err := url.ParseRequestURI(input) + if err != nil { + return errors.New("this is an invalid url") + } + return nil + } + + //else run prompt to enter domain + domainPrompt := promptui.Prompt{ + Label: "New Domain", + Validate: urlValidation, + Default: "Example - https://my-self-hosted-instance.com/api", + } + + domain, err := domainPrompt.Run() + if err != nil { + return "", err + } + + return domain, nil +} + +func LoggedInUsersPrompt(profiles []string) (string, error) { + prompt := promptui.Select{Label: "Which of your Infisical profiles would you like to use", + Items: profiles, + Size: 7, + } + + idx, _, err := prompt.Run() + if err != nil { + return "", err + } + + return profiles[idx], nil +} diff --git a/cli/packages/cmd/vault.go b/cli/packages/cmd/vault.go index d9e32769e..e6662c5d6 100644 --- a/cli/packages/cmd/vault.go +++ b/cli/packages/cmd/vault.go @@ -4,9 +4,12 @@ Copyright (c) 2023 Infisical Inc. package cmd import ( + "fmt" + "github.com/99designs/keyring" "github.com/Infisical/infisical-merge/packages/util" - log "github.com/sirupsen/logrus" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" "github.com/spf13/cobra" ) @@ -15,25 +18,24 @@ var vaultSetCmd = &cobra.Command{ Use: "set [vault-name]", Short: "Used to set the vault backend to store your login details securely at rest", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { wantedVaultTypeName := args[0] currentVaultBackend, err := util.GetCurrentVaultBackend() if err != nil { - log.Errorf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) + log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) return } if wantedVaultTypeName == string(currentVaultBackend) { - log.Errorf("You are already on vault backend [%s]", currentVaultBackend) + log.Error().Msgf("You are already on vault backend [%s]", currentVaultBackend) return } if isVaultToSwitchToValid(wantedVaultTypeName) { configFile, err := util.GetConfigFile() if err != nil { - log.Errorf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) + log.Error().Msgf("Unable to set vault to [%s] because of [err=%s]", wantedVaultTypeName, err) return } @@ -42,13 +44,15 @@ var vaultSetCmd = &cobra.Command{ err = util.WriteConfigFile(&configFile) if err != nil { - log.Errorf("Unable to set vault to [%s] because an error occurred when saving the config file [err=%s]", wantedVaultTypeName, err) + log.Error().Msgf("Unable to set vault to [%s] because an error occurred when saving the config file [err=%s]", wantedVaultTypeName, err) return } - log.Infof("Successfully, switched vault backend from [%s] to [%s]. Please login in again to store your login details in the new vault with [infisical login]", currentVaultBackend, wantedVaultTypeName) + fmt.Printf("\nSuccessfully, switched vault backend from [%s] to [%s]. Please login in again to store your login details in the new vault with [infisical login]", currentVaultBackend, wantedVaultTypeName) + + Telemetry.CaptureEvent("cli-command:vault set", posthog.NewProperties().Set("currentVault", currentVaultBackend).Set("wantedVault", wantedVaultTypeName).Set("version", util.CLI_VERSION)) } else { - log.Errorf("The requested vault type [%s] is not available on this system. Only the following vault backends are available for you system: %s", wantedVaultTypeName, keyring.AvailableBackends()) + log.Error().Msgf("The requested vault type [%s] is not available on this system. Only the following vault backends are available for you system: %s", wantedVaultTypeName, keyring.AvailableBackends()) } }, } @@ -58,7 +62,6 @@ var vaultCmd = &cobra.Command{ Use: "vault", Short: "Used to manage where your Infisical login token is saved on your machine", DisableFlagsInUseLine: true, - PreRun: toggleDebug, Args: cobra.NoArgs, Run: func(cmd *cobra.Command, args []string) { printAvailableVaultBackends() @@ -66,17 +69,19 @@ var vaultCmd = &cobra.Command{ } func printAvailableVaultBackends() { - log.Infof("The following vaults are available on your system:") + fmt.Printf("The following vaults are available on your system:") for _, backend := range keyring.AvailableBackends() { - log.Infof("- %s", backend) + fmt.Printf("\n- %s", backend) } currentVaultBackend, err := util.GetCurrentVaultBackend() if err != nil { - log.Errorf("printAvailableVaultBackends: unable to print the available vault backend because of error [err=%s]", err) + log.Error().Msgf("printAvailableVaultBackends: unable to print the available vault backend because of error [err=%s]", err) } - log.Infof("\nYou are currently using [%s] vault to store your login credentials", string(currentVaultBackend)) + Telemetry.CaptureEvent("cli-command:vault", posthog.NewProperties().Set("currentVault", currentVaultBackend).Set("version", util.CLI_VERSION)) + + fmt.Printf("\n\nYou are currently using [%s] vault to store your login credentials", string(currentVaultBackend)) } // Checks if the vault that the user wants to switch to is a valid available vault diff --git a/cli/packages/config/config.go b/cli/packages/config/config.go index 6c56858e6..e27bc8f68 100644 --- a/cli/packages/config/config.go +++ b/cli/packages/config/config.go @@ -1,3 +1,4 @@ package config var INFISICAL_URL string +var INFISICAL_URL_MANUAL_OVERRIDE string diff --git a/cli/packages/models/cli.go b/cli/packages/models/cli.go index 5e969a9c0..b9b0ab7b5 100644 --- a/cli/packages/models/cli.go +++ b/cli/packages/models/cli.go @@ -12,8 +12,15 @@ type UserCredentials struct { // The file struct for Infisical config file type ConfigFile struct { - LoggedInUserEmail string `json:"loggedInUserEmail"` - VaultBackendType keyring.BackendType `json:"vaultBackendType"` + LoggedInUserEmail string `json:"loggedInUserEmail"` + LoggedInUserDomain string `json:"LoggedInUserDomain,omitempty"` + VaultBackendType keyring.BackendType `json:"vaultBackendType"` + LoggedInUsers []LoggedInUser `json:"loggedInUsers,omitempty"` +} + +type LoggedInUser struct { + Email string `json:"email"` + Domain string `json:"domain"` } type SingleEnvironmentVariable struct { diff --git a/cli/packages/models/error.go b/cli/packages/models/error.go deleted file mode 100644 index f6d58cb5a..000000000 --- a/cli/packages/models/error.go +++ /dev/null @@ -1,17 +0,0 @@ -package models - -import log "github.com/sirupsen/logrus" - -// Custom error type so that we can give helpful messages in CLI -type Error struct { - Err error - FriendlyMessage string -} - -func (e *Error) printFriendlyMessage() { - log.Infoln(e.FriendlyMessage) -} - -func (e *Error) printDebuError() { - log.Debugln(e.Err) -} diff --git a/cli/packages/telemetry/telemetry.go b/cli/packages/telemetry/telemetry.go new file mode 100644 index 000000000..ffd743457 --- /dev/null +++ b/cli/packages/telemetry/telemetry.go @@ -0,0 +1,82 @@ +package telemetry + +import ( + "github.com/Infisical/infisical-merge/packages/util" + "github.com/denisbrodbeck/machineid" + "github.com/posthog/posthog-go" + "github.com/rs/zerolog/log" +) + +var POSTHOG_API_KEY_FOR_CLI string + +type Telemetry struct { + isEnabled bool + posthogClient posthog.Client +} + +type NoOpLogger struct{} + +func (NoOpLogger) Logf(format string, args ...interface{}) { + log.Debug().Msgf(format, args...) +} + +func (NoOpLogger) Errorf(format string, args ...interface{}) { + log.Debug().Msgf(format, args...) +} + +func NewTelemetry(telemetryIsEnabled bool) *Telemetry { + if POSTHOG_API_KEY_FOR_CLI != "" { + client, _ := posthog.NewWithConfig( + POSTHOG_API_KEY_FOR_CLI, + posthog.Config{ + Logger: NoOpLogger{}, + }, + ) + + return &Telemetry{isEnabled: telemetryIsEnabled, posthogClient: client} + } else { + return &Telemetry{isEnabled: false} + } +} + +func (t *Telemetry) CaptureEvent(eventName string, properties posthog.Properties) { + userIdentity, err := t.GetDistinctId() + if err != nil { + return + } + + if t.isEnabled { + t.posthogClient.Enqueue(posthog.Capture{ + DistinctId: userIdentity, + Event: eventName, + Properties: properties, + }) + + defer t.posthogClient.Close() + } +} + +func (t *Telemetry) GetDistinctId() (string, error) { + var distinctId string + var outputErr error + + machineId, err := machineid.ID() + if err != nil { + outputErr = err + } + + infisicalConfig, err := util.GetConfigFile() + if err != nil { + outputErr = err + } + + if infisicalConfig.LoggedInUserEmail != "" { + distinctId = infisicalConfig.LoggedInUserEmail + } else if machineId != "" { + distinctId = "anonymous_cli_" + machineId + } else { + distinctId = "" + } + + return distinctId, outputErr +} diff --git a/cli/packages/util/check-for-update.go b/cli/packages/util/check-for-update.go index 2f283070c..e59c04326 100644 --- a/cli/packages/util/check-for-update.go +++ b/cli/packages/util/check-for-update.go @@ -4,14 +4,16 @@ import ( "encoding/json" "errors" "fmt" - log "github.com/sirupsen/logrus" "io" + "io/ioutil" "net/http" "os" "os/exec" "runtime" + "strings" "github.com/fatih/color" + "github.com/rs/zerolog/log" ) func CheckForUpdate() { @@ -20,7 +22,7 @@ func CheckForUpdate() { } latestVersion, err := getLatestTag("Infisical", "infisical") if err != nil { - log.Debug(err) + log.Debug().Err(err) // do nothing and continue return } @@ -49,7 +51,7 @@ func CheckForUpdate() { } func getLatestTag(repoOwner string, repoName string) (string, error) { - url := fmt.Sprintf("https://api.github.com/repos/%s/%s/tags", repoOwner, repoName) + url := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", repoOwner, repoName) resp, err := http.Get(url) if err != nil { return "", err @@ -65,15 +67,20 @@ func getLatestTag(repoOwner string, repoName string) (string, error) { return "", err } - var tags []struct { - Name string `json:"name"` + var releaseTag struct { + TagName string `json:"tag_name"` } - if err := json.Unmarshal(body, &tags); err != nil { + if err := json.Unmarshal(body, &releaseTag); err != nil { return "", fmt.Errorf("failed to unmarshal github response: %w", err) } - return tags[0].Name[1:], nil + tag_prefix := "infisical-cli/v" + + // Extract the version from the first valid tag + version := strings.TrimPrefix(releaseTag.TagName, tag_prefix) + + return version, nil } func GetUpdateInstructions() string { @@ -125,3 +132,16 @@ func getLinuxPackageManager() string { return "" } + +func IsRunningInDocker() bool { + if _, err := os.Stat("/.dockerenv"); err == nil { + return true + } + + cgroup, err := ioutil.ReadFile("/proc/self/cgroup") + if err != nil { + return false + } + + return strings.Contains(string(cgroup), "docker") +} diff --git a/cli/packages/util/common.go b/cli/packages/util/common.go index 13e76046d..2b57383ef 100644 --- a/cli/packages/util/common.go +++ b/cli/packages/util/common.go @@ -23,8 +23,5 @@ func WriteToFile(fileName string, dataToWrite []byte, filePerm os.FileMode) erro func CheckIsConnectedToInternet() (ok bool) { _, err := http.Get("http://clients3.google.com/generate_204") - if err != nil { - return false - } - return true + return err == nil } diff --git a/cli/packages/util/config.go b/cli/packages/util/config.go index e7b6c8d97..e6c6fddb4 100644 --- a/cli/packages/util/config.go +++ b/cli/packages/util/config.go @@ -7,8 +7,9 @@ import ( "os" "path/filepath" + "github.com/Infisical/infisical-merge/packages/config" "github.com/Infisical/infisical-merge/packages/models" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" ) func WriteInitalConfig(userCredentials *models.UserCredentials) error { @@ -31,9 +32,28 @@ func WriteInitalConfig(userCredentials *models.UserCredentials) error { return fmt.Errorf("writeInitalConfig: unable to write config file because [err=%s]", err) } + //if profiles exists + loggedInUser := models.LoggedInUser{ + Email: userCredentials.Email, + Domain: config.INFISICAL_URL, + } + //if empty or if email not in loggedinUsers + if len(existingConfigFile.LoggedInUsers) == 0 || !ConfigContainsEmail(existingConfigFile.LoggedInUsers, userCredentials.Email) { + existingConfigFile.LoggedInUsers = append(existingConfigFile.LoggedInUsers, loggedInUser) + } else { + //if exists update domain of loggedin users + for idx, user := range existingConfigFile.LoggedInUsers { + if user.Email == userCredentials.Email { + existingConfigFile.LoggedInUsers[idx] = loggedInUser + } + } + } + configFile := models.ConfigFile{ - LoggedInUserEmail: userCredentials.Email, - VaultBackendType: existingConfigFile.VaultBackendType, + LoggedInUserEmail: userCredentials.Email, + LoggedInUserDomain: config.INFISICAL_URL, + VaultBackendType: existingConfigFile.VaultBackendType, + LoggedInUsers: existingConfigFile.LoggedInUsers, } configFileMarshalled, err := json.Marshal(configFile) @@ -53,7 +73,7 @@ func WriteInitalConfig(userCredentials *models.UserCredentials) error { func ConfigFileExists() bool { fullConfigFileURI, _, err := GetFullConfigFilePath() if err != nil { - log.Debugln("There was an error when creating the full path to config file", err) + log.Debug().Err(err).Msgf("There was an error when creating the full path to config file") return false } @@ -68,7 +88,7 @@ func WorkspaceConfigFileExistsInCurrentPath() bool { if _, err := os.Stat(INFISICAL_WORKSPACE_CONFIG_FILE_NAME); err == nil { return true } else { - log.Debugln(err) + log.Debug().Err(err) return false } } @@ -105,7 +125,7 @@ func FindWorkspaceConfigFile() (string, error) { _, err := os.Stat(path) if err == nil { // file found - log.Debugf("FindWorkspaceConfigFile: workspace file found at [path=%s]", path) + log.Debug().Msgf("FindWorkspaceConfigFile: workspace file found at [path=%s]", path) return path, nil } @@ -176,7 +196,7 @@ func GetConfigFile() (models.ConfigFile, error) { return configFile, nil } -// Write a ConfigFile to disk. Raise error if unable to save the model to ask +// Write a ConfigFile to disk. Raise error if unable to save the model to disk func WriteConfigFile(configFile *models.ConfigFile) error { fullConfigFilePath, fullConfigFileDirPath, err := GetFullConfigFilePath() if err != nil { diff --git a/cli/packages/util/credentials.go b/cli/packages/util/credentials.go index 1766f04c7..9147a717a 100644 --- a/cli/packages/util/credentials.go +++ b/cli/packages/util/credentials.go @@ -6,6 +6,7 @@ import ( "github.com/99designs/keyring" "github.com/Infisical/infisical-merge/packages/api" + "github.com/Infisical/infisical-merge/packages/config" "github.com/Infisical/infisical-merge/packages/models" "github.com/go-resty/resty/v2" ) @@ -87,6 +88,13 @@ func GetCurrentLoggedInUserDetails() (LoggedInUserDetails, error) { SetAuthToken(userCreds.JTWToken). SetHeader("Accept", "application/json") + config.INFISICAL_URL_MANUAL_OVERRIDE = config.INFISICAL_URL + //configFile.LoggedInUserDomain + //if not empty set as infisical url + if configFile.LoggedInUserDomain != "" { + config.INFISICAL_URL = configFile.LoggedInUserDomain + } + isAuthenticated := api.CallIsAuthenticated(httpClient) if !isAuthenticated { return LoggedInUserDetails{ diff --git a/cli/packages/util/helper.go b/cli/packages/util/helper.go index 76b6e3e46..8527c4059 100644 --- a/cli/packages/util/helper.go +++ b/cli/packages/util/helper.go @@ -9,6 +9,8 @@ import ( "os/exec" "path" "strings" + + "github.com/Infisical/infisical-merge/packages/models" ) type DecodedSymmetricEncryptionDetails = struct { @@ -61,6 +63,16 @@ func IsSecretTypeValid(s string) bool { return false } +// Checks if the passed in email already exists in the users slice +func ConfigContainsEmail(users []models.LoggedInUser, email string) bool { + for _, value := range users { + if value.Email == email { + return true + } + } + return false +} + func RequireLogin() { currentUserDetails, err := GetCurrentLoggedInUserDetails() diff --git a/cli/packages/util/secrets.go b/cli/packages/util/secrets.go index c25c07efd..a713abddb 100644 --- a/cli/packages/util/secrets.go +++ b/cli/packages/util/secrets.go @@ -12,15 +12,14 @@ import ( "github.com/Infisical/infisical-merge/packages/api" "github.com/Infisical/infisical-merge/packages/crypto" "github.com/Infisical/infisical-merge/packages/models" - log "github.com/sirupsen/logrus" - "github.com/go-resty/resty/v2" + "github.com/rs/zerolog/log" ) -func GetPlainTextSecretsViaServiceToken(fullServiceToken string) ([]models.SingleEnvironmentVariable, error) { +func GetPlainTextSecretsViaServiceToken(fullServiceToken string) ([]models.SingleEnvironmentVariable, api.GetServiceTokenDetailsResponse, error) { serviceTokenParts := strings.SplitN(fullServiceToken, ".", 4) if len(serviceTokenParts) < 4 { - return nil, fmt.Errorf("invalid service token entered. Please double check your service token and try again") + return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("invalid service token entered. Please double check your service token and try again") } serviceToken := fmt.Sprintf("%v.%v.%v", serviceTokenParts[0], serviceTokenParts[1], serviceTokenParts[2]) @@ -32,7 +31,7 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string) ([]models.Singl serviceTokenDetails, err := api.CallGetServiceTokenDetailsV2(httpClient) if err != nil { - return nil, fmt.Errorf("unable to get service token details. [err=%v]", err) + return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to get service token details. [err=%v]", err) } encryptedSecrets, err := api.CallGetSecretsV2(httpClient, api.GetEncryptedSecretsV2Request{ @@ -41,25 +40,25 @@ func GetPlainTextSecretsViaServiceToken(fullServiceToken string) ([]models.Singl }) if err != nil { - return nil, err + return nil, api.GetServiceTokenDetailsResponse{}, err } decodedSymmetricEncryptionDetails, err := GetBase64DecodedSymmetricEncryptionDetails(serviceTokenParts[3], serviceTokenDetails.EncryptedKey, serviceTokenDetails.Iv, serviceTokenDetails.Tag) if err != nil { - return nil, fmt.Errorf("unable to decode symmetric encryption details [err=%v]", err) + return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to decode symmetric encryption details [err=%v]", err) } plainTextWorkspaceKey, err := crypto.DecryptSymmetric([]byte(serviceTokenParts[3]), decodedSymmetricEncryptionDetails.Cipher, decodedSymmetricEncryptionDetails.Tag, decodedSymmetricEncryptionDetails.IV) if err != nil { - return nil, fmt.Errorf("unable to decrypt the required workspace key") + return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to decrypt the required workspace key") } plainTextSecrets, err := GetPlainTextSecrets(plainTextWorkspaceKey, encryptedSecrets) if err != nil { - return nil, fmt.Errorf("unable to decrypt your secrets [err=%v]", err) + return nil, api.GetServiceTokenDetailsResponse{}, fmt.Errorf("unable to decrypt your secrets [err=%v]", err) } - return plainTextSecrets, nil + return plainTextSecrets, serviceTokenDetails, nil } func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, workspaceId string, environmentName string, tagSlugs string) ([]models.SingleEnvironmentVariable, error) { @@ -97,7 +96,7 @@ func GetPlainTextSecretsViaJTW(JTWToken string, receiversPrivateKey string, work } if len(currentUsersPrivateKey) == 0 || len(encryptedWorkspaceKeySenderPublicKey) == 0 { - log.Debugf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) + log.Debug().Msgf("Missing credentials for generating plainTextEncryptionKey: [currentUsersPrivateKey=%s] [encryptedWorkspaceKeySenderPublicKey=%s]", currentUsersPrivateKey, encryptedWorkspaceKeySenderPublicKey) PrintErrorMessageAndExit("Some required user credentials are missing to generate your [plainTextEncryptionKey]. Please run [infisical login] then try again") } @@ -131,16 +130,17 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models isConnected := CheckIsConnectedToInternet() var secretsToReturn []models.SingleEnvironmentVariable + // var serviceTokenDetails api.GetServiceTokenDetailsResponse var errorToReturn error if infisicalToken == "" { if isConnected { - log.Debug("GetAllEnvironmentVariables: Connected to internet, checking logged in creds") + log.Debug().Msg("GetAllEnvironmentVariables: Connected to internet, checking logged in creds") RequireLocalWorkspaceFile() RequireLogin() } - log.Debug("GetAllEnvironmentVariables: Trying to fetch secrets using logged in details") + log.Debug().Msg("GetAllEnvironmentVariables: Trying to fetch secrets using logged in details") loggedInUserDetails, err := GetCurrentLoggedInUserDetails() if err != nil { @@ -163,7 +163,7 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models } secretsToReturn, errorToReturn = GetPlainTextSecretsViaJTW(loggedInUserDetails.UserCredentials.JTWToken, loggedInUserDetails.UserCredentials.PrivateKey, workspaceFile.WorkspaceId, params.Environment, params.TagSlugs) - log.Debugf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn) + log.Debug().Msgf("GetAllEnvironmentVariables: Trying to fetch secrets JTW token [err=%s]", errorToReturn) backupSecretsEncryptionKey := []byte(loggedInUserDetails.UserCredentials.PrivateKey)[0:32] if errorToReturn == nil { @@ -181,8 +181,12 @@ func GetAllEnvironmentVariables(params models.GetAllSecretsParameters) ([]models } } else { - log.Debug("Trying to fetch secrets using service token") - secretsToReturn, errorToReturn = GetPlainTextSecretsViaServiceToken(infisicalToken) + log.Debug().Msg("Trying to fetch secrets using service token") + secretsToReturn, _, errorToReturn = GetPlainTextSecretsViaServiceToken(infisicalToken) + + // if serviceTokenDetails.Environment != params.Environment { + // PrintErrorMessageAndExit(fmt.Sprintf("Fetch secrets failed: token allows [%s] environment access, not [%s]. Service tokens are environment-specific; no need for --env flag.", params.Environment, serviceTokenDetails.Environment)) + // } } return secretsToReturn, errorToReturn @@ -510,7 +514,7 @@ func DeleteBackupSecrets() error { func GetEnvFromWorkspaceFile() string { workspaceFile, err := GetWorkSpaceFromFile() if err != nil { - log.Debugf("getEnvFromWorkspaceFile: [err=%s]", err) + log.Debug().Msgf("getEnvFromWorkspaceFile: [err=%s]", err) return "" } @@ -524,17 +528,17 @@ func GetEnvFromWorkspaceFile() string { func GetEnvelopmentBasedOnGitBranch(workspaceFile models.WorkspaceConfigFile) string { branch, err := getCurrentBranch() if err != nil { - log.Debugf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) + log.Debug().Msgf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) } envBasedOnGitBranch, ok := workspaceFile.GitBranchToEnvironmentMapping[branch] - log.Debugf("GetEnvelopmentBasedOnGitBranch: [envBasedOnGitBranch=%s] [ok=%t]", envBasedOnGitBranch, ok) + log.Debug().Msgf("GetEnvelopmentBasedOnGitBranch: [envBasedOnGitBranch=%s] [ok=%t]", envBasedOnGitBranch, ok) if err == nil && ok { return envBasedOnGitBranch } else { - log.Debugf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) + log.Debug().Msgf("getEnvelopmentBasedOnGitBranch: [err=%s]", err) return "" } } diff --git a/cli/packages/util/vault.go b/cli/packages/util/vault.go index 0852e5f48..ff45be1ca 100644 --- a/cli/packages/util/vault.go +++ b/cli/packages/util/vault.go @@ -54,10 +54,12 @@ func GetKeyRing() (keyring.Keyring, error) { } func fileKeyringPassphrasePrompt(prompt string) (string, error) { - if password, ok := os.LookupEnv("INFISICAL_VAULT_FILE_PASSPHRASE"); ok { + if password, ok := os.LookupEnv("VAULT_PASS"); ok { + return password, nil + } else if password, ok := os.LookupEnv("INFISICAL_VAULT_FILE_PASSPHRASE"); ok { return password, nil } else { - fmt.Println("You may set the environment variable `INFISICAL_VAULT_FILE_PASSPHRASE` with your password to avoid typing it") + fmt.Println("To avoid repeatedly typing your password, set the environment variable `VAULT_PASS` to your password") } fmt.Fprintf(os.Stderr, "%s:", prompt) diff --git a/cli/packages/visualize/visualize.go b/cli/packages/visualize/visualize.go index 8599f2405..365cbeac4 100644 --- a/cli/packages/visualize/visualize.go +++ b/cli/packages/visualize/visualize.go @@ -8,7 +8,7 @@ import ( "github.com/mattn/go-isatty" "github.com/muesli/ansi" "github.com/muesli/reflow/truncate" - log "github.com/sirupsen/logrus" + "github.com/rs/zerolog/log" "golang.org/x/term" ) @@ -39,9 +39,9 @@ func Table(headers [3]string, rows [][3]string) { width, _, err := term.GetSize(int(os.Stdout.Fd())) if err != nil { if shouldTruncate { - log.Errorf("error getting terminal size: %s", err) + log.Error().Msgf("error getting terminal size: %s", err) } else { - log.Debug(err) + log.Debug().Err(err) } } diff --git a/cli/report/constants.go b/cli/report/constants.go new file mode 100644 index 000000000..8bad495cb --- /dev/null +++ b/cli/report/constants.go @@ -0,0 +1,25 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +package report + +const version = "v8.0.0" +const driver = "gitleaks" diff --git a/cli/report/csv.go b/cli/report/csv.go new file mode 100644 index 000000000..0a30c9fd5 --- /dev/null +++ b/cli/report/csv.go @@ -0,0 +1,81 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "encoding/csv" + "io" + "strconv" +) + +// writeCsv writes the list of findings to a writeCloser. +func writeCsv(f []Finding, w io.WriteCloser) error { + if len(f) == 0 { + return nil + } + defer w.Close() + cw := csv.NewWriter(w) + err := cw.Write([]string{"RuleID", + "Commit", + "File", + "SymlinkFile", + "Secret", + "Match", + "StartLine", + "EndLine", + "StartColumn", + "EndColumn", + "Author", + "Message", + "Date", + "Email", + "Fingerprint", + }) + if err != nil { + return err + } + for _, f := range f { + err = cw.Write([]string{f.RuleID, + f.Commit, + f.File, + f.SymlinkFile, + f.Secret, + f.Match, + strconv.Itoa(f.StartLine), + strconv.Itoa(f.EndLine), + strconv.Itoa(f.StartColumn), + strconv.Itoa(f.EndColumn), + f.Author, + f.Message, + f.Date, + f.Email, + f.Fingerprint, + }) + if err != nil { + return err + } + } + + cw.Flush() + return cw.Error() +} diff --git a/cli/report/csv_test.go b/cli/report/csv_test.go new file mode 100644 index 000000000..967026519 --- /dev/null +++ b/cli/report/csv_test.go @@ -0,0 +1,108 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestWriteCSV(t *testing.T) { + tests := []struct { + findings []Finding + testReportName string + expected string + wantEmpty bool + }{ + { + testReportName: "simple", + expected: filepath.Join(expectPath, "report", "csv_simple.csv"), + findings: []Finding{ + { + RuleID: "test-rule", + Match: "line containing secret", + Secret: "a secret", + StartLine: 1, + EndLine: 2, + StartColumn: 1, + EndColumn: 2, + Message: "opps", + File: "auth.py", + SymlinkFile: "", + Commit: "0000000000000000", + Author: "John Doe", + Email: "johndoe@gmail.com", + Date: "10-19-2003", + Fingerprint: "fingerprint", + }, + }}, + { + + wantEmpty: true, + testReportName: "empty", + expected: filepath.Join(expectPath, "report", "this_should_not_exist.csv"), + findings: []Finding{}}, + } + + for _, test := range tests { + tmpfile, err := os.Create(filepath.Join(tmpPath, test.testReportName+".csv")) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + err = writeCsv(test.findings, tmpfile) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + got, err := os.ReadFile(tmpfile.Name()) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + if test.wantEmpty { + if len(got) > 0 { + t.Errorf("Expected empty file, got %s", got) + } + os.Remove(tmpfile.Name()) + continue + } + want, err := os.ReadFile(test.expected) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + + if string(got) != string(want) { + err = os.WriteFile(strings.Replace(test.expected, ".csv", ".got.csv", 1), got, 0644) + if err != nil { + t.Error(err) + } + t.Errorf("got %s, want %s", string(got), string(want)) + } + + os.Remove(tmpfile.Name()) + } +} diff --git a/cli/report/finding.go b/cli/report/finding.go new file mode 100644 index 000000000..be461072b --- /dev/null +++ b/cli/report/finding.go @@ -0,0 +1,72 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "strings" +) + +// Finding contains information about strings that +// have been captured by a tree-sitter query. +type Finding struct { + Description string + StartLine int + EndLine int + StartColumn int + EndColumn int + + Line string `json:"-"` + + Match string + + // Secret contains the full content of what is matched in + // the tree-sitter query. + Secret string + + // File is the name of the file containing the finding + File string + SymlinkFile string + Commit string + + // Entropy is the shannon entropy of Value + Entropy float32 + + Author string + Email string + Date string + Message string + Tags []string + + // Rule is the name of the rule that was matched + RuleID string + + // unique identifer + Fingerprint string +} + +// Redact removes sensitive information from a finding. +func (f *Finding) Redact() { + f.Line = strings.Replace(f.Line, f.Secret, "REDACTED", -1) + f.Match = strings.Replace(f.Match, f.Secret, "REDACTED", -1) + f.Secret = "REDACTED" +} diff --git a/cli/report/finding_test.go b/cli/report/finding_test.go new file mode 100644 index 000000000..cdb74a329 --- /dev/null +++ b/cli/report/finding_test.go @@ -0,0 +1,48 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +package report + +import "testing" + +func TestRedact(t *testing.T) { + tests := []struct { + findings []Finding + redact bool + }{ + { + redact: true, + findings: []Finding{ + { + Secret: "line containing secret", + Match: "secret", + }, + }}, + } + for _, test := range tests { + for _, f := range test.findings { + f.Redact() + if f.Secret != "REDACTED" { + t.Error("redact not redacting: ", f.Secret) + } + } + } +} diff --git a/cli/report/json.go b/cli/report/json.go new file mode 100644 index 000000000..d091ac3c5 --- /dev/null +++ b/cli/report/json.go @@ -0,0 +1,37 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "encoding/json" + "io" +) + +func writeJson(findings []Finding, w io.WriteCloser) error { + if len(findings) == 0 { + findings = []Finding{} + } + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + return encoder.Encode(findings) +} diff --git a/cli/report/json_test.go b/cli/report/json_test.go new file mode 100644 index 000000000..e81aaa827 --- /dev/null +++ b/cli/report/json_test.go @@ -0,0 +1,111 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +func TestWriteJSON(t *testing.T) { + tests := []struct { + findings []Finding + testReportName string + expected string + wantEmpty bool + }{ + { + testReportName: "simple", + expected: filepath.Join(expectPath, "report", "json_simple.json"), + findings: []Finding{ + { + + Description: "", + RuleID: "test-rule", + Match: "line containing secret", + Secret: "a secret", + StartLine: 1, + EndLine: 2, + StartColumn: 1, + EndColumn: 2, + Message: "opps", + File: "auth.py", + SymlinkFile: "", + Commit: "0000000000000000", + Author: "John Doe", + Email: "johndoe@gmail.com", + Date: "10-19-2003", + Tags: []string{}, + }, + }}, + { + + testReportName: "empty", + expected: filepath.Join(expectPath, "report", "empty.json"), + findings: []Finding{}}, + } + + for _, test := range tests { + // create tmp file using os.TempDir() + tmpfile, err := os.Create(filepath.Join(tmpPath, test.testReportName+".json")) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + err = writeJson(test.findings, tmpfile) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + got, err := os.ReadFile(tmpfile.Name()) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + if test.wantEmpty { + if len(got) > 0 { + os.Remove(tmpfile.Name()) + t.Errorf("Expected empty file, got %s", got) + } + os.Remove(tmpfile.Name()) + continue + } + want, err := os.ReadFile(test.expected) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + + if string(got) != string(want) { + err = os.WriteFile(strings.Replace(test.expected, ".json", ".got.json", 1), got, 0644) + if err != nil { + t.Error(err) + } + t.Errorf("got %s, want %s", string(got), string(want)) + } + + os.Remove(tmpfile.Name()) + } +} diff --git a/cli/report/report.go b/cli/report/report.go new file mode 100644 index 000000000..1191a4f33 --- /dev/null +++ b/cli/report/report.go @@ -0,0 +1,54 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "os" + "strings" + + "github.com/Infisical/infisical-merge/config" +) + +const ( + // https://cwe.mitre.org/data/definitions/798.html + CWE = "CWE-798" + CWE_DESCRIPTION = "Use of Hard-coded Credentials" +) + +func Write(findings []Finding, cfg config.Config, ext string, reportPath string) error { + file, err := os.Create(reportPath) + if err != nil { + return err + } + ext = strings.ToLower(ext) + switch ext { + case ".json", "json": + err = writeJson(findings, file) + case ".csv", "csv": + err = writeCsv(findings, file) + case ".sarif", "sarif": + err = writeSarif(cfg, findings, file) + } + + return err +} diff --git a/cli/report/report_test.go b/cli/report/report_test.go new file mode 100644 index 000000000..ef38f19c2 --- /dev/null +++ b/cli/report/report_test.go @@ -0,0 +1,133 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "os" + "path/filepath" + "strconv" + "testing" + + "github.com/Infisical/infisical-merge/config" +) + +const ( + expectPath = "../testdata/expected/" + tmpPath = "../testdata/tmp" +) + +func TestReport(t *testing.T) { + tests := []struct { + findings []Finding + ext string + wantEmpty bool + }{ + { + ext: "json", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + }, + { + ext: ".json", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + }, + { + ext: ".jsonj", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + wantEmpty: true, + }, + { + ext: ".csv", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + }, + { + ext: "csv", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + }, + { + ext: "CSV", + findings: []Finding{ + { + RuleID: "test-rule", + }, + }, + }, + // { + // ext: "SARIF", + // findings: []Finding{ + // { + // RuleID: "test-rule", + // }, + // }, + // }, + } + + for i, test := range tests { + tmpfile, err := os.Create(filepath.Join(tmpPath, strconv.Itoa(i)+test.ext)) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + err = Write(test.findings, config.Config{}, test.ext, tmpfile.Name()) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + got, err := os.ReadFile(tmpfile.Name()) + if err != nil { + os.Remove(tmpfile.Name()) + t.Error(err) + } + os.Remove(tmpfile.Name()) + + if len(got) == 0 && !test.wantEmpty { + t.Errorf("got empty file with extension " + test.ext) + } + + if test.wantEmpty { + if len(got) > 0 { + t.Errorf("Expected empty file, got %s", got) + } + continue + } + } +} diff --git a/cli/report/sarif.go b/cli/report/sarif.go new file mode 100644 index 000000000..e5120887a --- /dev/null +++ b/cli/report/sarif.go @@ -0,0 +1,237 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +import ( + "encoding/json" + "fmt" + "io" + + "github.com/Infisical/infisical-merge/config" +) + +func writeSarif(cfg config.Config, findings []Finding, w io.WriteCloser) error { + sarif := Sarif{ + Schema: "https://json.schemastore.org/sarif-2.1.0.json", + Version: "2.1.0", + Runs: getRuns(cfg, findings), + } + + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + return encoder.Encode(sarif) +} + +func getRuns(cfg config.Config, findings []Finding) []Runs { + return []Runs{ + { + Tool: getTool(cfg), + Results: getResults(findings), + }, + } +} + +func getTool(cfg config.Config) Tool { + tool := Tool{ + Driver: Driver{ + Name: driver, + SemanticVersion: version, + InformationUri: "https://github.com/Infisical/infisical", + Rules: getRules(cfg), + }, + } + + // if this tool has no rules, ensure that it is represented as [] instead of null/nil + if hasEmptyRules(tool) { + tool.Driver.Rules = make([]Rules, 0) + } + + return tool +} + +func hasEmptyRules(tool Tool) bool { + return len(tool.Driver.Rules) == 0 +} + +func getRules(cfg config.Config) []Rules { + // TODO for _, rule := range cfg.Rules { + var rules []Rules + for _, rule := range cfg.OrderedRules() { + shortDescription := ShortDescription{ + Text: rule.Description, + } + if rule.Regex != nil { + shortDescription = ShortDescription{ + Text: rule.Regex.String(), + } + } else if rule.Path != nil { + shortDescription = ShortDescription{ + Text: rule.Path.String(), + } + } + rules = append(rules, Rules{ + ID: rule.RuleID, + Name: rule.Description, + Description: shortDescription, + }) + } + return rules +} + +func messageText(f Finding) string { + if f.Commit == "" { + return fmt.Sprintf("%s has detected secret for file %s.", f.RuleID, f.File) + } + + return fmt.Sprintf("%s has detected secret for file %s at commit %s.", f.RuleID, f.File, f.Commit) + +} + +func getResults(findings []Finding) []Results { + results := []Results{} + for _, f := range findings { + r := Results{ + Message: Message{ + Text: messageText(f), + }, + RuleId: f.RuleID, + Locations: getLocation(f), + // This information goes in partial fingerprings until revision + // data can be added somewhere else + PartialFingerPrints: PartialFingerPrints{ + CommitSha: f.Commit, + Email: f.Email, + CommitMessage: f.Message, + Date: f.Date, + Author: f.Author, + }, + } + results = append(results, r) + } + return results +} + +func getLocation(f Finding) []Locations { + uri := f.File + if f.SymlinkFile != "" { + uri = f.SymlinkFile + } + return []Locations{ + { + PhysicalLocation: PhysicalLocation{ + ArtifactLocation: ArtifactLocation{ + URI: uri, + }, + Region: Region{ + StartLine: f.StartLine, + EndLine: f.EndLine, + StartColumn: f.StartColumn, + EndColumn: f.EndColumn, + Snippet: Snippet{ + Text: f.Secret, + }, + }, + }, + }, + } +} + +type PartialFingerPrints struct { + CommitSha string `json:"commitSha"` + Email string `json:"email"` + Author string `json:"author"` + Date string `json:"date"` + CommitMessage string `json:"commitMessage"` +} + +type Sarif struct { + Schema string `json:"$schema"` + Version string `json:"version"` + Runs []Runs `json:"runs"` +} + +type ShortDescription struct { + Text string `json:"text"` +} + +type FullDescription struct { + Text string `json:"text"` +} + +type Rules struct { + ID string `json:"id"` + Name string `json:"name"` + Description ShortDescription `json:"shortDescription"` +} + +type Driver struct { + Name string `json:"name"` + SemanticVersion string `json:"semanticVersion"` + InformationUri string `json:"informationUri"` + Rules []Rules `json:"rules"` +} + +type Tool struct { + Driver Driver `json:"driver"` +} + +type Message struct { + Text string `json:"text"` +} + +type ArtifactLocation struct { + URI string `json:"uri"` +} + +type Region struct { + StartLine int `json:"startLine"` + StartColumn int `json:"startColumn"` + EndLine int `json:"endLine"` + EndColumn int `json:"endColumn"` + Snippet Snippet `json:"snippet"` +} + +type Snippet struct { + Text string `json:"text"` +} + +type PhysicalLocation struct { + ArtifactLocation ArtifactLocation `json:"artifactLocation"` + Region Region `json:"region"` +} + +type Locations struct { + PhysicalLocation PhysicalLocation `json:"physicalLocation"` +} + +type Results struct { + Message Message `json:"message"` + RuleId string `json:"ruleId"` + Locations []Locations `json:"locations"` + PartialFingerPrints `json:"partialFingerprints"` +} + +type Runs struct { + Tool Tool `json:"tool"` + Results []Results `json:"results"` +} diff --git a/cli/report/sarif_test.go b/cli/report/sarif_test.go new file mode 100644 index 000000000..9331060f1 --- /dev/null +++ b/cli/report/sarif_test.go @@ -0,0 +1,122 @@ +// MIT License + +// Copyright (c) 2019 Zachary Rice + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +package report + +const configPath = "../testdata/config/" + +// func TestWriteSarif(t *testing.T) { +// tests := []struct { +// findings []Finding +// testReportName string +// expected string +// wantEmpty bool +// cfgName string +// }{ +// { +// cfgName: "simple", +// testReportName: "simple", +// expected: filepath.Join(expectPath, "report", "sarif_simple.sarif"), +// findings: []Finding{ +// { + +// Description: "A test rule", +// RuleID: "test-rule", +// Match: "line containing secret", +// Secret: "a secret", +// StartLine: 1, +// EndLine: 2, +// StartColumn: 1, +// EndColumn: 2, +// Message: "opps", +// File: "auth.py", +// Commit: "0000000000000000", +// Author: "John Doe", +// Email: "johndoe@gmail.com", +// Date: "10-19-2003", +// Tags: []string{}, +// }, +// }}, +// } + +// for _, test := range tests { +// // create tmp file using os.TempDir() +// tmpfile, err := os.Create(filepath.Join(tmpPath, test.testReportName+".json")) +// if err != nil { +// os.Remove(tmpfile.Name()) +// t.Error(err) +// } +// viper.Reset() +// viper.AddConfigPath(configPath) +// viper.SetConfigName(test.cfgName) +// viper.SetConfigType("toml") +// err = viper.ReadInConfig() +// if err != nil { +// t.Error(err) +// } + +// var vc config.ViperConfig +// err = viper.Unmarshal(&vc) +// if err != nil { +// t.Error(err) +// } + +// cfg, err := vc.Translate() +// if err != nil { +// t.Error(err) +// } +// err = writeSarif(cfg, test.findings, tmpfile) +// fmt.Println(cfg) +// if err != nil { +// os.Remove(tmpfile.Name()) +// t.Error(err) +// } +// got, err := os.ReadFile(tmpfile.Name()) +// if err != nil { +// os.Remove(tmpfile.Name()) +// t.Error(err) +// } +// if test.wantEmpty { +// if len(got) > 0 { +// os.Remove(tmpfile.Name()) +// t.Errorf("Expected empty file, got %s", got) +// } +// os.Remove(tmpfile.Name()) +// continue +// } +// want, err := os.ReadFile(test.expected) +// if err != nil { +// os.Remove(tmpfile.Name()) +// t.Error(err) +// } + +// if string(got) != string(want) { +// err = os.WriteFile(strings.Replace(test.expected, ".sarif", ".got.sarif", 1), got, 0644) +// if err != nil { +// t.Error(err) +// } +// t.Errorf("got %s, want %s", string(got), string(want)) +// } + +// os.Remove(tmpfile.Name()) +// } +// } diff --git a/cli/testdata/baseline/baseline.csv b/cli/testdata/baseline/baseline.csv new file mode 100644 index 000000000..d3f953727 --- /dev/null +++ b/cli/testdata/baseline/baseline.csv @@ -0,0 +1,2 @@ +RuleID,Commit,File,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint +1,b,c,f,s,m,s,e,s,e,a,m,f,r,f \ No newline at end of file diff --git a/cli/testdata/baseline/baseline.json b/cli/testdata/baseline/baseline.json new file mode 100644 index 000000000..3a4c5427f --- /dev/null +++ b/cli/testdata/baseline/baseline.json @@ -0,0 +1,40 @@ +[ + { + "Description": "PyPI upload token", + "StartLine": 32, + "EndLine": 32, + "StartColumn": 21, + "EndColumn": 106, + "Match": "************************", + "Secret": "************************", + "File": "detect/detect_test.go", + "Commit": "9326f35380636bcbe61e94b0584d1618c4b5c2c2", + "Entropy": 1.9606875, + "Author": "****", + "Email": "****", + "Date": "2022-03-07T14:33:06Z", + "Message": "Escape - character in regex character groups (#802)\n\n* fix char escape\n\n* add test\n\n* fix verbosity in make test", + "Tags": [], + "RuleID": "pypi-upload-token", + "Fingerprint": "9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:32" + }, + { + "Description": "PyPI upload token", + "StartLine": 33, + "EndLine": 33, + "StartColumn": 21, + "EndColumn": 106, + "Match": "************************", + "Secret": "************************", + "File": "detect/detect_test.go", + "Commit": "9326f35380636bcbe61e94b0584d1618c4b5c2c2", + "Entropy": 1.9606875, + "Author": "****", + "Email": "****", + "Date": "2022-03-07T14:33:06Z", + "Message": "Escape - character in regex character groups (#802)\n\n* fix char escape\n\n* add test\n\n* fix verbosity in make test", + "Tags": [], + "RuleID": "pypi-upload-token", + "Fingerprint": "9326f35380636bcbe61e94b0584d1618c4b5c2c2:detect/detect_test.go:pypi-upload-token:33" + } +] diff --git a/cli/testdata/baseline/baseline.sarif b/cli/testdata/baseline/baseline.sarif new file mode 100644 index 000000000..b2f84890a --- /dev/null +++ b/cli/testdata/baseline/baseline.sarif @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + ] +} diff --git a/cli/testdata/config/allow_aws_re.toml b/cli/testdata/config/allow_aws_re.toml new file mode 100644 index 000000000..2e2d4f278 --- /dev/null +++ b/cli/testdata/config/allow_aws_re.toml @@ -0,0 +1,9 @@ +title = "simple config with allowlist for aws" + +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + [rules.allowlist] + regexes = ['''AKIALALEMEL33243OLIA'''] diff --git a/cli/testdata/config/allow_commit.toml b/cli/testdata/config/allow_commit.toml new file mode 100644 index 000000000..ee8fefd83 --- /dev/null +++ b/cli/testdata/config/allow_commit.toml @@ -0,0 +1,9 @@ +title = "simple config with allowlist for a specific commit" + +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + [rules.allowlist] + commits = ['''allowthiscommit'''] diff --git a/cli/testdata/config/allow_global_aws_re.toml b/cli/testdata/config/allow_global_aws_re.toml new file mode 100644 index 000000000..7b7c3eeed --- /dev/null +++ b/cli/testdata/config/allow_global_aws_re.toml @@ -0,0 +1,8 @@ +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + +[allowlist] + regexes = ['''AKIALALEMEL33243OLIA'''] diff --git a/cli/testdata/config/allow_path.toml b/cli/testdata/config/allow_path.toml new file mode 100644 index 000000000..0fa837701 --- /dev/null +++ b/cli/testdata/config/allow_path.toml @@ -0,0 +1,9 @@ +title = "simple config with allowlist for .go files" + +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + [rules.allowlist] + paths = ['''.go'''] diff --git a/cli/testdata/config/bad_entropy_group.toml b/cli/testdata/config/bad_entropy_group.toml new file mode 100755 index 000000000..8e4d1c25c --- /dev/null +++ b/cli/testdata/config/bad_entropy_group.toml @@ -0,0 +1,8 @@ +title = "gitleaks config" + +[[rules]] +id = "discord-api-key" +description = "Discord API key" +regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]''' +secretGroup = 5 +entropy = 3.5 diff --git a/cli/testdata/config/base.toml b/cli/testdata/config/base.toml new file mode 100644 index 000000000..ba7b2ce2c --- /dev/null +++ b/cli/testdata/config/base.toml @@ -0,0 +1,10 @@ +title = "gitleaks config" + +[extend] +path="../testdata/config/extend_1.toml" + +[[rules]] + description = "AWS Secret Key" + id = "aws-secret-key" + regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}''' + tags = ["key", "AWS"] diff --git a/cli/testdata/config/entropy_group.toml b/cli/testdata/config/entropy_group.toml new file mode 100755 index 000000000..eacfc50ea --- /dev/null +++ b/cli/testdata/config/entropy_group.toml @@ -0,0 +1,8 @@ +title = "gitleaks config" + +[[rules]] +id = "discord-api-key" +description = "Discord API key" +regex = '''(?i)(discord[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([a-h0-9]{64})['\"]''' +secretGroup = 3 +entropy = 3.5 diff --git a/cli/testdata/config/escaped_character_group.toml b/cli/testdata/config/escaped_character_group.toml new file mode 100644 index 000000000..b28039539 --- /dev/null +++ b/cli/testdata/config/escaped_character_group.toml @@ -0,0 +1,8 @@ +title = "gitleaks config" +# https://learnxinyminutes.com/docs/toml/ for toml reference + +[[rules]] + id = "pypi-upload-token" + description = "PyPI upload token" + regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9\-_]{50,1000}''' + tags = ["key", "pypi"] \ No newline at end of file diff --git a/cli/testdata/config/extend_1.toml b/cli/testdata/config/extend_1.toml new file mode 100644 index 000000000..1f4eec0f0 --- /dev/null +++ b/cli/testdata/config/extend_1.toml @@ -0,0 +1,10 @@ +title = "gitleaks extended 1" + +[extend] +path="../testdata/config/extend_2.toml" + +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] diff --git a/cli/testdata/config/extend_2.toml b/cli/testdata/config/extend_2.toml new file mode 100644 index 000000000..7532c99e6 --- /dev/null +++ b/cli/testdata/config/extend_2.toml @@ -0,0 +1,10 @@ +title = "gitleaks extended 2" + +[extend] +path="../testdata/config/extend_3.toml" + +[[rules]] + description = "AWS Secret Key" + id = "aws-secret-key-again" + regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}''' + tags = ["key", "AWS"] diff --git a/cli/testdata/config/extend_3.toml b/cli/testdata/config/extend_3.toml new file mode 100644 index 000000000..47644c296 --- /dev/null +++ b/cli/testdata/config/extend_3.toml @@ -0,0 +1,9 @@ +title = "gitleaks extended 3" + +## This should not be loaded since we can only extend configs to a depth of 3 + +[[rules]] + description = "AWS Secret Key" + id = "aws-secret-key-again-again" + regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}''' + tags = ["key", "AWS"] diff --git a/cli/testdata/config/generic.toml b/cli/testdata/config/generic.toml new file mode 100644 index 000000000..625e44efc --- /dev/null +++ b/cli/testdata/config/generic.toml @@ -0,0 +1,8 @@ +title = "gitleaks config" + +[[rules]] +description = "Generic API Key" +id = "generic-api-key" +regex = '''(?i)((key|api|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]''' +entropy = 3.7 +secretGroup = 4 diff --git a/cli/testdata/config/generic_with_py_path.toml b/cli/testdata/config/generic_with_py_path.toml new file mode 100644 index 000000000..a528893e9 --- /dev/null +++ b/cli/testdata/config/generic_with_py_path.toml @@ -0,0 +1,36 @@ +title = "gitleaks config" + +[[rules]] +description = "Generic API Key" +id = "generic-api-key" +regex = '''(?i)((key|api|token|secret|password)[a-z0-9_ .\-,]{0,25})(=|>|:=|\|\|:|<=|=>|:).{0,5}['\"]([0-9a-zA-Z\-_=]{8,64})['\"]''' +path = '''.py''' +entropy = 3.7 +secretGroup = 4 + +[allowlist] +description = "global allow lists" +regexes = [ + '''219-09-9999''', + '''078-05-1120''', + '''(9[0-9]{2}|666)-\d{2}-\d{4}''', + '''process''', + '''getenv''', + '''\.env''', + '''env\(''', + '''env\.''', + '''setting''', + '''load''', + '''token''', + '''password''', + '''secret''', + '''api\_key''', + '''apikey''', + '''api\-key''', + ] +paths = [ + '''gitleaks.toml''', + '''(.*?)(jpg|gif|doc|pdf|bin|svg|socket)$''', + '''(go.mod|go.sum)$''' +] + diff --git a/cli/testdata/config/path_only.toml b/cli/testdata/config/path_only.toml new file mode 100644 index 000000000..97a8a4870 --- /dev/null +++ b/cli/testdata/config/path_only.toml @@ -0,0 +1,6 @@ +title = "gitleaks config" + +[[rules]] +description = "Python Files" +id = "python-files-only" +path = '''.py''' diff --git a/cli/testdata/config/simple.toml b/cli/testdata/config/simple.toml new file mode 100644 index 000000000..c5fbea1c3 --- /dev/null +++ b/cli/testdata/config/simple.toml @@ -0,0 +1,222 @@ +title = "gitleaks config" +# https://learnxinyminutes.com/docs/toml/ for toml reference + +[[rules]] + description = "AWS Access Key" + id = "aws-access-key" + regex = '''(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}''' + tags = ["key", "AWS"] + +[[rules]] + description = "AWS Secret Key" + id = "aws-secret-key" + regex = '''(?i)aws_(.{0,20})?=?.[\'\"0-9a-zA-Z\/+]{40}''' + tags = ["key", "AWS"] + +[[rules]] + description = "AWS MWS key" + id = "aws-mws-key" + regex = '''amzn\.mws\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}''' + tags = ["key", "AWS", "MWS"] + +[[rules]] + description = "Facebook Secret Key" + id = "facebook-secret-key" + regex = '''(?i)(facebook|fb)(.{0,20})?(?-i)['\"][0-9a-f]{32}['\"]''' + tags = ["key", "Facebook"] + +[[rules]] + description = "Facebook Client ID" + id = "facebook-client-id" + regex = '''(?i)(facebook|fb)(.{0,20})?['\"][0-9]{13,17}['\"]''' + tags = ["key", "Facebook"] + +[[rules]] + description = "Twitter Secret Key" + id = "twitter-secret-key" + regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{35,44}['\"]''' + tags = ["key", "Twitter"] + +[[rules]] + description = "Twitter Client ID" + id = "twitter-client-id" + regex = '''(?i)twitter(.{0,20})?['\"][0-9a-z]{18,25}['\"]''' + tags = ["client", "Twitter"] + +[[rules]] + description = "Github Personal Access Token" + id = "github-pat" + regex = '''ghp_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + description = "Github OAuth Access Token" + id = "github-oauth" + regex = '''gho_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + id = "github-app" + description = "Github App Token" + regex = '''(ghu|ghs)_[0-9a-zA-Z]{36}''' + tags = ["key", "Github"] +[[rules]] + id = "github-refresh" + description = "Github Refresh Token" + regex = '''ghr_[0-9a-zA-Z]{76}''' + tags = ["key", "Github"] + +[[rules]] + id = "linkedin-client" + description = "LinkedIn Client ID" + regex = '''(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}''' + tags = ["client", "LinkedIn"] + +[[rules]] + id = "linkedin-secret" + description = "LinkedIn Secret Key" + regex = '''(?i)linkedin(.{0,20})?[0-9a-z]{16}''' + tags = ["secret", "LinkedIn"] + +[[rules]] + id = "slack" + description = "Slack" + regex = '''xox[baprs]-([0-9a-zA-Z]{10,48})?''' + tags = ["key", "Slack"] + +[[rules]] + id = "apkey" + description = "Asymmetric Private Key" + regex = '''-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----''' + tags = ["key", "AsymmetricPrivateKey"] + +[[rules]] + id = "google" + description = "Google API key" + regex = '''AIza[0-9A-Za-z\-_]{35}''' + tags = ["key", "Google"] + +[[rules]] + id = "google" + description = "Google (GCP) Service Account" + regex = '''"type": "service_account"''' + tags = ["key", "Google"] + +[[rules]] + id = "heroku" + description = "Heroku API key" + regex = '''(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}''' + tags = ["key", "Heroku"] + +[[rules]] + id = "mailchimp" + description = "MailChimp API key" + regex = '''(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}''' + tags = ["key", "Mailchimp"] + +[[rules]] + id = "mailgun" + description = "Mailgun API key" + regex = '''((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}''' + tags = ["key", "Mailgun"] + +[[rules]] + id = "paypal" + description = "PayPal Braintree access token" + regex = '''access_token\$production\$[0-9a-z]{16}\$[0-9a-f]{32}''' + tags = ["key", "Paypal"] + +[[rules]] + id = "piacatic" + description = "Picatic API key" + regex = '''sk_live_[0-9a-z]{32}''' + tags = ["key", "Picatic"] + +[[rules]] + id = "sendgrid" + description = "SendGrid API Key" + regex = '''SG\.[\w_]{16,32}\.[\w_]{16,64}''' + tags = ["key", "SendGrid"] + +[[rules]] + description = "Sidekiq Secret" + id = "sidekiq-secret" + regex = '''(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\-_\t .]{0,20})(?:[\s|']|[\s|"]){0,3}(?:=|>|:=|\|\|:|<=|=>|:)(?:'|\"|\s|=|\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\"|\n|\r|\s|\x60|;]|$)''' + secretGroup = 1 + keywords = [ + "bundle_enterprise__contribsys__com","bundle_gems__contribsys__com", + ] + +[[rules]] + description = "Sidekiq Sensitive URL" + id = "sidekiq-sensitive-url" + regex = '''(?i)\b(http(?:s??):\/\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\/|\#|\?|:]|$)''' + secretGroup = 2 + keywords = [ + "gems.contribsys.com","enterprise.contribsys.com", + ] + +[[rules]] + id = "slack-webhook" + description = "Slack Webhook" + regex = '''https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}''' + tags = ["key", "slack"] + +[[rules]] + id = "stripe" + description = "Stripe API key" + regex = '''(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}''' + tags = ["key", "Stripe"] + +[[rules]] + id = "square" + description = "Square access token" + regex = '''sq0atp-[0-9A-Za-z\-_]{22}''' + tags = ["key", "square"] + +[[rules]] + id = "square-oauth" + description = "Square OAuth secret" + regex = '''sq0csp-[0-9A-Za-z\-_]{43}''' + tags = ["key", "square"] + +[[rules]] + id = "twilio" + description = "Twilio API key" + regex = '''(?i)twilio(.{0,20})?SK[0-9a-f]{32}''' + tags = ["key", "twilio"] + +[[rules]] + id = "dynatrace" + description = "Dynatrace ttoken" + regex = '''dt0[a-zA-Z]{1}[0-9]{2}\.[A-Z0-9]{24}\.[A-Z0-9]{64}''' + tags = ["key", "Dynatrace"] + +[[rules]] + id = "shopify" + description = "Shopify shared secret" + regex = '''shpss_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + id = "shopify-access" + description = "Shopify access token" + regex = '''shpat_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + id = "shopify-custom" + description = "Shopify custom app access token" + regex = '''shpca_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + id = "shopify-private" + description = "Shopify private app access token" + regex = '''shppa_[a-fA-F0-9]{32}''' + tags = ["key", "Shopify"] + +[[rules]] + id = "pypi" + description = "PyPI upload token" + regex = '''pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}''' + tags = ["key", "pypi"] + diff --git a/cli/testdata/expected/git/small-branch-foo.txt b/cli/testdata/expected/git/small-branch-foo.txt new file mode 100644 index 000000000..b3554c7ac --- /dev/null +++ b/cli/testdata/expected/git/small-branch-foo.txt @@ -0,0 +1,17 @@ +import ( + "fmt" + "os" +) + // seems safer + aws_token := os.Getenv("AWS_TOKEN") +package foo + +import "fmt" + +func Foo() { + fmt.Println("foo") + + // seems safe + aws_token := "AKIALALEMEL33243OLIA" + fmt.Println(aws_token) +} diff --git a/cli/testdata/expected/git/small.txt b/cli/testdata/expected/git/small.txt new file mode 100644 index 000000000..7235dd3a8 --- /dev/null +++ b/cli/testdata/expected/git/small.txt @@ -0,0 +1,67 @@ +import ( + "fmt" + "os" +) + // seems safer + aws_token := os.Getenv("AWS_TOKEN") +package foo + +import "fmt" + +func Foo() { + fmt.Println("foo") + + // seems safe + aws_token := "AKIALALEMEL33243OLIA" + fmt.Println(aws_token) +} +package api + +import "fmt" + +func PrintHello() { + fmt.Println("hello") +} +import ( + "fmt" + "os" +) + var a = "initial" + fmt.Println(a) + var b, c int = 1, 2 + fmt.Println(b, c) + var d = true + fmt.Println(d) + var e int + fmt.Println(e) + // load secret via env + awsToken := os.Getenv("AWS_TOKEN") + + f := "apple" + fmt.Println(f) + + // opps I added a secret at line 20 + awsToken := "AKIALALEMEL33243OLIA" +package main + +import "fmt" + +func main() { + + var a = "initial" + fmt.Println(a) + + var b, c int = 1, 2 + fmt.Println(b, c) + + var d = true + fmt.Println(d) + + var e int + fmt.Println(e) + + f := "apple" + fmt.Println(f) +} +# test +This is a repo used for testing gitleaks diff --git a/cli/testdata/expected/report/csv_simple.csv b/cli/testdata/expected/report/csv_simple.csv new file mode 100644 index 000000000..a02ab0101 --- /dev/null +++ b/cli/testdata/expected/report/csv_simple.csv @@ -0,0 +1,2 @@ +RuleID,Commit,File,SymlinkFile,Secret,Match,StartLine,EndLine,StartColumn,EndColumn,Author,Message,Date,Email,Fingerprint +test-rule,0000000000000000,auth.py,,a secret,line containing secret,1,2,1,2,John Doe,opps,10-19-2003,johndoe@gmail.com,fingerprint diff --git a/cli/testdata/expected/report/empty.json b/cli/testdata/expected/report/empty.json new file mode 100644 index 000000000..fe51488c7 --- /dev/null +++ b/cli/testdata/expected/report/empty.json @@ -0,0 +1 @@ +[] diff --git a/cli/testdata/expected/report/json_simple.json b/cli/testdata/expected/report/json_simple.json new file mode 100644 index 000000000..c7516f118 --- /dev/null +++ b/cli/testdata/expected/report/json_simple.json @@ -0,0 +1,22 @@ +[ + { + "Description": "", + "StartLine": 1, + "EndLine": 2, + "StartColumn": 1, + "EndColumn": 2, + "Match": "line containing secret", + "Secret": "a secret", + "File": "auth.py", + "SymlinkFile": "", + "Commit": "0000000000000000", + "Entropy": 0, + "Author": "John Doe", + "Email": "johndoe@gmail.com", + "Date": "10-19-2003", + "Message": "opps", + "Tags": [], + "RuleID": "test-rule", + "Fingerprint": "" + } +] diff --git a/cli/testdata/expected/report/sarif_simple.got.sarif b/cli/testdata/expected/report/sarif_simple.got.sarif new file mode 100644 index 000000000..9708dd833 --- /dev/null +++ b/cli/testdata/expected/report/sarif_simple.got.sarif @@ -0,0 +1,302 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "gitleaks", + "semanticVersion": "v8.0.0", + "informationUri": "https://github.com/Infisical/infisical", + "rules": [ + { + "id": "aws-access-key", + "name": "AWS Access Key", + "shortDescription": { + "text": "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" + } + }, + { + "id": "aws-secret-key", + "name": "AWS Secret Key", + "shortDescription": { + "text": "(?i)aws_(.{0,20})?=?.[\\'\\\"0-9a-zA-Z\\/+]{40}" + } + }, + { + "id": "aws-mws-key", + "name": "AWS MWS key", + "shortDescription": { + "text": "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + } + }, + { + "id": "facebook-secret-key", + "name": "Facebook Secret Key", + "shortDescription": { + "text": "(?i)(facebook|fb)(.{0,20})?(?-i)['\\\"][0-9a-f]{32}['\\\"]" + } + }, + { + "id": "facebook-client-id", + "name": "Facebook Client ID", + "shortDescription": { + "text": "(?i)(facebook|fb)(.{0,20})?['\\\"][0-9]{13,17}['\\\"]" + } + }, + { + "id": "twitter-secret-key", + "name": "Twitter Secret Key", + "shortDescription": { + "text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{35,44}['\\\"]" + } + }, + { + "id": "twitter-client-id", + "name": "Twitter Client ID", + "shortDescription": { + "text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{18,25}['\\\"]" + } + }, + { + "id": "github-pat", + "name": "Github Personal Access Token", + "shortDescription": { + "text": "ghp_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-oauth", + "name": "Github OAuth Access Token", + "shortDescription": { + "text": "gho_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-app", + "name": "Github App Token", + "shortDescription": { + "text": "(ghu|ghs)_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-refresh", + "name": "Github Refresh Token", + "shortDescription": { + "text": "ghr_[0-9a-zA-Z]{76}" + } + }, + { + "id": "linkedin-client", + "name": "LinkedIn Client ID", + "shortDescription": { + "text": "(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}" + } + }, + { + "id": "linkedin-secret", + "name": "LinkedIn Secret Key", + "shortDescription": { + "text": "(?i)linkedin(.{0,20})?[0-9a-z]{16}" + } + }, + { + "id": "slack", + "name": "Slack", + "shortDescription": { + "text": "xox[baprs]-([0-9a-zA-Z]{10,48})?" + } + }, + { + "id": "apkey", + "name": "Asymmetric Private Key", + "shortDescription": { + "text": "-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----" + } + }, + { + "id": "google", + "name": "Google (GCP) Service Account", + "shortDescription": { + "text": "\"type\": \"service_account\"" + } + }, + { + "id": "google", + "name": "Google (GCP) Service Account", + "shortDescription": { + "text": "\"type\": \"service_account\"" + } + }, + { + "id": "heroku", + "name": "Heroku API key", + "shortDescription": { + "text": "(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + } + }, + { + "id": "mailchimp", + "name": "MailChimp API key", + "shortDescription": { + "text": "(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}" + } + }, + { + "id": "mailgun", + "name": "Mailgun API key", + "shortDescription": { + "text": "((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}" + } + }, + { + "id": "paypal", + "name": "PayPal Braintree access token", + "shortDescription": { + "text": "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}" + } + }, + { + "id": "piacatic", + "name": "Picatic API key", + "shortDescription": { + "text": "sk_live_[0-9a-z]{32}" + } + }, + { + "id": "sendgrid", + "name": "SendGrid API Key", + "shortDescription": { + "text": "SG\\.[\\w_]{16,32}\\.[\\w_]{16,64}" + } + }, + { + "id": "sidekiq-secret", + "name": "Sidekiq Secret", + "shortDescription": { + "text": "(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|\u003e|:=|\\|\\|:|\u003c=|=\u003e|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60|;]|$)" + } + }, + { + "id": "sidekiq-sensitive-url", + "name": "Sidekiq Sensitive URL", + "shortDescription": { + "text": "(?i)\\b(http(?:s??):\\/\\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\\/|\\#|\\?|:]|$)" + } + }, + { + "id": "slack-webhook", + "name": "Slack Webhook", + "shortDescription": { + "text": "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}" + } + }, + { + "id": "stripe", + "name": "Stripe API key", + "shortDescription": { + "text": "(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}" + } + }, + { + "id": "square", + "name": "Square access token", + "shortDescription": { + "text": "sq0atp-[0-9A-Za-z\\-_]{22}" + } + }, + { + "id": "square-oauth", + "name": "Square OAuth secret", + "shortDescription": { + "text": "sq0csp-[0-9A-Za-z\\-_]{43}" + } + }, + { + "id": "twilio", + "name": "Twilio API key", + "shortDescription": { + "text": "(?i)twilio(.{0,20})?SK[0-9a-f]{32}" + } + }, + { + "id": "dynatrace", + "name": "Dynatrace ttoken", + "shortDescription": { + "text": "dt0[a-zA-Z]{1}[0-9]{2}\\.[A-Z0-9]{24}\\.[A-Z0-9]{64}" + } + }, + { + "id": "shopify", + "name": "Shopify shared secret", + "shortDescription": { + "text": "shpss_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-access", + "name": "Shopify access token", + "shortDescription": { + "text": "shpat_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-custom", + "name": "Shopify custom app access token", + "shortDescription": { + "text": "shpca_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-private", + "name": "Shopify private app access token", + "shortDescription": { + "text": "shppa_[a-fA-F0-9]{32}" + } + }, + { + "id": "pypi", + "name": "PyPI upload token", + "shortDescription": { + "text": "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}" + } + } + ] + } + }, + "results": [ + { + "message": { + "text": "test-rule has detected secret for file auth.py at commit 0000000000000000." + }, + "ruleId": "test-rule", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "auth.py" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "endLine": 2, + "endColumn": 2, + "snippet": { + "text": "a secret" + } + } + } + } + ], + "partialFingerprints": { + "commitSha": "0000000000000000", + "email": "johndoe@gmail.com", + "author": "John Doe", + "date": "10-19-2003", + "commitMessage": "opps" + } + } + ] + } + ] +} diff --git a/cli/testdata/expected/report/sarif_simple.sarif b/cli/testdata/expected/report/sarif_simple.sarif new file mode 100644 index 000000000..0b1b15f70 --- /dev/null +++ b/cli/testdata/expected/report/sarif_simple.sarif @@ -0,0 +1,302 @@ +{ + "$schema": "https://json.schemastore.org/sarif-2.1.0.json", + "version": "2.1.0", + "runs": [ + { + "tool": { + "driver": { + "name": "gitleaks", + "semanticVersion": "v8.0.0", + "informationUri": "https://github.com/gitleaks/gitleaks", + "rules": [ + { + "id": "aws-access-key", + "name": "AWS Access Key", + "shortDescription": { + "text": "(A3T[A-Z0-9]|AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[A-Z0-9]{16}" + } + }, + { + "id": "aws-secret-key", + "name": "AWS Secret Key", + "shortDescription": { + "text": "(?i)aws_(.{0,20})?=?.[\\'\\\"0-9a-zA-Z\\/+]{40}" + } + }, + { + "id": "aws-mws-key", + "name": "AWS MWS key", + "shortDescription": { + "text": "amzn\\.mws\\.[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + } + }, + { + "id": "facebook-secret-key", + "name": "Facebook Secret Key", + "shortDescription": { + "text": "(?i)(facebook|fb)(.{0,20})?(?-i)['\\\"][0-9a-f]{32}['\\\"]" + } + }, + { + "id": "facebook-client-id", + "name": "Facebook Client ID", + "shortDescription": { + "text": "(?i)(facebook|fb)(.{0,20})?['\\\"][0-9]{13,17}['\\\"]" + } + }, + { + "id": "twitter-secret-key", + "name": "Twitter Secret Key", + "shortDescription": { + "text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{35,44}['\\\"]" + } + }, + { + "id": "twitter-client-id", + "name": "Twitter Client ID", + "shortDescription": { + "text": "(?i)twitter(.{0,20})?['\\\"][0-9a-z]{18,25}['\\\"]" + } + }, + { + "id": "github-pat", + "name": "Github Personal Access Token", + "shortDescription": { + "text": "ghp_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-oauth", + "name": "Github OAuth Access Token", + "shortDescription": { + "text": "gho_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-app", + "name": "Github App Token", + "shortDescription": { + "text": "(ghu|ghs)_[0-9a-zA-Z]{36}" + } + }, + { + "id": "github-refresh", + "name": "Github Refresh Token", + "shortDescription": { + "text": "ghr_[0-9a-zA-Z]{76}" + } + }, + { + "id": "linkedin-client", + "name": "LinkedIn Client ID", + "shortDescription": { + "text": "(?i)linkedin(.{0,20})?(?-i)[0-9a-z]{12}" + } + }, + { + "id": "linkedin-secret", + "name": "LinkedIn Secret Key", + "shortDescription": { + "text": "(?i)linkedin(.{0,20})?[0-9a-z]{16}" + } + }, + { + "id": "slack", + "name": "Slack", + "shortDescription": { + "text": "xox[baprs]-([0-9a-zA-Z]{10,48})?" + } + }, + { + "id": "apkey", + "name": "Asymmetric Private Key", + "shortDescription": { + "text": "-----BEGIN ((EC|PGP|DSA|RSA|OPENSSH) )?PRIVATE KEY( BLOCK)?-----" + } + }, + { + "id": "google", + "name": "Google (GCP) Service Account", + "shortDescription": { + "text": "\"type\": \"service_account\"" + } + }, + { + "id": "google", + "name": "Google (GCP) Service Account", + "shortDescription": { + "text": "\"type\": \"service_account\"" + } + }, + { + "id": "heroku", + "name": "Heroku API key", + "shortDescription": { + "text": "(?i)heroku(.{0,20})?[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}" + } + }, + { + "id": "mailchimp", + "name": "MailChimp API key", + "shortDescription": { + "text": "(?i)(mailchimp|mc)(.{0,20})?[0-9a-f]{32}-us[0-9]{1,2}" + } + }, + { + "id": "mailgun", + "name": "Mailgun API key", + "shortDescription": { + "text": "((?i)(mailgun|mg)(.{0,20})?)?key-[0-9a-z]{32}" + } + }, + { + "id": "paypal", + "name": "PayPal Braintree access token", + "shortDescription": { + "text": "access_token\\$production\\$[0-9a-z]{16}\\$[0-9a-f]{32}" + } + }, + { + "id": "piacatic", + "name": "Picatic API key", + "shortDescription": { + "text": "sk_live_[0-9a-z]{32}" + } + }, + { + "id": "sendgrid", + "name": "SendGrid API Key", + "shortDescription": { + "text": "SG\\.[\\w_]{16,32}\\.[\\w_]{16,64}" + } + }, + { + "id": "sidekiq-secret", + "name": "Sidekiq Secret", + "shortDescription": { + "text": "(?i)(?:BUNDLE_ENTERPRISE__CONTRIBSYS__COM|BUNDLE_GEMS__CONTRIBSYS__COM)(?:[0-9a-z\\-_\\t .]{0,20})(?:[\\s|']|[\\s|\"]){0,3}(?:=|\u003e|:=|\\|\\|:|\u003c=|=\u003e|:)(?:'|\\\"|\\s|=|\\x60){0,5}([a-f0-9]{8}:[a-f0-9]{8})(?:['|\\\"|\\n|\\r|\\s|\\x60|;]|$)" + } + }, + { + "id": "sidekiq-sensitive-url", + "name": "Sidekiq Sensitive URL", + "shortDescription": { + "text": "(?i)\\b(http(?:s??):\\/\\/)([a-f0-9]{8}:[a-f0-9]{8})@(?:gems.contribsys.com|enterprise.contribsys.com)(?:[\\/|\\#|\\?|:]|$)" + } + }, + { + "id": "slack-webhook", + "name": "Slack Webhook", + "shortDescription": { + "text": "https://hooks.slack.com/services/T[a-zA-Z0-9_]{8}/B[a-zA-Z0-9_]{8,12}/[a-zA-Z0-9_]{24}" + } + }, + { + "id": "stripe", + "name": "Stripe API key", + "shortDescription": { + "text": "(?i)stripe(.{0,20})?[sr]k_live_[0-9a-zA-Z]{24}" + } + }, + { + "id": "square", + "name": "Square access token", + "shortDescription": { + "text": "sq0atp-[0-9A-Za-z\\-_]{22}" + } + }, + { + "id": "square-oauth", + "name": "Square OAuth secret", + "shortDescription": { + "text": "sq0csp-[0-9A-Za-z\\-_]{43}" + } + }, + { + "id": "twilio", + "name": "Twilio API key", + "shortDescription": { + "text": "(?i)twilio(.{0,20})?SK[0-9a-f]{32}" + } + }, + { + "id": "dynatrace", + "name": "Dynatrace ttoken", + "shortDescription": { + "text": "dt0[a-zA-Z]{1}[0-9]{2}\\.[A-Z0-9]{24}\\.[A-Z0-9]{64}" + } + }, + { + "id": "shopify", + "name": "Shopify shared secret", + "shortDescription": { + "text": "shpss_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-access", + "name": "Shopify access token", + "shortDescription": { + "text": "shpat_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-custom", + "name": "Shopify custom app access token", + "shortDescription": { + "text": "shpca_[a-fA-F0-9]{32}" + } + }, + { + "id": "shopify-private", + "name": "Shopify private app access token", + "shortDescription": { + "text": "shppa_[a-fA-F0-9]{32}" + } + }, + { + "id": "pypi", + "name": "PyPI upload token", + "shortDescription": { + "text": "pypi-AgEIcHlwaS5vcmc[A-Za-z0-9-_]{50,1000}" + } + } + ] + } + }, + "results": [ + { + "message": { + "text": "test-rule has detected secret for file auth.py at commit 0000000000000000." + }, + "ruleId": "test-rule", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "auth.py" + }, + "region": { + "startLine": 1, + "startColumn": 1, + "endLine": 2, + "endColumn": 2, + "snippet": { + "text": "a secret" + } + } + } + } + ], + "partialFingerprints": { + "commitSha": "0000000000000000", + "email": "johndoe@gmail.com", + "author": "John Doe", + "date": "10-19-2003", + "commitMessage": "opps" + } + } + ] + } + ] +} diff --git a/cli/testdata/repos/nogit/main.go b/cli/testdata/repos/nogit/main.go new file mode 100644 index 000000000..acbef43fd --- /dev/null +++ b/cli/testdata/repos/nogit/main.go @@ -0,0 +1,24 @@ +package main + +import "fmt" + +func main() { + + var a = "initial" + fmt.Println(a) + + var b, c int = 1, 2 + fmt.Println(b, c) + + var d = true + fmt.Println(d) + + var e int + fmt.Println(e) + + // opps I added a secret at line 20 + awsToken := "AKIALALEMEL33243OLIA" + + f := "apple" + fmt.Println(f) +} diff --git a/cli/testdata/repos/small/README.md b/cli/testdata/repos/small/README.md new file mode 100644 index 000000000..5cc9baf4d --- /dev/null +++ b/cli/testdata/repos/small/README.md @@ -0,0 +1,2 @@ +# test +This is a repo used for testing gitleaks diff --git a/cli/testdata/repos/small/api/api.go b/cli/testdata/repos/small/api/api.go new file mode 100644 index 000000000..d83247911 --- /dev/null +++ b/cli/testdata/repos/small/api/api.go @@ -0,0 +1,7 @@ +package api + +import "fmt" + +func PrintHello() { + fmt.Println("hello") +} diff --git a/cli/testdata/repos/small/dotGit/COMMIT_EDITMSG b/cli/testdata/repos/small/dotGit/COMMIT_EDITMSG new file mode 100644 index 000000000..0ba1543fd --- /dev/null +++ b/cli/testdata/repos/small/dotGit/COMMIT_EDITMSG @@ -0,0 +1 @@ +removing secret from foo package diff --git a/cli/testdata/repos/small/dotGit/FETCH_HEAD b/cli/testdata/repos/small/dotGit/FETCH_HEAD new file mode 100644 index 000000000..66c1c77ce --- /dev/null +++ b/cli/testdata/repos/small/dotGit/FETCH_HEAD @@ -0,0 +1 @@ +2e1db472eeba53f06c4026ae4566ea022e36598e branch 'main' of github.com:gitleaks/test diff --git a/cli/testdata/repos/small/dotGit/HEAD b/cli/testdata/repos/small/dotGit/HEAD new file mode 100644 index 000000000..b870d8262 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/cli/testdata/repos/small/dotGit/ORIG_HEAD b/cli/testdata/repos/small/dotGit/ORIG_HEAD new file mode 100644 index 000000000..96321ccd4 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/ORIG_HEAD @@ -0,0 +1 @@ +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 diff --git a/cli/testdata/repos/small/dotGit/config b/cli/testdata/repos/small/dotGit/config new file mode 100644 index 000000000..374df60b1 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true +[remote "origin"] + url = git@github.com:gitleaks/test.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "main"] + remote = origin + merge = refs/heads/main diff --git a/cli/testdata/repos/small/dotGit/description b/cli/testdata/repos/small/dotGit/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/cli/testdata/repos/small/dotGit/index b/cli/testdata/repos/small/dotGit/index new file mode 100644 index 000000000..fec9889ae Binary files /dev/null and b/cli/testdata/repos/small/dotGit/index differ diff --git a/cli/testdata/repos/small/dotGit/info/exclude b/cli/testdata/repos/small/dotGit/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/cli/testdata/repos/small/dotGit/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/cli/testdata/repos/small/dotGit/logs/HEAD b/cli/testdata/repos/small/dotGit/logs/HEAD new file mode 100644 index 000000000..8fc59bb3b --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/HEAD @@ -0,0 +1,13 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896362 -0500 checkout: moving from main to remove-secrets +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice 1635896426 -0500 commit: load token via env var +906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896518 -0500 commit: add api package +a122b33c6bad3ee54724f52f2caad385ab1982ab a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896543 -0500 checkout: moving from remove-secrets to api-pkg +a122b33c6bad3ee54724f52f2caad385ab1982ab 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896644 -0500 checkout: moving from api-pkg to main +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: Fast-forward +2e1db472eeba53f06c4026ae4566ea022e36598e 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896716 -0500 checkout: moving from main to foo +2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice 1635896886 -0500 commit: adding foo package with secret +491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896931 -0500 commit: removing secret from foo package +f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635897009 -0500 checkout: moving from foo to main +2e1db472eeba53f06c4026ae4566ea022e36598e f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635897062 -0500 checkout: moving from main to foo +f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635897508 -0500 checkout: moving from foo to main diff --git a/cli/testdata/repos/small/dotGit/logs/refs/heads/api-pkg b/cli/testdata/repos/small/dotGit/logs/refs/heads/api-pkg new file mode 100644 index 000000000..18e1cff1a --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/heads/api-pkg @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896543 -0500 branch: Created from HEAD diff --git a/cli/testdata/repos/small/dotGit/logs/refs/heads/foo b/cli/testdata/repos/small/dotGit/logs/refs/heads/foo new file mode 100644 index 000000000..0588ad530 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/heads/foo @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896716 -0500 branch: Created from HEAD +2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice 1635896886 -0500 commit: adding foo package with secret +491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896931 -0500 commit: removing secret from foo package diff --git a/cli/testdata/repos/small/dotGit/logs/refs/heads/main b/cli/testdata/repos/small/dotGit/logs/refs/heads/main new file mode 100644 index 000000000..50148f0e8 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/heads/main @@ -0,0 +1,2 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: Fast-forward diff --git a/cli/testdata/repos/small/dotGit/logs/refs/heads/remove-secrets b/cli/testdata/repos/small/dotGit/logs/refs/heads/remove-secrets new file mode 100644 index 000000000..58344a340 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/heads/remove-secrets @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896362 -0500 branch: Created from HEAD +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice 1635896426 -0500 commit: load token via env var +906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896518 -0500 commit: add api package diff --git a/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/HEAD b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..a2076e59a --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git diff --git a/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/api-pkg b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/api-pkg new file mode 100644 index 000000000..9c8e059cf --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/api-pkg @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896552 -0500 update by push diff --git a/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/foo b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/foo new file mode 100644 index 000000000..f6aed264f --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/foo @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896935 -0500 update by push diff --git a/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/main b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/main new file mode 100644 index 000000000..530a7894d --- /dev/null +++ b/cli/testdata/repos/small/dotGit/logs/refs/remotes/origin/main @@ -0,0 +1 @@ +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: fast-forward diff --git a/cli/testdata/repos/small/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 b/cli/testdata/repos/small/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 new file mode 100644 index 000000000..dab89999a --- /dev/null +++ b/cli/testdata/repos/small/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 @@ -0,0 +1 @@ +xUÌ1 Â0`×ܯ8nJ––.‚ƒƒ:*(8–´\¤´ɕ$ê þw3 Noxï{Ý$6Ëf1Û~´wF'0øYbF ŠœÏTB�p�ÐãND|ƒ*]uŽCÈSÐT •…ªkLÌ>a²Ž#(ûJm–‘®Ö(©ÚsæðԴ¹]Úëé°=õ÷ô>ð°ú03 \ No newline at end of file diff --git a/cli/testdata/repos/small/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 b/cli/testdata/repos/small/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 new file mode 100644 index 000000000..f9ada0721 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 differ diff --git a/cli/testdata/repos/small/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e b/cli/testdata/repos/small/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e new file mode 100644 index 000000000..5dd33dfc9 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e differ diff --git a/cli/testdata/repos/small/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca b/cli/testdata/repos/small/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca new file mode 100644 index 000000000..754d7397e Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca differ diff --git a/cli/testdata/repos/small/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 b/cli/testdata/repos/small/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 new file mode 100644 index 000000000..5bddb82e2 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 differ diff --git a/cli/testdata/repos/small/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a b/cli/testdata/repos/small/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a new file mode 100644 index 000000000..93acde0f5 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a differ diff --git a/cli/testdata/repos/small/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 b/cli/testdata/repos/small/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 new file mode 100644 index 000000000..ce4a269d3 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 @@ -0,0 +1,3 @@ +x�ŽM +Â0F]çs%™üt +"žÁ¥»I2¡E۔»ðôö ®>x¼_ªË2w@;œz㑈ءCŒXЧ@‘²Ö6 5�)–ÔÆMÖ&†ÌÎF:l'ÌFÇTHďFFÃ1–äiPüéSmðä4ÁcN×o;¦ݷV{]žߗT—˜`=�Áa€³öZ«ƒ»ü«wå ½¾d…}f�u‡�›úKKœ \ No newline at end of file diff --git a/cli/testdata/repos/small/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad b/cli/testdata/repos/small/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad new file mode 100644 index 000000000..5e51e39d4 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad differ diff --git a/cli/testdata/repos/small/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab b/cli/testdata/repos/small/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab new file mode 100644 index 000000000..fbcf357cc Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab differ diff --git a/cli/testdata/repos/small/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 b/cli/testdata/repos/small/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 new file mode 100644 index 000000000..8be258a32 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 differ diff --git a/cli/testdata/repos/small/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a b/cli/testdata/repos/small/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a new file mode 100644 index 000000000..9221b3c0a Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a differ diff --git a/cli/testdata/repos/small/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 b/cli/testdata/repos/small/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 new file mode 100644 index 000000000..ec618b7a9 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 differ diff --git a/cli/testdata/repos/small/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 b/cli/testdata/repos/small/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 new file mode 100644 index 000000000..0bd9a371a Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 differ diff --git a/cli/testdata/repos/small/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 b/cli/testdata/repos/small/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 new file mode 100644 index 000000000..d4a8c3de9 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 differ diff --git a/cli/testdata/repos/small/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb b/cli/testdata/repos/small/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb new file mode 100644 index 000000000..53b83ef00 Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb differ diff --git a/cli/testdata/repos/small/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 b/cli/testdata/repos/small/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 new file mode 100644 index 000000000..a7bf9018e Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 differ diff --git a/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx b/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx new file mode 100644 index 000000000..3cdb2bd0f Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx differ diff --git a/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack b/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack new file mode 100644 index 000000000..975d3711a Binary files /dev/null and b/cli/testdata/repos/small/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack differ diff --git a/cli/testdata/repos/small/dotGit/packed-refs b/cli/testdata/repos/small/dotGit/packed-refs new file mode 100644 index 000000000..859b8c5a8 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 refs/remotes/origin/main diff --git a/cli/testdata/repos/small/dotGit/refs/heads/api-pkg b/cli/testdata/repos/small/dotGit/refs/heads/api-pkg new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/heads/api-pkg @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/small/dotGit/refs/heads/foo b/cli/testdata/repos/small/dotGit/refs/heads/foo new file mode 100644 index 000000000..57d584841 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/heads/foo @@ -0,0 +1 @@ +f1b58b97808f8e744f6a23c693859df5b5968901 diff --git a/cli/testdata/repos/small/dotGit/refs/heads/main b/cli/testdata/repos/small/dotGit/refs/heads/main new file mode 100644 index 000000000..98f12e928 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/heads/main @@ -0,0 +1 @@ +2e1db472eeba53f06c4026ae4566ea022e36598e diff --git a/cli/testdata/repos/small/dotGit/refs/heads/remove-secrets b/cli/testdata/repos/small/dotGit/refs/heads/remove-secrets new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/heads/remove-secrets @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/small/dotGit/refs/remotes/origin/HEAD b/cli/testdata/repos/small/dotGit/refs/remotes/origin/HEAD new file mode 100644 index 000000000..4b0a87595 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/main diff --git a/cli/testdata/repos/small/dotGit/refs/remotes/origin/api-pkg b/cli/testdata/repos/small/dotGit/refs/remotes/origin/api-pkg new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/remotes/origin/api-pkg @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/small/dotGit/refs/remotes/origin/foo b/cli/testdata/repos/small/dotGit/refs/remotes/origin/foo new file mode 100644 index 000000000..57d584841 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/remotes/origin/foo @@ -0,0 +1 @@ +f1b58b97808f8e744f6a23c693859df5b5968901 diff --git a/cli/testdata/repos/small/dotGit/refs/remotes/origin/main b/cli/testdata/repos/small/dotGit/refs/remotes/origin/main new file mode 100644 index 000000000..98f12e928 --- /dev/null +++ b/cli/testdata/repos/small/dotGit/refs/remotes/origin/main @@ -0,0 +1 @@ +2e1db472eeba53f06c4026ae4566ea022e36598e diff --git a/cli/testdata/repos/small/main.go b/cli/testdata/repos/small/main.go new file mode 100644 index 000000000..9a932e37e --- /dev/null +++ b/cli/testdata/repos/small/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "os" +) + +func main() { + + var a = "initial" + fmt.Println(a) + + var b, c int = 1, 2 + fmt.Println(b, c) + + var d = true + fmt.Println(d) + + var e int + fmt.Println(e) + + // load secret via env + awsToken := os.Getenv("AWS_TOKEN") + + f := "apple" + fmt.Println(f) +} diff --git a/cli/testdata/repos/staged/.gitleaksignore b/cli/testdata/repos/staged/.gitleaksignore new file mode 100644 index 000000000..770453ca4 --- /dev/null +++ b/cli/testdata/repos/staged/.gitleaksignore @@ -0,0 +1 @@ +api/api.go:aws-access-key:6 \ No newline at end of file diff --git a/cli/testdata/repos/staged/README.md b/cli/testdata/repos/staged/README.md new file mode 100644 index 000000000..5cc9baf4d --- /dev/null +++ b/cli/testdata/repos/staged/README.md @@ -0,0 +1,2 @@ +# test +This is a repo used for testing gitleaks diff --git a/cli/testdata/repos/staged/api/api.go b/cli/testdata/repos/staged/api/api.go new file mode 100644 index 000000000..b16d768dd --- /dev/null +++ b/cli/testdata/repos/staged/api/api.go @@ -0,0 +1,10 @@ +package api + +import "fmt" + +func PrintHello() { + aws_token := "AKIALALEMEL33243OLIA" // fingerprint of that secret is added to .gitleaksignore + aws_token2 := "AKIALALEMEL33243OLIA" // this one is not + fmt.Println(aws_token) + fmt.Println(aws_token2) +} diff --git a/cli/testdata/repos/staged/dotGit/COMMIT_EDITMSG b/cli/testdata/repos/staged/dotGit/COMMIT_EDITMSG new file mode 100644 index 000000000..b83ad5393 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/COMMIT_EDITMSG @@ -0,0 +1 @@ +add .gitleaksignore file diff --git a/cli/testdata/repos/staged/dotGit/FETCH_HEAD b/cli/testdata/repos/staged/dotGit/FETCH_HEAD new file mode 100644 index 000000000..66c1c77ce --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/FETCH_HEAD @@ -0,0 +1 @@ +2e1db472eeba53f06c4026ae4566ea022e36598e branch 'main' of github.com:gitleaks/test diff --git a/cli/testdata/repos/staged/dotGit/HEAD b/cli/testdata/repos/staged/dotGit/HEAD new file mode 100644 index 000000000..b870d8262 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/cli/testdata/repos/staged/dotGit/ORIG_HEAD b/cli/testdata/repos/staged/dotGit/ORIG_HEAD new file mode 100644 index 000000000..96321ccd4 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/ORIG_HEAD @@ -0,0 +1 @@ +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 diff --git a/cli/testdata/repos/staged/dotGit/config b/cli/testdata/repos/staged/dotGit/config new file mode 100644 index 000000000..374df60b1 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/config @@ -0,0 +1,13 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true + precomposeunicode = true +[remote "origin"] + url = git@github.com:gitleaks/test.git + fetch = +refs/heads/*:refs/remotes/origin/* +[branch "main"] + remote = origin + merge = refs/heads/main diff --git a/cli/testdata/repos/staged/dotGit/description b/cli/testdata/repos/staged/dotGit/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/cli/testdata/repos/staged/dotGit/index b/cli/testdata/repos/staged/dotGit/index new file mode 100644 index 000000000..42a3c4433 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/index differ diff --git a/cli/testdata/repos/staged/dotGit/info/exclude b/cli/testdata/repos/staged/dotGit/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/cli/testdata/repos/staged/dotGit/logs/HEAD b/cli/testdata/repos/staged/dotGit/logs/HEAD new file mode 100644 index 000000000..928095a13 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/HEAD @@ -0,0 +1,14 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896362 -0500 checkout: moving from main to remove-secrets +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice 1635896426 -0500 commit: load token via env var +906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896518 -0500 commit: add api package +a122b33c6bad3ee54724f52f2caad385ab1982ab a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896543 -0500 checkout: moving from remove-secrets to api-pkg +a122b33c6bad3ee54724f52f2caad385ab1982ab 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896644 -0500 checkout: moving from api-pkg to main +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: Fast-forward +2e1db472eeba53f06c4026ae4566ea022e36598e 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896716 -0500 checkout: moving from main to foo +2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice 1635896886 -0500 commit: adding foo package with secret +491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896931 -0500 commit: removing secret from foo package +f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635897009 -0500 checkout: moving from foo to main +2e1db472eeba53f06c4026ae4566ea022e36598e f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635897062 -0500 checkout: moving from main to foo +f1b58b97808f8e744f6a23c693859df5b5968901 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635897508 -0500 checkout: moving from foo to main +2e1db472eeba53f06c4026ae4566ea022e36598e bf3f24164d7256b4021575cbdb2f97b98e6f057e Rafael Figueiredo 1679239434 -0300 commit: add .gitleaksignore file diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/heads/api-pkg b/cli/testdata/repos/staged/dotGit/logs/refs/heads/api-pkg new file mode 100644 index 000000000..18e1cff1a --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/heads/api-pkg @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896543 -0500 branch: Created from HEAD diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/heads/foo b/cli/testdata/repos/staged/dotGit/logs/refs/heads/foo new file mode 100644 index 000000000..0588ad530 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/heads/foo @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896716 -0500 branch: Created from HEAD +2e1db472eeba53f06c4026ae4566ea022e36598e 491504d5a31946ce75e22554cc34203d8e5ff3ca Zach Rice 1635896886 -0500 commit: adding foo package with secret +491504d5a31946ce75e22554cc34203d8e5ff3ca f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896931 -0500 commit: removing secret from foo package diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/heads/main b/cli/testdata/repos/staged/dotGit/logs/refs/heads/main new file mode 100644 index 000000000..c4bd6cb68 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/heads/main @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: Fast-forward +2e1db472eeba53f06c4026ae4566ea022e36598e bf3f24164d7256b4021575cbdb2f97b98e6f057e Rafael Figueiredo 1679239434 -0300 commit: add .gitleaksignore file diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/heads/remove-secrets b/cli/testdata/repos/staged/dotGit/logs/refs/heads/remove-secrets new file mode 100644 index 000000000..58344a340 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/heads/remove-secrets @@ -0,0 +1,3 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896362 -0500 branch: Created from HEAD +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 906335481df9a4b48906c90318b4fac76b67fe73 Zach Rice 1635896426 -0500 commit: load token via env var +906335481df9a4b48906c90318b4fac76b67fe73 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896518 -0500 commit: add api package diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/HEAD b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/HEAD new file mode 100644 index 000000000..a2076e59a --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 Zach Rice 1635896329 -0500 clone: from github.com:gitleaks/test.git diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/api-pkg b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/api-pkg new file mode 100644 index 000000000..9c8e059cf --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/api-pkg @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 a122b33c6bad3ee54724f52f2caad385ab1982ab Zach Rice 1635896552 -0500 update by push diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/foo b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/foo new file mode 100644 index 000000000..f6aed264f --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/foo @@ -0,0 +1 @@ +0000000000000000000000000000000000000000 f1b58b97808f8e744f6a23c693859df5b5968901 Zach Rice 1635896935 -0500 update by push diff --git a/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/main b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/main new file mode 100644 index 000000000..530a7894d --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/logs/refs/remotes/origin/main @@ -0,0 +1 @@ +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 2e1db472eeba53f06c4026ae4566ea022e36598e Zach Rice 1635896648 -0500 pull origin main: fast-forward diff --git a/cli/testdata/repos/staged/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 b/cli/testdata/repos/staged/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 new file mode 100644 index 000000000..dab89999a --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/objects/02/d85657604c34e7b7fbb324a0c6c8b13c2c3760 @@ -0,0 +1 @@ +xUÌ1 Â0`×ܯ8nJ––.‚ƒƒ:*(8–´\¤´ɕ$ê þw3 Noxï{Ý$6Ëf1Û~´wF'0øYbF ŠœÏTB�p�ÐãND|ƒ*]uŽCÈSÐT •…ªkLÌ>a²Ž#(ûJm–‘®Ö(©ÚsæðԴ¹]Úëé°=õ÷ô>ð°ú03 \ No newline at end of file diff --git a/cli/testdata/repos/staged/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 b/cli/testdata/repos/staged/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 new file mode 100644 index 000000000..f9ada0721 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/15/2888a42422b2ff5868b8d003d626120a9cb738 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e b/cli/testdata/repos/staged/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e new file mode 100644 index 000000000..5dd33dfc9 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/2e/1db472eeba53f06c4026ae4566ea022e36598e differ diff --git a/cli/testdata/repos/staged/dotGit/objects/46/18d7e4512b6b0b1dab85cf846d9f43474ec8be b/cli/testdata/repos/staged/dotGit/objects/46/18d7e4512b6b0b1dab85cf846d9f43474ec8be new file mode 100644 index 000000000..92ce09d28 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/46/18d7e4512b6b0b1dab85cf846d9f43474ec8be differ diff --git a/cli/testdata/repos/staged/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca b/cli/testdata/repos/staged/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca new file mode 100644 index 000000000..754d7397e Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/49/1504d5a31946ce75e22554cc34203d8e5ff3ca differ diff --git a/cli/testdata/repos/staged/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 b/cli/testdata/repos/staged/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 new file mode 100644 index 000000000..5bddb82e2 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/5c/547e4215d9594c3935bdfefdf4f500016a4112 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/65/83d6db4a57bbeda62d50fc91649036d499418d b/cli/testdata/repos/staged/dotGit/objects/65/83d6db4a57bbeda62d50fc91649036d499418d new file mode 100644 index 000000000..b6fec1e0b Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/65/83d6db4a57bbeda62d50fc91649036d499418d differ diff --git a/cli/testdata/repos/staged/dotGit/objects/66/bc70d0c0bfbb6468b3f90c3f1e9f2ddba02b43 b/cli/testdata/repos/staged/dotGit/objects/66/bc70d0c0bfbb6468b3f90c3f1e9f2ddba02b43 new file mode 100644 index 000000000..f6622df7e Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/66/bc70d0c0bfbb6468b3f90c3f1e9f2ddba02b43 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a b/cli/testdata/repos/staged/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a new file mode 100644 index 000000000..93acde0f5 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/78/9ba677976d5db481de55c799d67acbf8e3f16a differ diff --git a/cli/testdata/repos/staged/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 b/cli/testdata/repos/staged/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 new file mode 100644 index 000000000..ce4a269d3 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/objects/90/6335481df9a4b48906c90318b4fac76b67fe73 @@ -0,0 +1,3 @@ +x�ŽM +Â0F]çs%™üt +"žÁ¥»I2¡E۔»ðôö ®>x¼_ªË2w@;œz㑈ءCŒXЧ@‘²Ö6 5�)–ÔÆMÖ&†ÌÎF:l'ÌFÇTHďFFÃ1–äiPüéSmðä4ÁcN×o;¦ݷV{]žߗT—˜`=�Áa€³öZ«ƒ»ü«wå ½¾d…}f�u‡�›úKKœ \ No newline at end of file diff --git a/cli/testdata/repos/staged/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad b/cli/testdata/repos/staged/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad new file mode 100644 index 000000000..5e51e39d4 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/9a/932e37eaa9fb64b09e47e5e859c9b2c8cb47ad differ diff --git a/cli/testdata/repos/staged/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab b/cli/testdata/repos/staged/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab new file mode 100644 index 000000000..fbcf357cc Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/a1/22b33c6bad3ee54724f52f2caad385ab1982ab differ diff --git a/cli/testdata/repos/staged/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 b/cli/testdata/repos/staged/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 new file mode 100644 index 000000000..8be258a32 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/a5/caae6d742e49a33982f1fdc608ce861ea59be5 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a b/cli/testdata/repos/staged/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a new file mode 100644 index 000000000..9221b3c0a Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/a9/aa0c942dcef669a94f207a77426106b25efd1a differ diff --git a/cli/testdata/repos/staged/dotGit/objects/b1/6d768dd595a59f947abe087901183d219d7e54 b/cli/testdata/repos/staged/dotGit/objects/b1/6d768dd595a59f947abe087901183d219d7e54 new file mode 100644 index 000000000..6ba6deaf0 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/b1/6d768dd595a59f947abe087901183d219d7e54 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 b/cli/testdata/repos/staged/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 new file mode 100644 index 000000000..ec618b7a9 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/bc/f47ef84f29bb7ed6e653d61fccd30d0ecce886 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/bf/3f24164d7256b4021575cbdb2f97b98e6f057e b/cli/testdata/repos/staged/dotGit/objects/bf/3f24164d7256b4021575cbdb2f97b98e6f057e new file mode 100644 index 000000000..897417b68 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/objects/bf/3f24164d7256b4021575cbdb2f97b98e6f057e @@ -0,0 +1,2 @@ +x¥ŽAn!sæó�X³ÀÎɲ|Êòƒš5ÊÚX˜ý¬ò[ª*uj·[dçð1:@"1-œ9q,1Š—ct%preB(6ç¨l£wæ¡÷—ˆ)G¿X êì +KòlEág¼P 's8Âè>®­ӷÅF_uÝQ;r£S/ÿã²jozH[Ûó™&Y‚uÁ;OŸì˜Mú;;ðfÆhÎtXëؠ?ϺÞ[•ºÁü_]U \ No newline at end of file diff --git a/cli/testdata/repos/staged/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 b/cli/testdata/repos/staged/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 new file mode 100644 index 000000000..0bd9a371a Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/d8/32479114dc6be7207edc7c37ce91dd11b93161 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 b/cli/testdata/repos/staged/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 new file mode 100644 index 000000000..d4a8c3de9 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/da/2622b4d97e32c5801511244b809144b6b3ea78 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb b/cli/testdata/repos/staged/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb new file mode 100644 index 000000000..53b83ef00 Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/e5/c0849a65c586eab87dcfc31fec74f0fd7c62cb differ diff --git a/cli/testdata/repos/staged/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 b/cli/testdata/repos/staged/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 new file mode 100644 index 000000000..a7bf9018e Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/f1/b58b97808f8e744f6a23c693859df5b5968901 differ diff --git a/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx b/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx new file mode 100644 index 000000000..3cdb2bd0f Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.idx differ diff --git a/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack b/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack new file mode 100644 index 000000000..975d3711a Binary files /dev/null and b/cli/testdata/repos/staged/dotGit/objects/pack/pack-2cdc2976b84768d0829c75cc8d8fc4d849be62cd.pack differ diff --git a/cli/testdata/repos/staged/dotGit/packed-refs b/cli/testdata/repos/staged/dotGit/packed-refs new file mode 100644 index 000000000..859b8c5a8 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled fully-peeled sorted +1b6da43b82b22e4eaa10bcf8ee591e91abbfc587 refs/remotes/origin/main diff --git a/cli/testdata/repos/staged/dotGit/refs/heads/api-pkg b/cli/testdata/repos/staged/dotGit/refs/heads/api-pkg new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/heads/api-pkg @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/staged/dotGit/refs/heads/foo b/cli/testdata/repos/staged/dotGit/refs/heads/foo new file mode 100644 index 000000000..57d584841 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/heads/foo @@ -0,0 +1 @@ +f1b58b97808f8e744f6a23c693859df5b5968901 diff --git a/cli/testdata/repos/staged/dotGit/refs/heads/main b/cli/testdata/repos/staged/dotGit/refs/heads/main new file mode 100644 index 000000000..a06d4d30f --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/heads/main @@ -0,0 +1 @@ +bf3f24164d7256b4021575cbdb2f97b98e6f057e diff --git a/cli/testdata/repos/staged/dotGit/refs/heads/remove-secrets b/cli/testdata/repos/staged/dotGit/refs/heads/remove-secrets new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/heads/remove-secrets @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/staged/dotGit/refs/remotes/origin/HEAD b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/HEAD new file mode 100644 index 000000000..4b0a87595 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/HEAD @@ -0,0 +1 @@ +ref: refs/remotes/origin/main diff --git a/cli/testdata/repos/staged/dotGit/refs/remotes/origin/api-pkg b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/api-pkg new file mode 100644 index 000000000..31b6c7893 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/api-pkg @@ -0,0 +1 @@ +a122b33c6bad3ee54724f52f2caad385ab1982ab diff --git a/cli/testdata/repos/staged/dotGit/refs/remotes/origin/foo b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/foo new file mode 100644 index 000000000..57d584841 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/foo @@ -0,0 +1 @@ +f1b58b97808f8e744f6a23c693859df5b5968901 diff --git a/cli/testdata/repos/staged/dotGit/refs/remotes/origin/main b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/main new file mode 100644 index 000000000..98f12e928 --- /dev/null +++ b/cli/testdata/repos/staged/dotGit/refs/remotes/origin/main @@ -0,0 +1 @@ +2e1db472eeba53f06c4026ae4566ea022e36598e diff --git a/cli/testdata/repos/staged/main.go b/cli/testdata/repos/staged/main.go new file mode 100644 index 000000000..9a932e37e --- /dev/null +++ b/cli/testdata/repos/staged/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "fmt" + "os" +) + +func main() { + + var a = "initial" + fmt.Println(a) + + var b, c int = 1, 2 + fmt.Println(b, c) + + var d = true + fmt.Println(d) + + var e int + fmt.Println(e) + + // load secret via env + awsToken := os.Getenv("AWS_TOKEN") + + f := "apple" + fmt.Println(f) +} diff --git a/cli/testdata/repos/symlinks/file_symlink/symlinked_id_ed25519 b/cli/testdata/repos/symlinks/file_symlink/symlinked_id_ed25519 new file mode 120000 index 000000000..fd0203d88 --- /dev/null +++ b/cli/testdata/repos/symlinks/file_symlink/symlinked_id_ed25519 @@ -0,0 +1 @@ +../source_file/id_ed25519 \ No newline at end of file diff --git a/cli/testdata/repos/symlinks/source_file/id_ed25519 b/cli/testdata/repos/symlinks/source_file/id_ed25519 new file mode 100644 index 000000000..9f4ff614b --- /dev/null +++ b/cli/testdata/repos/symlinks/source_file/id_ed25519 @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACA8YWKYztuuvxUIMomc3zv0OdXCT57Cc2cRYu3TMbX9XAAAAJDiKO3C4ijt +wgAAAAtzc2gtZWQyNTUxOQAAACA8YWKYztuuvxUIMomc3zv0OdXCT57Cc2cRYu3TMbX9XA +AAAECzmj8DGxg5YHtBK4AmBttMXDQHsPAaCyYHQjJ4YujRBTxhYpjO266/FQgyiZzfO/Q5 +1cJPnsJzZxFi7dMxtf1cAAAADHJvb3RAZGV2aG9zdAE= +-----END OPENSSH PRIVATE KEY----- diff --git a/cli/testdata/tmp/note.txt b/cli/testdata/tmp/note.txt new file mode 100644 index 000000000..429d60380 --- /dev/null +++ b/cli/testdata/tmp/note.txt @@ -0,0 +1 @@ +nothing should be saved here diff --git a/cloudformation/ec2-deployment/infisical-ec2-deployment.template b/cloudformation/ec2-deployment/infisical-ec2-deployment.template index 36f0d9dce..2db93b779 100644 --- a/cloudformation/ec2-deployment/infisical-ec2-deployment.template +++ b/cloudformation/ec2-deployment/infisical-ec2-deployment.template @@ -96,6 +96,7 @@ Resources: echo "JWT_AUTH_SECRET=${!JWT_AUTH_SECRET}" >> .env echo "JWT_SERVICE_SECRET=${!JWT_SERVICE_SECRET}" >> .env echo "MONGO_URL=${!DOCUMENT_DB_CONNECTION_URL}" >> .env + echo "HTTPS_ENABLED=false" >> .env docker-compose up -d diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 287e80945..ad5a3ce02 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -37,6 +37,8 @@ services: - MONGO_URL=mongodb://root:example@mongo:27017/?authSource=admin networks: - infisical-dev + extra_hosts: + - "host.docker.internal:host-gateway" frontend: container_name: infisical-dev-frontend @@ -49,7 +51,6 @@ services: volumes: - ./frontend/src:/app/src/ # mounted whole src to avoid missing reload on new files - ./frontend/public:/app/public - - ./frontend/next-i18next.config.js:/app/next-i18next.config.js env_file: .env environment: - NEXT_PUBLIC_ENV=development diff --git a/docs/api-reference/endpoints/secrets/create.mdx b/docs/api-reference/endpoints/secrets/create.mdx index 2fba642a7..85d8ed350 100644 --- a/docs/api-reference/endpoints/secrets/create.mdx +++ b/docs/api-reference/endpoints/secrets/create.mdx @@ -1,11 +1,11 @@ --- title: "Create" -openapi: "POST /api/v2/secrets/" +openapi: "POST /api/v3/secrets/{secretName}" --- Using this route requires understanding Infisical's system and cryptography. It may be helpful to read through the [introduction](/api-reference/overview/introduction) and [guide for creating - secrets](/api-reference/overview/examples/create-secrets). + secrets](/api-reference/overview/examples/create-secret). diff --git a/docs/api-reference/endpoints/secrets/delete.mdx b/docs/api-reference/endpoints/secrets/delete.mdx index af87e7120..d4084a465 100644 --- a/docs/api-reference/endpoints/secrets/delete.mdx +++ b/docs/api-reference/endpoints/secrets/delete.mdx @@ -1,4 +1,4 @@ --- title: "Delete" -openapi: "DELETE /api/v2/secrets/" +openapi: "DELETE /api/v3/secrets/{secretName}" --- diff --git a/docs/api-reference/endpoints/secrets/read-one.mdx b/docs/api-reference/endpoints/secrets/read-one.mdx new file mode 100644 index 000000000..6dbbcd726 --- /dev/null +++ b/docs/api-reference/endpoints/secrets/read-one.mdx @@ -0,0 +1,11 @@ +--- +title: "Retrieve" +openapi: "GET /api/v3/secrets/{secretName}" +--- + + + Using this route requires understanding Infisical's system and cryptography. + It may be helpful to read through the + [introduction](/api-reference/overview/introduction) and [guide for retrieving + secrets](/api-reference/overview/examples/retrieve-secret). + diff --git a/docs/api-reference/endpoints/secrets/read.mdx b/docs/api-reference/endpoints/secrets/read.mdx index bc30ec8f2..ab258bdba 100644 --- a/docs/api-reference/endpoints/secrets/read.mdx +++ b/docs/api-reference/endpoints/secrets/read.mdx @@ -1,11 +1,11 @@ --- -title: "Retrieve" -openapi: "GET /api/v2/secrets/" +title: "Retrieve All" +openapi: "GET /api/v3/secrets/" --- Using this route requires understanding Infisical's system and cryptography. It may be helpful to read through the [introduction](/api-reference/overview/introduction) and [guide for retrieving - secrets](/api-reference/overview/examples/retrieve-secrets). + secrets](/api-reference/overview/examples/retrieve-secret). diff --git a/docs/api-reference/endpoints/secrets/update.mdx b/docs/api-reference/endpoints/secrets/update.mdx index c77a9de12..594d8201c 100644 --- a/docs/api-reference/endpoints/secrets/update.mdx +++ b/docs/api-reference/endpoints/secrets/update.mdx @@ -1,11 +1,11 @@ --- title: "Update" -openapi: "PATCH /api/v2/secrets/" +openapi: "PATCH /api/v3/secrets/{secretName}" --- Using this route requires understanding Infisical's system and cryptography. It may be helpful to read through the [introduction](/api-reference/overview/introduction) and [guide for updating - secrets](/api-reference/overview/examples/update-secrets). + secrets](/api-reference/overview/examples/update-secret). diff --git a/docs/api-reference/overview/authentication.mdx b/docs/api-reference/overview/authentication.mdx index 7df8f10e5..5fa4fbc30 100644 --- a/docs/api-reference/overview/authentication.mdx +++ b/docs/api-reference/overview/authentication.mdx @@ -1,25 +1,31 @@ --- title: "Authentication" +description: "How to authenticate with the Infisical Public API" --- -To authenticate requests with Infisical, you can either use an API Key or [Infisical Token](../../../getting-started/dashboard/token); certain endpoints will accept either one or both. -- API Key: This general-purpose authentication token provides user access to most endpoints in this reference. -- [Infisical Token](../../../getting-started/dashboard/token): This authentication token (also referred to as the service token) is scoped to a specific project and environment and used for CRUD secret operations. +The Public API accepts multiple modes of authentication being via [Infisical Token](/documentation/platform/token) or API Key. - - -To authenticate requests with Infisical using the API Key, you must include an API key in the `X-API-KEY` header of HTTP requests made to the platform. +- [Infisical Token](/documentation/platform/token): Provides short-lived, scoped CRUD access to the secrets of a specific project and environment. +- API Key: Provides full access to all endpoints representing the user without ability to encrypt/decrypt secrets for **E2EE** endpoints. -You can obtain an API key in User Settings > API Keys + + + The Infisical Token mode uses an Infisical Token to authenticate with the API. -![API key dashboard](../../images/api-key-dashboard.png) -![API key in personal settings](../../images/api-key-settings.png) - - -To authenticate requests with Infisical using the Infisical Token, you must include your Infisical Token in the `Authorization` header of HTTP requests made to the platform with the value `Bearer st.`. + To authenticate requests with Infisical using the Infisical Token, you must include your Infisical Token in the `Authorization` header of HTTP requests made to the platform with the value `Bearer `. -You can obtain an Infisical Token in Project Settings > Service Tokens. + You can obtain an Infisical Token in Project Settings > Service Tokens. -![token add](../../images/project-token-add.png) - - \ No newline at end of file + ![token add](../../images/project-token-add.png) + + + The API key mode uses an API key to authenticate with the API. + + To authenticate requests with Infisical using the API Key, you must include an API key in the `X-API-KEY` header of HTTP requests made to the platform. + + You can obtain an API key in User Settings > API Keys + + ![API key dashboard](../../images/api-key-dashboard.png) + ![API key in personal settings](../../images/api-key-settings.png) + + \ No newline at end of file diff --git a/docs/api-reference/overview/blind-indices.mdx b/docs/api-reference/overview/blind-indices.mdx new file mode 100644 index 000000000..755ba682f --- /dev/null +++ b/docs/api-reference/overview/blind-indices.mdx @@ -0,0 +1,18 @@ +--- +title: "Blind Indices" +--- + +In April 2023, we added the capability for users to query for secrets by name to improve the user experience of Infisical. Previously, it was only possible to query by id of the secret or fetch all secrets belonging to a project and environment. + +Blind indexing must be enabled for projects created prior to April 2023 to take effect. If your project can be blind indexed, then you'll see a section in your project settings appear as shown below: + +![project enable blind indices](../../images/project-settings-blind-indices.png) + + +It works using virtually irreversible blind indices generated by applying `argon2id` to the name of each secret and a random 128-bit salt assigned to each project on the server. We continue to keep the values of secrets E2EE by default. + +You can read more about it [here](/security/mechanics). + + + As previously mentioned, all projects made after April 2023 are automatically blind indexed. If you created a project before this date, you have to enable it manually in your project settings. + \ No newline at end of file diff --git a/docs/api-reference/overview/examples/create-secrets.mdx b/docs/api-reference/overview/examples/create-secrets.mdx deleted file mode 100644 index a20e9f2e3..000000000 --- a/docs/api-reference/overview/examples/create-secrets.mdx +++ /dev/null @@ -1,247 +0,0 @@ ---- -title: "Create secrets" ---- - -In this example, we demonstrate how to add secrets to a project and environment using an Infisical Token. - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- Create an [Infisical Token](../../../getting-started/dashboard/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. Decrypt the (encrypted) project key with the key from your Infisical Token. -3. Encrypt your secret(s) with the project key -4. [Send (encrypted) secret(s) to Infical](/api-reference/endpoints/secrets/create) - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); -const nacl = require('tweetnacl'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; -const BLOCK_SIZE_BYTES = 16; - -const encrypt = ({ text, secret }) => { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); - const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); - - let ciphertext = cipher.update(text, 'utf8', 'base64'); - ciphertext += cipher.final('base64'); - return { - ciphertext, - iv: iv.toString('base64'), - tag: cipher.getAuthTag().toString('base64') - }; -} - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const createSecrets = async () => { - const serviceToken = ''; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - const secretType = 'shared'; // 'shared' or 'personal' - const secretKey = 'some_key'; - const secretValue = 'some_value'; - const secretComment = 'some_comment'; - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 3. Encrypt your secret(s) with the project key - const { - ciphertext: secretKeyCiphertext, - iv: secretKeyIV, - tag: secretKeyTag - } = encrypt({ - text: secretKey, - secret: projectKey - }); - - const { - ciphertext: secretValueCiphertext, - iv: secretValueIV, - tag: secretValueTag - } = encrypt({ - text: secretValue, - secret: projectKey - }); - - const { - ciphertext: secretCommentCiphertext, - iv: secretCommentIV, - tag: secretCommentTag - } = encrypt({ - text: secretComment, - secret: projectKey - }); - - const secret = { - type: secretType, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - } - - // 4. Send (encrypted) secret(s) to Infisical - await axios.post( - `${BASE_URL}/api/v2/secrets`, - { - workspaceId: serviceTokenData.workspace, - environment: serviceTokenData.environment, - secrets: [secret] - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); -} - -createSecrets(); -``` - - - -```Python -import base64 -import requests -from Cryptodome.Cipher import AES -from Cryptodome.Random import get_random_bytes - - -BASE_URL = "https://app.infisical.com" -BLOCK_SIZE_BYTES = 16 - - -def encrypt(text, secret): - iv = get_random_bytes(BLOCK_SIZE_BYTES) - secret = bytes(secret, "utf-8") - cipher = AES.new(secret, AES.MODE_GCM, iv) - ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) - return { - "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), - "tag": base64.standard_b64encode(tag).decode("utf-8"), - "iv": base64.standard_b64encode(iv).decode("utf-8"), - } - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def create_secrets(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - secret_type = "shared" # "shared or "personal" - secret_key = "some_key" - secret_value = "some_value" - secret_comment = "some_comment" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 3. Encrypt your secret(s) with the project key - encrypted_key_data = encrypt(text=secret_key, secret=project_key) - encrypted_value_data = encrypt(text=secret_value, secret=project_key) - encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) - - secret = { - "type": secret_type, - "secretKeyCiphertext": encrypted_key_data["ciphertext"], - "secretKeyIV": encrypted_key_data["iv"], - "secretKeyTag": encrypted_key_data["tag"], - "secretValueCiphertext": encrypted_value_data["ciphertext"], - "secretValueIV": encrypted_value_data["iv"], - "secretValueTag": encrypted_value_data["tag"], - "secretCommentCiphertext": encrypted_comment_data["ciphertext"], - "secretCommentIV": encrypted_comment_data["iv"], - "secretCommentTag": encrypted_comment_data["tag"], - } - - # 4. Send (encrypted) secret (s) to Infisical - requests.post( - f"{BASE_URL}/api/v2/secrets", - json={ - "workspaceId": service_token_data["workspace"], - "environment": service_token_data["environment"], - "secrets": [secret], - }, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -create_secrets() - -``` - - - - - This example uses [TweetNaCl.js](https://tweetnacl.js.org/#/), a port of - TweetNacl/Nacl, to perform asymmeric decryption of the project key but there - are ports of NaCl available in every major language. - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/delete-secrets.mdx b/docs/api-reference/overview/examples/delete-secrets.mdx deleted file mode 100644 index 766f674ca..000000000 --- a/docs/api-reference/overview/examples/delete-secrets.mdx +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: "Delete secrets" ---- - -In this example, we demonstrate how to delete secrets - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- Create either an [API Key](/api-reference/overview/authentication) or [Infisical Token](../../../getting-started/dashboard/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). - -## Example - - - -```js -const axios = require('axios'); -const BASE_URL = 'https://app.infisical.com'; - -const deleteSecrets = async () => { - const serviceToken = 'your_service_token'; - const secretId = 'id_of_secret_to_delete'; - - // 6. Send ID(s) of secret(s) to delete to the Infisical API - await axios.delete( - `${BASE_URL}/api/v2/secrets`, - { - secretIds: [secretId], - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - }, - } - ); -}; - -deleteSecrets(); -``` - - - -```Python -import requests - -BASE_URL = "https://app.infisical.com" - - -def delete_secrets(): - service_token = "" - secret_id = "id_of_secret_to_delete" - - # Send ID(s) of secret(s) to delete to the Infisical API - requests.delete( - f"{BASE_URL}/api/v2/secrets", - json={"secretIds": [secret_id]}, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -delete_secrets() - -``` - - - - If using an `API_KEY` to authenticate with the Infisical API, then you should include it in the `X_API_KEY` header. - - diff --git a/docs/api-reference/overview/examples/e2ee-disabled.mdx b/docs/api-reference/overview/examples/e2ee-disabled.mdx new file mode 100644 index 000000000..9864a1ff5 --- /dev/null +++ b/docs/api-reference/overview/examples/e2ee-disabled.mdx @@ -0,0 +1,176 @@ +--- +title: "E2EE Disabled" +--- + +Using Infisical's API to read/write secrets with E2EE disabled allows you to create, update, and retrieve secrets +in plaintext. Effectively, this means each such secret operation only requires 1 HTTP call. + + + + Retrieve all secrets for an Infisical project and environment. + + + + ```bash + curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw?environment=environment&workspaceId=workspaceId' \ + --header 'Authorization: Bearer serviceToken' + + ``` + + + + + The ID of the workspace + + + The environment slug + + + Path to secrets in workspace + + + + Create a secret in Infisical. + + + + ```bash + curl --location --request POST 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretValue": "secretValue", + "secretPath": "/" + }' + ``` + + + + + Name of secret to create + + + The ID of the workspace + + + The environment slug + + + Value of secret + + + Comment of secret + + + Path to secret in workspace + + + The type of the secret. Valid options are “shared” or “personal” + + + + Retrieve a secret from Infisical. + + + + ```bash + curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw/secretName?workspaceId=workspaceId&environment=environment' \ + --header 'Authorization: Bearer serviceToken' + ``` + + + + + Name of secret to retrieve + + + The ID of the workspace + + + The environment slug + + + Path to secrets in workspace + + + The type of the secret. Valid options are “shared” or “personal” + + + + Update an existing secret in Infisical. + + + + ```bash + curl --location --request PATCH 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretValue": "secretValue", + "secretPath": "/" + }' + ``` + + + + + Name of secret to update + + + The ID of the workspace + + + The environment slug + + + Value of secret + + + Path to secret in workspace. + + + The type of the secret. Valid options are “shared” or “personal” + + + + Delete a secret in Infisical. + + + + ```bash + curl --location --request DELETE 'https://app.infisical.com/api/v3/secrets/raw/secretName' \ + --header 'Authorization: Bearer serviceToken' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "workspaceId": "workspaceId", + "environment": "environment", + "type": "shared", + "secretPath": "/" + }' + ``` + + + + + Name of secret to update + + + The ID of the workspace + + + The environment slug + + + Path to secret in workspace. + + + The type of the secret. Valid options are “shared” or “personal” + + + \ No newline at end of file diff --git a/docs/api-reference/overview/examples/e2ee-enabled.mdx b/docs/api-reference/overview/examples/e2ee-enabled.mdx new file mode 100644 index 000000000..0cbeaabcf --- /dev/null +++ b/docs/api-reference/overview/examples/e2ee-enabled.mdx @@ -0,0 +1,858 @@ +--- +title: "E2EE Enabled" +--- + +Using Infisical's API to read/write secrets with E2EE enabled allows you to create, update, and retrieve secrets +but requires you to perform client-side encryption/decryption operations. For this reason, we recommend using one of the available +SDKs instead. + + + + + + Retrieve all secrets for an Infisical project and environment. +```js +const crypto = require('crypto'); +const axios = require('axios'); + +const BASE_URL = 'https://app.infisical.com'; +const ALGORITHM = 'aes-256-gcm'; + +const decrypt = ({ ciphertext, iv, tag, secret}) => { + const decipher = crypto.createDecipheriv( + ALGORITHM, + secret, + Buffer.from(iv, 'base64') + ); + decipher.setAuthTag(Buffer.from(tag, 'base64')); + + let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); + cleartext += decipher.final('utf8'); + + return cleartext; +} + +const getSecrets = async () => { + const serviceToken = 'your_service_token'; + const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); + + // 1. Get your Infisical Token data + const { data: serviceTokenData } = await axios.get( + `${BASE_URL}/api/v2/service-token`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + // 2. Get secrets for your project and environment + const { data } = await axios.get( + `${BASE_URL}/api/v3/secrets?${new URLSearchParams({ + environment: serviceTokenData.environment, + workspaceId: serviceTokenData.workspace + })}`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + const encryptedSecrets = data.secrets; + + // 3. Decrypt the (encrypted) project key with the key from your Infisical Token + const projectKey = decrypt({ + ciphertext: serviceTokenData.encryptedKey, + iv: serviceTokenData.iv, + tag: serviceTokenData.tag, + secret: serviceTokenSecret + }); + + // 4. Decrypt the (encrypted) secrets + const secrets = encryptedSecrets.map((secret) => { + const secretKey = decrypt({ + ciphertext: secret.secretKeyCiphertext, + iv: secret.secretKeyIV, + tag: secret.secretKeyTag, + secret: projectKey + }); + + const secretValue = decrypt({ + ciphertext: secret.secretValueCiphertext, + iv: secret.secretValueIV, + tag: secret.secretValueTag, + secret: projectKey + }); + + return ({ + secretKey, + secretValue + }); + }); + + console.log('secrets: ', secrets); +} + +getSecrets(); + +``` + + + +```Python +import requests +import base64 +from Cryptodome.Cipher import AES + + +BASE_URL = "http://app.infisical.com" + + +def decrypt(ciphertext, iv, tag, secret): + secret = bytes(secret, "utf-8") + iv = base64.standard_b64decode(iv) + tag = base64.standard_b64decode(tag) + ciphertext = base64.standard_b64decode(ciphertext) + + cipher = AES.new(secret, AES.MODE_GCM, iv) + cipher.update(tag) + cleartext = cipher.decrypt(ciphertext).decode("utf-8") + return cleartext + + +def get_secrets(): + service_token = "your_service_token" + service_token_secret = service_token[service_token.rindex(".") + 1 :] + + # 1. Get your Infisical Token data + service_token_data = requests.get( + f"{BASE_URL}/api/v2/service-token", + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + # 2. Get secrets for your project and environment + data = requests.get( + f"{BASE_URL}/api/v3/secrets", + params={ + "environment": service_token_data["environment"], + "workspaceId": service_token_data["workspace"], + }, + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + encrypted_secrets = data["secrets"] + + # 3. Decrypt the (encrypted) project key with the key from your Infisical Token + project_key = decrypt( + ciphertext=service_token_data["encryptedKey"], + iv=service_token_data["iv"], + tag=service_token_data["tag"], + secret=service_token_secret, + ) + + # 4. Decrypt the (encrypted) secrets + secrets = [] + for secret in encrypted_secrets: + secret_key = decrypt( + ciphertext=secret["secretKeyCiphertext"], + iv=secret["secretKeyIV"], + tag=secret["secretKeyTag"], + secret=project_key, + ) + + secret_value = decrypt( + ciphertext=secret["secretValueCiphertext"], + iv=secret["secretValueIV"], + tag=secret["secretValueTag"], + secret=project_key, + ) + + secrets.append( + { + "secret_key": secret_key, + "secret_value": secret_value, + } + ) + + print("secrets:", secrets) + + +get_secrets() + +``` + + + + + + +Create a secret in Infisical. +```js +const crypto = require('crypto'); +const axios = require('axios'); +const nacl = require('tweetnacl'); + +const BASE_URL = 'https://app.infisical.com'; +const ALGORITHM = 'aes-256-gcm'; +const BLOCK_SIZE_BYTES = 16; + +const encrypt = ({ text, secret }) => { + const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); + const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); + + let ciphertext = cipher.update(text, 'utf8', 'base64'); + ciphertext += cipher.final('base64'); + return { + ciphertext, + iv: iv.toString('base64'), + tag: cipher.getAuthTag().toString('base64') + }; +} + +const decrypt = ({ ciphertext, iv, tag, secret}) => { + const decipher = crypto.createDecipheriv( + ALGORITHM, + secret, + Buffer.from(iv, 'base64') + ); + decipher.setAuthTag(Buffer.from(tag, 'base64')); + + let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); + cleartext += decipher.final('utf8'); + + return cleartext; +} + +const createSecrets = async () => { + const serviceToken = ''; + const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); + + const secretType = 'shared'; // 'shared' or 'personal' + const secretKey = 'some_key'; + const secretValue = 'some_value'; + const secretComment = 'some_comment'; + + // 1. Get your Infisical Token data + const { data: serviceTokenData } = await axios.get( + `${BASE_URL}/api/v2/service-token`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + // 2. Decrypt the (encrypted) project key with the key from your Infisical Token + const projectKey = decrypt({ + ciphertext: serviceTokenData.encryptedKey, + iv: serviceTokenData.iv, + tag: serviceTokenData.tag, + secret: serviceTokenSecret + }); + + // 3. Encrypt your secret with the project key + const { + ciphertext: secretKeyCiphertext, + iv: secretKeyIV, + tag: secretKeyTag + } = encrypt({ + text: secretKey, + secret: projectKey + }); + + const { + ciphertext: secretValueCiphertext, + iv: secretValueIV, + tag: secretValueTag + } = encrypt({ + text: secretValue, + secret: projectKey + }); + + const { + ciphertext: secretCommentCiphertext, + iv: secretCommentIV, + tag: secretCommentTag + } = encrypt({ + text: secretComment, + secret: projectKey + }); + + // 4. Send (encrypted) secret to Infisical + await axios.post( + `${BASE_URL}/api/v3/secrets/${secretKey}`, + { + workspaceId: serviceTokenData.workspace, + environment: serviceTokenData.environment, + type: secretType, + secretKeyCiphertext, + secretKeyIV, + secretKeyTag, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag + }, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); +} + +createSecrets(); +``` + + + +```Python +import base64 +import requests +from Cryptodome.Cipher import AES +from Cryptodome.Random import get_random_bytes + + +BASE_URL = "https://app.infisical.com" +BLOCK_SIZE_BYTES = 16 + + +def encrypt(text, secret): + iv = get_random_bytes(BLOCK_SIZE_BYTES) + secret = bytes(secret, "utf-8") + cipher = AES.new(secret, AES.MODE_GCM, iv) + ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) + return { + "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), + "tag": base64.standard_b64encode(tag).decode("utf-8"), + "iv": base64.standard_b64encode(iv).decode("utf-8"), + } + + +def decrypt(ciphertext, iv, tag, secret): + secret = bytes(secret, "utf-8") + iv = base64.standard_b64decode(iv) + tag = base64.standard_b64decode(tag) + ciphertext = base64.standard_b64decode(ciphertext) + + cipher = AES.new(secret, AES.MODE_GCM, iv) + cipher.update(tag) + cleartext = cipher.decrypt(ciphertext).decode("utf-8") + return cleartext + + +def create_secrets(): + service_token = "your_service_token" + service_token_secret = service_token[service_token.rindex(".") + 1 :] + + secret_type = "shared" # "shared or "personal" + secret_key = "some_key" + secret_value = "some_value" + secret_comment = "some_comment" + + # 1. Get your Infisical Token data + service_token_data = requests.get( + f"{BASE_URL}/api/v2/service-token", + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + # 2. Decrypt the (encrypted) project key with the key from your Infisical Token + project_key = decrypt( + ciphertext=service_token_data["encryptedKey"], + iv=service_token_data["iv"], + tag=service_token_data["tag"], + secret=service_token_secret, + ) + + # 3. Encrypt your secret with the project key + encrypted_key_data = encrypt(text=secret_key, secret=project_key) + encrypted_value_data = encrypt(text=secret_value, secret=project_key) + encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) + + # 4. Send (encrypted) secret to Infisical + requests.post( + f"{BASE_URL}/api/v3/secrets/{secret_key}", + json={ + "workspaceId": service_token_data["workspace"], + "environment": service_token_data["environment"], + "type": secret_type, + "secretKeyCiphertext": encrypted_key_data["ciphertext"], + "secretKeyIV": encrypted_key_data["iv"], + "secretKeyTag": encrypted_key_data["tag"], + "secretValueCiphertext": encrypted_value_data["ciphertext"], + "secretValueIV": encrypted_value_data["iv"], + "secretValueTag": encrypted_value_data["tag"], + "secretCommentCiphertext": encrypted_comment_data["ciphertext"], + "secretCommentIV": encrypted_comment_data["iv"], + "secretCommentTag": encrypted_comment_data["tag"] + }, + headers={"Authorization": f"Bearer {service_token}"}, + ) + + +create_secrets() + +``` + + + + + + + Retrieve a secret from Infisical. +```js +const crypto = require('crypto'); +const axios = require('axios'); + +const BASE_URL = 'https://app.infisical.com'; +const ALGORITHM = 'aes-256-gcm'; + +const decrypt = ({ ciphertext, iv, tag, secret}) => { + const decipher = crypto.createDecipheriv( + ALGORITHM, + secret, + Buffer.from(iv, 'base64') + ); + decipher.setAuthTag(Buffer.from(tag, 'base64')); + + let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); + cleartext += decipher.final('utf8'); + + return cleartext; +} + +const getSecret = async () => { + const serviceToken = 'your_service_token'; + const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); + + const secretType = 'shared' // 'shared' or 'personal' + const secretKey = 'some_key'; + + // 1. Get your Infisical Token data + const { data: serviceTokenData } = await axios.get( + `${BASE_URL}/api/v2/service-token`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + // 2. Get the secret from your project and environment + const { data } = await axios.get( + `${BASE_URL}/api/v3/secrets/${secretKey}?${new URLSearchParams({ + environment: serviceTokenData.environment, + workspaceId: serviceTokenData.workspace, + type: secretType // optional, defaults to 'shared' + })}`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + const encryptedSecret = data.secret; + + // 3. Decrypt the (encrypted) project key with the key from your Infisical Token + const projectKey = decrypt({ + ciphertext: serviceTokenData.encryptedKey, + iv: serviceTokenData.iv, + tag: serviceTokenData.tag, + secret: serviceTokenSecret + }); + + // 4. Decrypt the (encrypted) secret value + + const secretValue = decrypt({ + ciphertext: encryptedSecret.secretValueCiphertext, + iv: encryptedSecret.secretValueIV, + tag: encryptedSecret.secretValueTag, + secret: projectKey + }); + + console.log('secret: ', ({ + secretKey, + secretValue + })); +} + +getSecret(); + +``` + + + +```Python +import requests +import base64 +from Cryptodome.Cipher import AES + + +BASE_URL = "http://app.infisical.com" + + +def decrypt(ciphertext, iv, tag, secret): + secret = bytes(secret, "utf-8") + iv = base64.standard_b64decode(iv) + tag = base64.standard_b64decode(tag) + ciphertext = base64.standard_b64decode(ciphertext) + + cipher = AES.new(secret, AES.MODE_GCM, iv) + cipher.update(tag) + cleartext = cipher.decrypt(ciphertext).decode("utf-8") + return cleartext + + +def get_secret(): + service_token = "your_service_token" + service_token_secret = service_token[service_token.rindex(".") + 1 :] + + secret_type = "shared" # "shared" or "personal" + secret_key = "some_key" + + # 1. Get your Infisical Token data + service_token_data = requests.get( + f"{BASE_URL}/api/v2/service-token", + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + # 2. Get secret from your project and environment + data = requests.get( + f"{BASE_URL}/api/v3/secrets/{secret_key}", + params={ + "environment": service_token_data["environment"], + "workspaceId": service_token_data["workspace"], + "type": secret_type # optional, defaults to "shared" + }, + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + encrypted_secret = data["secret"] + + # 3. Decrypt the (encrypted) project key with the key from your Infisical Token + project_key = decrypt( + ciphertext=service_token_data["encryptedKey"], + iv=service_token_data["iv"], + tag=service_token_data["tag"], + secret=service_token_secret, + ) + + # 4. Decrypt the (encrypted) secret value + secret_value = decrypt( + ciphertext=encrypted_secret["secretValueCiphertext"], + iv=encrypted_secret["secretValueIV"], + tag=encrypted_secret["secretValueTag"], + secret=project_key, + ) + + print("secret: ", { + "secret_key": secret_key, + "secret_value": secret_value + }) + + +get_secret() + +``` + + + + + + +Update an existing secret in Infisical. +```js +const crypto = require('crypto'); +const axios = require('axios'); + +const BASE_URL = 'https://app.infisical.com'; +const ALGORITHM = 'aes-256-gcm'; +const BLOCK_SIZE_BYTES = 16; + +const encrypt = ({ text, secret }) => { + const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); + const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); + + let ciphertext = cipher.update(text, 'utf8', 'base64'); + ciphertext += cipher.final('base64'); + return { + ciphertext, + iv: iv.toString('base64'), + tag: cipher.getAuthTag().toString('base64') + }; +} + +const decrypt = ({ ciphertext, iv, tag, secret}) => { + const decipher = crypto.createDecipheriv( + ALGORITHM, + secret, + Buffer.from(iv, 'base64') + ); + decipher.setAuthTag(Buffer.from(tag, 'base64')); + + let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); + cleartext += decipher.final('utf8'); + + return cleartext; +} + +const updateSecrets = async () => { + const serviceToken = 'your_service_token'; + const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); + + const secretType = 'shared' // 'shared' or 'personal' + const secretKey = 'some_key'; + const secretValue = 'updated_value'; + const secretComment = 'updated_comment'; + + // 1. Get your Infisical Token data + const { data: serviceTokenData } = await axios.get( + `${BASE_URL}/api/v2/service-token`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + // 2. Decrypt the (encrypted) project key with the key from your Infisical Token + const projectKey = decrypt({ + ciphertext: serviceTokenData.encryptedKey, + iv: serviceTokenData.iv, + tag: serviceTokenData.tag, + secret: serviceTokenSecret + }); + + // 3. Encrypt your updated secret with the project key + const { + ciphertext: secretKeyCiphertext, + iv: secretKeyIV, + tag: secretKeyTag + } = encrypt({ + text: secretKey, + secret: projectKey + }); + + const { + ciphertext: secretValueCiphertext, + iv: secretValueIV, + tag: secretValueTag + } = encrypt({ + text: secretValue, + secret: projectKey + }); + + const { + ciphertext: secretCommentCiphertext, + iv: secretCommentIV, + tag: secretCommentTag + } = encrypt({ + text: secretComment, + secret: projectKey + }); + + // 4. Send (encrypted) updated secret to Infisical + await axios.patch( + `${BASE_URL}/api/v3/secrets/${secretKey}`, + { + workspaceId: serviceTokenData.workspace, + environment: serviceTokenData.environment, + type: secretType, + secretValueCiphertext, + secretValueIV, + secretValueTag, + secretCommentCiphertext, + secretCommentIV, + secretCommentTag + }, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); +} + +updateSecrets(); +``` + + + +```Python +import base64 +import requests +from Cryptodome.Cipher import AES +from Cryptodome.Random import get_random_bytes + + +BASE_URL = "https://app.infisical.com" +BLOCK_SIZE_BYTES = 16 + + +def encrypt(text, secret): + iv = get_random_bytes(BLOCK_SIZE_BYTES) + secret = bytes(secret, "utf-8") + cipher = AES.new(secret, AES.MODE_GCM, iv) + ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) + return { + "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), + "tag": base64.standard_b64encode(tag).decode("utf-8"), + "iv": base64.standard_b64encode(iv).decode("utf-8"), + } + + +def decrypt(ciphertext, iv, tag, secret): + secret = bytes(secret, "utf-8") + iv = base64.standard_b64decode(iv) + tag = base64.standard_b64decode(tag) + ciphertext = base64.standard_b64decode(ciphertext) + + cipher = AES.new(secret, AES.MODE_GCM, iv) + cipher.update(tag) + cleartext = cipher.decrypt(ciphertext).decode("utf-8") + return cleartext + + +def update_secret(): + service_token = "your_service_token" + service_token_secret = service_token[service_token.rindex(".") + 1 :] + + secret_type = "shared" # "shared" or "personal" + secret_key = "some_key" + secret_value = "updated_value" + secret_comment = "updated_comment" + + # 1. Get your Infisical Token data + service_token_data = requests.get( + f"{BASE_URL}/api/v2/service-token", + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + # 2. Decrypt the (encrypted) project key with the key from your Infisical Token + project_key = decrypt( + ciphertext=service_token_data["encryptedKey"], + iv=service_token_data["iv"], + tag=service_token_data["tag"], + secret=service_token_secret, + ) + + # 3. Encrypt your updated secret with the project key + encrypted_key_data = encrypt(text=secret_key, secret=project_key) + encrypted_value_data = encrypt(text=secret_value, secret=project_key) + encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) + + # 4. Send (encrypted) updated secret to Infisical + requests.patch( + f"{BASE_URL}/api/v3/secrets/{secret_key}", + json={ + "workspaceId": service_token_data["workspace"], + "environment": service_token_data["environment"], + "type": secret_type, + "secretKeyCiphertext": encrypted_key_data["ciphertext"], + "secretKeyIV": encrypted_key_data["iv"], + "secretKeyTag": encrypted_key_data["tag"], + "secretValueCiphertext": encrypted_value_data["ciphertext"], + "secretValueIV": encrypted_value_data["iv"], + "secretValueTag": encrypted_value_data["tag"], + "secretCommentCiphertext": encrypted_comment_data["ciphertext"], + "secretCommentIV": encrypted_comment_data["iv"], + "secretCommentTag": encrypted_comment_data["tag"] + }, + headers={"Authorization": f"Bearer {service_token}"}, + ) + + +update_secret() + +``` + + + + + + + Delete a secret in Infisical. +```js +const axios = require('axios'); +const BASE_URL = 'https://app.infisical.com'; + +const deleteSecrets = async () => { + const serviceToken = 'your_service_token'; + const secretType = 'shared' // 'shared' or 'personal' + const secretKey = 'some_key' + + // 1. Get your Infisical Token data + const { data: serviceTokenData } = await axios.get( + `${BASE_URL}/api/v2/service-token`, + { + headers: { + Authorization: `Bearer ${serviceToken}` + } + } + ); + + // 2. Delete secret from Infisical + await axios.delete( + `${BASE_URL}/api/v3/secrets/${secretKey}`, + { + workspaceId: serviceTokenData.workspace, + environment: serviceTokenData.environment, + type: secretType + }, + { + headers: { + Authorization: `Bearer ${serviceToken}` + }, + } + ); +}; + +deleteSecrets(); +``` + + + +```Python +import requests + +BASE_URL = "https://app.infisical.com" + + +def delete_secrets(): + service_token = "" + secret_type = "shared" # "shared" or "personal" + secret_key = "some_key" + + # 1. Get your Infisical Token data + service_token_data = requests.get( + f"{BASE_URL}/api/v2/service-token", + headers={"Authorization": f"Bearer {service_token}"}, + ).json() + + # 2. Delete secret from Infisical + requests.delete( + f"{BASE_URL}/api/v2/secrets/{secret_key}", + json={ + "workspaceId": service_token_data["workspace"], + "environment": service_token_data["environment"], + "type": secret_type + }, + headers={"Authorization": f"Bearer {service_token}"}, + ) + + +delete_secrets() + +``` + + + + If using an `API_KEY` to authenticate with the Infisical API, then you should include it in the `X_API_KEY` header. + + + + \ No newline at end of file diff --git a/docs/api-reference/overview/examples/note.mdx b/docs/api-reference/overview/examples/note.mdx new file mode 100644 index 000000000..8491dfaae --- /dev/null +++ b/docs/api-reference/overview/examples/note.mdx @@ -0,0 +1,54 @@ +--- +title: "Note on E2EE" +--- + +Each project in Infisical can have **End-to-End Encryption (E2EE)** enabled or disabled. + +By default, all projects have **E2EE** enabled which means the server is not able to decrypt any values because all secret encryption/decryption operations occur on the client-side; this can be (optionally) disabled. However, this has limitations around functionality and ease-of-use: + +- You cannot make HTTP calls to Infisical to read/write secrets in plaintext. +- You cannot leverage non-E2EE features like native integrations and in-platform automations like dynamic secrets and secret rotation. + + + + Example read/write secrets without client-side encryption/decryption + + + Example read/write secrets with client-side encryption/decryption + + + +## FAQ + + + + We recommend starting with having **E2EE** enabled and disabling it if: + + - You're self-hosting Infisical, so having your instance of Infisical be able to read your secrets isn't an issue. + - You want an easier way to read/write secrets with Infisical. + - You need more power out of non-E2EE features such as secret rotation, dynamic secrets, etc. + + + + You can enable/disable E2EE for your project in Infisical in the Project Settings. + + + It is secure and in fact how most vendors in our industry are able to offer features like secret rotation. In this mode, secrets are encrypted at rest by + a series of keys, secured ultimately by a top-level `ROOT_ENCRYPTION_KEY` located on the server. + + If you're concerned about Infisical Cloud's ability to read your secrets, then you may wish to + use it with **E2EE** enabled or self-host Infisical on your own infrastructure and disable E2EE there. + + As an organization, we do not read any customer secrets without explicit permission; access to the `ROOT_ENCRYPTION_KEY` is restricted to one individual in the organization. + + \ No newline at end of file diff --git a/docs/api-reference/overview/examples/retrieve-secrets.mdx b/docs/api-reference/overview/examples/retrieve-secrets.mdx deleted file mode 100644 index 794f76d7a..000000000 --- a/docs/api-reference/overview/examples/retrieve-secrets.mdx +++ /dev/null @@ -1,201 +0,0 @@ ---- -title: "Retrieve secrets" ---- - -In this example, we demonstrate how to retrieve secrets from a project and environment using an Infisical Token. - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com). -- Create an [Infisical Token](../../../getting-started/dashboard/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. [Get secrets for your project and environment](/api-reference/endpoints/secrets/read). -3. Decrypt the (encrypted) project key with the key from your Infisical Token. -4. Decrypt the (encrypted) secrets - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const getSecrets = async () => { - const serviceToken = 'your_service_token'; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Get secrets for your project and environment - const { data } = await axios.get( - `${BASE_URL}/api/v2/secrets?${new URLSearchParams({ - environment: serviceTokenData.environment, - workspaceId: serviceTokenData.workspace - })}`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - const encryptedSecrets = data.secrets; - - // 3. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 4. Decrypt the (encrypted) secrets - const secrets = encryptedSecrets.map((secret) => { - const secretKey = decrypt({ - ciphertext: secret.secretKeyCiphertext, - iv: secret.secretKeyIV, - tag: secret.secretKeyTag, - secret: projectKey - }); - - const secretValue = decrypt({ - ciphertext: secret.secretValueCiphertext, - iv: secret.secretValueIV, - tag: secret.secretValueTag, - secret: projectKey - }); - - return ({ - secretKey, - secretValue - }); - }); - - console.log('secrets: ', secrets); -} - -getSecrets(); - -``` - - - -```Python -import requests -import base64 -from Cryptodome.Cipher import AES - - -BASE_URL = "http://app.infisical.com" - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def get_secrets(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Get secrets for your project and environment - data = requests.get( - f"{BASE_URL}/api/v2/secrets", - params={ - "environment": service_token_data["environment"], - "workspaceId": service_token_data["workspace"], - }, - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - encrypted_secrets = data["secrets"] - - # 3. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 4. Decrypt the (encrypted) secrets - secrets = [] - for secret in encrypted_secrets: - secret_key = decrypt( - ciphertext=secret["secretKeyCiphertext"], - iv=secret["secretKeyIV"], - tag=secret["secretKeyTag"], - secret=project_key, - ) - - secret_value = decrypt( - ciphertext=secret["secretValueCiphertext"], - iv=secret["secretValueIV"], - tag=secret["secretValueTag"], - secret=project_key, - ) - - secrets.append( - { - "secret_key": secret_key, - "secret_value": secret_value, - } - ) - - print("secrets:", secrets) - - -get_secrets() - -``` - - - - - This example uses [TweetNaCl.js](https://tweetnacl.js.org/#/), a port of - TweetNacl/Nacl, to perform asymmeric decryption of the project key but there - are ports of NaCl available in every major language. - \ No newline at end of file diff --git a/docs/api-reference/overview/examples/update-secrets.mdx b/docs/api-reference/overview/examples/update-secrets.mdx deleted file mode 100644 index 13bc4ee3e..000000000 --- a/docs/api-reference/overview/examples/update-secrets.mdx +++ /dev/null @@ -1,244 +0,0 @@ ---- -title: "Update secrets" ---- - -In this example, we demonstrate how to update secrets using an Infisical Token. - -Prerequisites: - -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- Create an [Infisical Token](../../../getting-started/dashboard/token) for your project and environment. -- Grasp a basic understanding of the system and its underlying cryptography [here](/api-reference/overview/introduction). - -## Flow - -1. [Get your Infisical Token data](/api-reference/endpoints/service-tokens/get) including a (encrypted) project key. -2. Decrypt the (encrypted) project key with the key from your Infisical Token. -3. Encrypt your updated secret(s) with the project key -4. [Send (encrypted) updated secret(s) to Infical](/api-reference/endpoints/secrets/update) - -## Example - - - -```js -const crypto = require('crypto'); -const axios = require('axios'); - -const BASE_URL = 'https://app.infisical.com'; -const ALGORITHM = 'aes-256-gcm'; -const BLOCK_SIZE_BYTES = 16; - -const encrypt = ({ text, secret }) => { - const iv = crypto.randomBytes(BLOCK_SIZE_BYTES); - const cipher = crypto.createCipheriv(ALGORITHM, secret, iv); - - let ciphertext = cipher.update(text, 'utf8', 'base64'); - ciphertext += cipher.final('base64'); - return { - ciphertext, - iv: iv.toString('base64'), - tag: cipher.getAuthTag().toString('base64') - }; -} - -const decrypt = ({ ciphertext, iv, tag, secret}) => { - const decipher = crypto.createDecipheriv( - ALGORITHM, - secret, - Buffer.from(iv, 'base64') - ); - decipher.setAuthTag(Buffer.from(tag, 'base64')); - - let cleartext = decipher.update(ciphertext, 'base64', 'utf8'); - cleartext += decipher.final('utf8'); - - return cleartext; -} - -const updateSecrets = async () => { - const serviceToken = 'your_service_token'; - const serviceTokenSecret = serviceToken.substring(serviceToken.lastIndexOf('.') + 1); - - const secretId = 'id_of_secret_to_update'; - const secretKey = 'some_key'; - const secretValue = 'updated_value'; - const secretComment = 'updated_comment'; - - // 1. Get your Infisical Token data - const { data: serviceTokenData } = await axios.get( - `${BASE_URL}/api/v2/service-token`, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); - - // 2. Decrypt the (encrypted) project key with the key from your Infisical Token - const projectKey = decrypt({ - ciphertext: serviceTokenData.encryptedKey, - iv: serviceTokenData.iv, - tag: serviceTokenData.tag, - secret: serviceTokenSecret - }); - - // 3. Encrypt your updated secret(s) with the project key - const { - ciphertext: secretKeyCiphertext, - iv: secretKeyIV, - tag: secretKeyTag - } = encrypt({ - text: secretKey, - secret: projectKey - }); - - const { - ciphertext: secretValueCiphertext, - iv: secretValueIV, - tag: secretValueTag - } = encrypt({ - text: secretValue, - secret: projectKey - }); - - const { - ciphertext: secretCommentCiphertext, - iv: secretCommentIV, - tag: secretCommentTag - } = encrypt({ - text: secretComment, - secret: projectKey - }); - - const secret = { - id: secretId, - workspace: serviceTokenData.workspace, - environment: serviceTokenData.environment, - secretKeyCiphertext, - secretKeyIV, - secretKeyTag, - secretValueCiphertext, - secretValueIV, - secretValueTag, - secretCommentCiphertext, - secretCommentIV, - secretCommentTag - } - - // 4. Send (encrypted) updated secret(s) to Infisical - await axios.patch( - `${BASE_URL}/api/v2/secrets`, - { - secrets: [secret] - }, - { - headers: { - Authorization: `Bearer ${serviceToken}` - } - } - ); -} - -updateSecrets(); -``` - - - -```Python -import base64 -import requests -from Cryptodome.Cipher import AES -from Cryptodome.Random import get_random_bytes - - -BASE_URL = "https://app.infisical.com" -BLOCK_SIZE_BYTES = 16 - - -def encrypt(text, secret): - iv = get_random_bytes(BLOCK_SIZE_BYTES) - secret = bytes(secret, "utf-8") - cipher = AES.new(secret, AES.MODE_GCM, iv) - ciphertext, tag = cipher.encrypt_and_digest(text.encode("utf-8")) - return { - "ciphertext": base64.standard_b64encode(ciphertext).decode("utf-8"), - "tag": base64.standard_b64encode(tag).decode("utf-8"), - "iv": base64.standard_b64encode(iv).decode("utf-8"), - } - - -def decrypt(ciphertext, iv, tag, secret): - secret = bytes(secret, "utf-8") - iv = base64.standard_b64decode(iv) - tag = base64.standard_b64decode(tag) - ciphertext = base64.standard_b64decode(ciphertext) - - cipher = AES.new(secret, AES.MODE_GCM, iv) - cipher.update(tag) - cleartext = cipher.decrypt(ciphertext).decode("utf-8") - return cleartext - - -def update_secret(): - service_token = "your_service_token" - service_token_secret = service_token[service_token.rindex(".") + 1 :] - - secret_id = "id_of_secret_to_update" - secret_key = "some_key" - secret_value = "updated_value" - secret_comment = "updated_comment" - - # 1. Get your Infisical Token data - service_token_data = requests.get( - f"{BASE_URL}/api/v2/service-token", - headers={"Authorization": f"Bearer {service_token}"}, - ).json() - - # 2. Decrypt the (encrypted) project key with the key from your Infisical Token - project_key = decrypt( - ciphertext=service_token_data["encryptedKey"], - iv=service_token_data["iv"], - tag=service_token_data["tag"], - secret=service_token_secret, - ) - - # 3. Encrypt your updated secret(s) with the project key - encrypted_key_data = encrypt(text=secret_key, secret=project_key) - encrypted_value_data = encrypt(text=secret_value, secret=project_key) - encrypted_comment_data = encrypt(text=secret_comment, secret=project_key) - - secret = { - "id": secret_id, - "workspace": service_token_data["workspace"], - "environment": service_token_data["environment"], - "secretKeyCiphertext": encrypted_key_data["ciphertext"], - "secretKeyIV": encrypted_key_data["iv"], - "secretKeyTag": encrypted_key_data["tag"], - "secretValueCiphertext": encrypted_value_data["ciphertext"], - "secretValueIV": encrypted_value_data["iv"], - "secretValueTag": encrypted_value_data["tag"], - "secretCommentCiphertext": encrypted_comment_data["ciphertext"], - "secretCommentIV": encrypted_comment_data["iv"], - "secretCommentTag": encrypted_comment_data["tag"], - } - - # 4. Send (encrypted) updated secret(s) to Infisical - requests.patch( - f"{BASE_URL}/api/v2/secrets", - json={"secrets": [secret]}, - headers={"Authorization": f"Bearer {service_token}"}, - ) - - -update_secret() - -``` - - - - - This example uses [TweetNaCl.js](https://tweetnacl.js.org/#/), a port of - TweetNacl/Nacl, to perform asymmeric decryption of the project key but there - are ports of NaCl available in every major language. - \ No newline at end of file diff --git a/docs/api-reference/overview/introduction.mdx b/docs/api-reference/overview/introduction.mdx index 3d748314b..546e0b9a2 100644 --- a/docs/api-reference/overview/introduction.mdx +++ b/docs/api-reference/overview/introduction.mdx @@ -2,27 +2,12 @@ title: "Introduction" --- -Infisical's REST API provides users an alternative way to programmatically access and manage +Infisical's Public (REST) API provides users an alternative way to programmatically access and manage secrets via HTTPS requests. This can be useful for automating tasks, such as rotating credentials, or for integrating secret management into a larger system. -With the REST API, users can create, read, update, and delete secrets, as well as manage access control, query audit logs, and more. +With the Public API, users can create, read, update, and delete secrets, as well as manage access control, query audit logs, and more. -## Concepts - -Using Infisical's API to manage secrets requires a basic understanding of the system and its underlying cryptography detailed [here](/security/overview). - -- Each user has a public/private key pair that is stored with the platform; private keys are encrypted locally by protected keys that are encrypted by keys derived from Argon2id applied to the user's password before being sent off to the server during the account signup process. -- Each (encrypted) secret belongs to a project and environment. -- Each project has an (encrypted) project key used to encrypt the secrets within that project; Infisical stores copies of the project key, for each member of that project, encrypted under each member's public key. -- Secrets are encrypted symmetrically by your copy of the project key belonging to the project containing. -- Infisical Tokens contain a symmetric key that can be used to decrypt a copy of a project key from the [call to get the Infisical Token data](/api-reference/endpoints/service-tokens/get). -- Infisical uses AES256-GCM and [TweetNaCl.js](https://tweetnacl.js.org/#/) for symmetric and asymmetric encryption/decryption operations. - - - Infisical's system requires that secrets be encrypted/decrypted on the - client-side to maintain E2EE. We strongly recommend you read up on the system - prior to using the Infisical API. The (opt-in) ability to retrieve secrets - back in decrypted format if you choose to share secrets with Infisical is on - our roadmap. - + + In April 2023, we added the capability for users to query for secrets by name to improve the user experience of Infisical. If your project was created prior to April 2023, please read and follow the section on [blind indices](./blind-indices) and how to enable them for better usage of Infisical. + \ No newline at end of file diff --git a/docs/changelog/overview.mdx b/docs/changelog/overview.mdx new file mode 100644 index 000000000..7acab93c6 --- /dev/null +++ b/docs/changelog/overview.mdx @@ -0,0 +1,110 @@ +--- +title: "Changelog" +--- + +The changelog below reflects new product developments and updates on a monthly basis; it will be updated later this quarter to include issues-addressed on a weekly basis. + +## May 2023 + +- Released secret scanning capability for the CLI. +- Released customer / license service to manage customer billing information, cloud plans, and self-hosted enterprise licenses; all instances of Infisicals now fetch/relay information from this service. +- Completed penetration test. +- Released new landing page. +- Started SOC 2 (Type II) compliance certification preparation. + +More coming soon. + +## April 2023 + +- Upgraded secret-handling to include blind-indexing (can be thought of as a fingerprint). +- Added Node SDK support for working with individual secrets. +- Released preliminary Python SDK. +- Released service accounts, a client type capable of accessing multiple projects. +- Added native Supabase integration. +- Added native Railway integration. +- Improved dashboard speed / performance. +- Released the Secrets Overview page for users to view and identify missing environment secrets within one dashboard. +- Updated documentation to include quickstarts and guides; also updated `README.md`. + +## March 2023 + +- Added support for global configs to the Kubernetes operator. +- Added support for self-hosted deployments to operate without any attached email service / SMTP configuration. +- Added native Azure Key Vault integration. +- Released one-click AWS EC2 deployment method. +- Released preliminary Node SDK. + +## Feb 2023 + +- Upgraded private key encryption/decryption mechanism to use Argon2id and 256-bit protected keys. +- Added preliminary emai-based 2FA capability +- Added suspicious login alerting if user logs in via new device or IP address. +- Added documentation for PM2 integration. +- Added secret backups support for the CLI; it now fetches and caches secrets locally to be used in the event of future failed fetch. +- Added support for comparing secret values across environments on each secret. +- Added native AWS Parameter Store integration. +- Added native AWS Secret Manager integration. +- Added native GitLab integration. +- Added native CircleCI integration. +- Added native Travis CI integration. +- Added secret tagging capability for enhanced organizational structure/grouping. +- Released new dashboard design allowing more actions to be performed within the dashboard itself. +- Added capability to generate `.env.example` file. + +## Jan 2023 + +- Added preliminary audit logging capability covering CRUD secret operations. +- Added secret overriding capability for team members to have their own branch of a secret. +- Added secret versioning capability. +- Added secret snapshot and point-in-time recovery capabilities to track and roll back the full state of a project. +- Added native Vercel integration. +- Added native Netlify integration. +- Added native GitHub Actions integration. +- Added custom environment names. +- Added auto-redeployment capability to the Kubernetes operator. +- (Service Token 2.0) Shortened the length of service tokens +- Added a public-facing API +- Added preliminary access control capability for users to be provisioned read/write access to environments +- Performed various web UI optimizations. + +## Nov 2022 + +- Infisical is open sourced. +- Added Infisical CLI support for Docker and Docker Compose. +- Rewrote the Infisical CLI in Golang to be platform-agnostic. +- Rewrote the documentation. + +## Oct 2022 + +- Added support for organizations; projects now belong to organizations. +- Improved speed / performance of dashboard by 25x. +- Added capability to change account password in settings. +- Added persistence for logging into the organization and project that users left from in their previous session. +- Added password recovery emergency kit with automatic download enforcement upon account creation. +- Added capability to copy-to-clipboard capabilities. +- Released first native integration between Infisical and Heroku; environment variables can now be sent and kept in sync with Heroku. + +## Sep 2022 + +- Added capability to change user roles in projects. +- Added capabilty to delete projects. +- Added Stripe. +- Added default environments (development, staging, production) for new users with example key-pairs. +- Added loading indicators. +- Moved from push/pull mode of secret operation to automatically pulling and injecting secrets into processes upon startup. +- Added drag-and-drop capability for adding new .env files. +- Improved security measures against common attacks (e.g. XSS, clickjacking, etc.). +- Added support for personal secrets (later modified to be secret overrides in Jan 2023). +- Improved account password validation and enforce minimum requirements. +- Added sorting capability to sort keys by name alphabetically in dashboard. +- Added downloading secrets back as `.env` file capability. + +## August 2022 + +- Released first version of the Infisical platform with push/pull capability and end-to-end encryption. +- Improved security handling of authentication tokens by storing refresh tokens in HttpOnly cookies. +- Added hiding key values on client-side. +- Added search bar to dashboard to query for keys on client-side. +- Added capability to rename a project. +- Added user roles for projects. +- Added incident contacts. \ No newline at end of file diff --git a/docs/cli/commands/export.mdx b/docs/cli/commands/export.mdx index 0fb673418..59d15ed2f 100644 --- a/docs/cli/commands/export.mdx +++ b/docs/cli/commands/export.mdx @@ -37,7 +37,7 @@ Export environment variables from the platform into a file format. ### Environment variables - Used to fetch secrets via a [service token](/getting-started/dashboard/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. + Used to fetch secrets via a [service token](/documentation/platform/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. ```bash # Example diff --git a/docs/cli/commands/login.mdx b/docs/cli/commands/login.mdx index 36abaf94e..3028ec110 100644 --- a/docs/cli/commands/login.mdx +++ b/docs/cli/commands/login.mdx @@ -9,4 +9,7 @@ infisical login ## Description The CLI uses authentication to verify your identity. When you enter the correct email and password for your account, a token is generated and saved in your system Keyring to allow you to make future interactions with the CLI. -If you want to change where the login credentials are stored, visit the [vaults command](./vault) \ No newline at end of file + +To change where the login credentials are stored, visit the [vaults command](./vault). + +If you have added multiple users, you can switch between the users by using the [user command](./user). \ No newline at end of file diff --git a/docs/cli/commands/run.mdx b/docs/cli/commands/run.mdx index d801bd9f3..b9995f82d 100644 --- a/docs/cli/commands/run.mdx +++ b/docs/cli/commands/run.mdx @@ -42,7 +42,7 @@ Inject secrets from Infisical into your application process. ### Environment variables - Used to fetch secrets via a [service token](/getting-started/dashboard/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. + Used to fetch secrets via a [service token](/documentation/platform/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. ```bash # Example @@ -72,7 +72,7 @@ Inject secrets from Infisical into your application process. - If you are using a [service token](../../getting-started/dashboard/token) to authenticate, you can pass the token as a flag + If you are using a [service token](/documentation/platform/token) to authenticate, you can pass the token as a flag ```bash # Example diff --git a/docs/cli/commands/scan-git-changes.mdx b/docs/cli/commands/scan-git-changes.mdx new file mode 100644 index 000000000..d2a6c452c --- /dev/null +++ b/docs/cli/commands/scan-git-changes.mdx @@ -0,0 +1,104 @@ +--- +title: "scan git-changes" +description: "Scan for secrets in your uncommitted code" +--- + +```bash +infisical scan git-changes + +# Display the full secret findings +infisical scan git-changes --verbose +``` + +## Description +Scanning for secrets before you commit your changes is great way to prevent leaks. Infisical makes this easy with the sub command `git-changes`. + +The `git-changes` scans for uncommitted changes in a Git repository, and is especially designed for use on developer machines, aligning with the ['shift left'](https://cloud.google.com/architecture/devops/devops-tech-shifting-left-on-security) security approach. +When `git-changes` is run on a Git repository, Infisical parses the output from a `git diff` command. + +To scan changes in commits that have been staged via `git add`, you can add the `--staged` flag to the sub command. This flag is particularly useful when using Infisical CLI as a pre-commit tool. + +### Flags + + **Description** + + detect secrets in a --staged state + + Default value: `false` + + + + **Description** + + git log options + + + + Short hand: `-b` + + **Description** + + path to baseline with issues that can be ignored + + + + Short hand: `-c` + + **Description** + + config file path + + order of precedence: + 1. --config flag + 2. env var INFISICAL_SCAN_CONFIG + 3. (--source/-s)/.infisical-scan.toml + If none of the three options are used, then Infisical will use the default config + + + + **Description** + + exit code when leaks have been encountered (default 1) + + + + **Description** + + files larger than this will be skipped + + + + **Description** + + turn off color for verbose output + + + + **Description** + + redact secrets from logs and stdout + + + + **Description** + + output format (json, csv, sarif) (default "json") + + + + **Description** + + report file + + + + **Description** + + path to source (default ".") + + + + **Description** + + show verbose output from scan + diff --git a/docs/cli/commands/scan-install.mdx b/docs/cli/commands/scan-install.mdx new file mode 100644 index 000000000..a0128ef18 --- /dev/null +++ b/docs/cli/commands/scan-install.mdx @@ -0,0 +1,23 @@ +--- +title: "scan install" +description: "Add various scanning tools seamlessly into your development lifecycle" +--- + +```bash +infisical scan install --pre-commit-hook +``` + +## Description +The command `infisical scan install` is designed to incorporate various scanning tools seamlessly into your development lifecycle. +Initially, we are offering users the ability to install a pre-commit hook. This hook conducts an automatic scan for any exposed secrets in your commits before they are pushed. + +### Flags + + ```bash + infisical scan install --pre-commit-hook + ``` + + **Description** + Installs a git pre-commit hook that triggers Infisical to scan your staged changes for any exposed secrets prior to pushing. + + \ No newline at end of file diff --git a/docs/cli/commands/scan.mdx b/docs/cli/commands/scan.mdx new file mode 100644 index 000000000..3de69dd58 --- /dev/null +++ b/docs/cli/commands/scan.mdx @@ -0,0 +1,126 @@ +--- +title: "scan" +description: "Scan git history, directories, and files for secrets" +--- + +```bash +infisical scan + +# Display the full secret findings +infisical scan --verbose +``` + +## Description +The `infisical scan` command serves to scan repositories, directories, and files. It's compatible with both individual developer machines and Continuous Integration (CI) environments. + +When you run `infisical scan` on a Git repository, Infisical will parses the output of a `git log -p` command. This command generates [patches](https://stackoverflow.com/questions/8279602/what-is-a-patch-in-git-version-control) that Infisical uses to identify secrets in your code. +You can configure the range of commits that `git log` will cover using the `--log-opts` flag. +Any options you can use with `git log -p` are valid for `--log-opts`. + +For instance, to instruct Infisical to scan a specific range of commits, use the following command: `infisical scan --log-opts="--all commitA..commitB"`. For more details, refer to the [Git log documentation](https://git-scm.com/docs/git-log). + +To scan individual files and directories, use the `--no-git` flag. + +### Flags + + **Description** + + git log options + + + + **Description** + + treat git repo as a regular directory and scan those files, --log-opts has no effect on the scan when --no-git is set + + Default value: `false` + + + + Short hand: `-b` + + **Description** + + scan input from stdin, ex: `cat some_file | infisical scan --pipe` + + Default value: `false` + + + + Short hand: `-b` + + **Description** + scan files that are symlinks to other files + + Default value: `false` + + + + Short hand: `-b` + + **Description** + + path to baseline with issues that can be ignored + + + + Short hand: `-c` + + **Description** + + config file path + + order of precedence: + 1. --config flag + 2. env var INFISICAL_SCAN_CONFIG + 3. (--source/-s)/.infisical-scan.toml + If none of the three options are used, then Infisical will use the default config + + + + **Description** + + exit code when leaks have been encountered (default 1) + + + + **Description** + + files larger than this will be skipped + + + + **Description** + + turn off color for verbose output + + + + **Description** + + redact secrets from logs and stdout + + + + **Description** + + output format (json, csv, sarif) (default "json") + + + + **Description** + + report file + + + + **Description** + + path to source (default ".") + + + + **Description** + + show verbose output from scan + diff --git a/docs/cli/commands/secrets.mdx b/docs/cli/commands/secrets.mdx index 55f0dc0dc..3b1ccd3fb 100644 --- a/docs/cli/commands/secrets.mdx +++ b/docs/cli/commands/secrets.mdx @@ -20,7 +20,7 @@ This command enables you to perform CRUD (create, read, update, delete) operatio ### Environment variables - Used to fetch secrets via a [service token](/getting-started/dashboard/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. + Used to fetch secrets via a [service token](/documentation/platform/token) apposed to logged in credentials. Simply, export this variable in the terminal before running this command. ```bash # Example diff --git a/docs/cli/commands/user.mdx b/docs/cli/commands/user.mdx new file mode 100644 index 000000000..38a92bbab --- /dev/null +++ b/docs/cli/commands/user.mdx @@ -0,0 +1,29 @@ +--- +title: "infisical user" +description: "Manage logged in users" +--- + +```bash +infisical user +``` + +## Description +This command allows you to manage the current logged in users on the CLI + +### Sub-commands + + Use this command to switch between profiles that are currently logged into the CLI + + ```bash + infisical user switch + ``` + + + + With this command, you can modify the backend API that is utilized for all requests associated with a specific profile. + For instance, you have the option to point the profile to use either the Infisical Cloud or your own self-hosted Infisical instance. + + ```bash + infisical user update domain + ``` + diff --git a/docs/cli/faq.mdx b/docs/cli/faq.mdx index 80229de01..529ec70ab 100644 --- a/docs/cli/faq.mdx +++ b/docs/cli/faq.mdx @@ -1,6 +1,6 @@ --- title: "FAQ" -description: "Frequently Asked Questions about Infisical" +description: "Frequently Asked Questions about Infisical CLI" --- Frequently asked questions about the CLI can be found on this page. diff --git a/docs/cli/overview.mdx b/docs/cli/overview.mdx index 8934d8e07..32bd06946 100644 --- a/docs/cli/overview.mdx +++ b/docs/cli/overview.mdx @@ -109,15 +109,36 @@ infisical login The CLI is set to connect to Infisical Cloud by default, but if you're running your own instance of Infisical, you can direct the CLI to it using one of the methods provided below. -#### Export environment variable +#### Method 1: Use the updated CLI +Beginning with CLI version V0.4.0, it is now possible to choose between logging in through the Infisical cloud or your own self-hosted instance. Simply execute the `infisical login` command and follow the on-screen instructions. + +#### Method 2: Export environment variable You can point the CLI to the self hosted Infisical instance by exporting the environment variable `INFISICAL_API_URL` in your terminal. -```bash -# Example -export INFISICAL_API_URL="https://your-self-hosted-infisical.com/api" -``` + + + ```bash + # Set backend host + export INFISICAL_API_URL="https://your-self-hosted-infisical.com/api" -#### Set manually on every command + # Remove backend host + unset INFISICAL_API_URL + ``` + + + ```bash + # Set backend host + setx INFISICAL_API_URL "https://your-self-hosted-infisical.com/api" + + # Remove backend host + setx INFISICAL_API_URL "" + + # NOTE: Once set or removed, please restart powershell for the change to take effect + ``` + + + +#### Method 3: Set manually on every command Another option to point the CLI to your self hosted Infisical instance is to set it via a flag on every command you run. ```bash diff --git a/docs/cli/scanning-overview.mdx b/docs/cli/scanning-overview.mdx new file mode 100644 index 000000000..5fb65a54b --- /dev/null +++ b/docs/cli/scanning-overview.mdx @@ -0,0 +1,245 @@ +--- +title: 'Secret scanning' +description: "Scan and prevent secret leaks in your code base" +--- + +Building upon its core functionality of fetching and injecting secrets into your applications, Infisical now takes a significant step forward in bolstering your code security. +We've enhanced our CLI tool to include a powerful scanning feature, capable of identifying more than 140 different types of secret leaks in your codebase. +In addition to scanning for past leaks, this new addition also actively aids in preventing future leaks. + +# Scanning + + + ```bash + infisical scan + + # Display the full secret findings + infisical scan --verbose + ``` + + The `infisical scan` command serves to scan repositories, directories, and files. It's compatible with both individual developer machines and Continuous Integration (CI) environments. + + When you run `infisical scan` on a Git repository, Infisical will parses the output of a `git log -p` command. This command generates [patches](https://stackoverflow.com/questions/8279602/what-is-a-patch-in-git-version-control) that Infisical uses to identify secrets in your code. + You can configure the range of commits that `git log` will cover using the `--log-opts` flag. + Any options you can use with `git log -p` are valid for `--log-opts`. + + For instance, to instruct Infisical to scan a specific range of commits, use the following command: `infisical scan --log-opts="--all commitA..commitB"`. For more details, refer to the [Git log documentation](https://git-scm.com/docs/git-log). + + To scan individual files and directories, use the `--no-git` flag. + + **View [full details for this command](./commands/scan)** + + + ```bash + infisical scan git-changes + + # Display the full secret findings + infisical git-changes --verbose + ``` + + Scanning for secrets before you commit your changes is great way to prevent leaks. Infisical makes this easy with the sub command `git-changes`. + + The `git-changes` scans for uncommitted changes in a Git repository, and is especially designed for use on developer machines, aligning with the ['shift left'](https://cloud.google.com/architecture/devops/devops-tech-shifting-left-on-security) security approach. + When `git-changes` is run on a Git repository, Infisical parses the output from a `git diff` command. + + To scan changes in commits that have been staged via `git add`, you can add the `--staged` flag to the sub command. This flag is particularly useful when using Infisical CLI as a pre-commit tool. + + **View [full details for this command](./commands/scan-git-changes)** + ​ + + `git-changes` command is only for Git repositories; using it on files or directories will result in an error. + + + + +# +# +# Automatically scan changes before you commit + +To lower the risk of committing hardcoded secrets to your code repository, we have designed a custom git pre-commit hook. +This hook scans the changes you're about to commit for any exposed secrets. If any hardcoded secrets are detected, it will block your commit. + +### Install pre-commit hook + +To install this git hook, go into your local git repository and run the following command. + +```bash +infisical scan install --pre-commit-hook +``` + +To disable this hook after installing it, run the command `git config --bool hooks.infisical-scan false` + +### Third party hooks management +If you would rather handle your pre-commit hook outside of the standard `.git/hooks` directory, you can quickly achieve this by adding the following command into your pre-commit script. +For instance, if you utilize [Husky](https://typicode.github.io/husky/) for managing your Git hooks, you can insert the command provided below into your `.husky/pre-commit` file. + +```bash +infisical scan git-changes --staged --verbose +``` + +# +# +# Creating a baseline + +When scanning large repositories or repositories with a long history, it can be helpful to use a baseline. + +A baseline allows Infisical to ignore any old findings that are already present in the baseline findings. You can create a infisical scan report by running `infisical scan` with the `--report-path` flag. + +To create a Infisical scan report and save it in a file called leaks-report.json, use the following command: + +``` +infisical scan --report-path leaks-report.json +``` + +Once a baseline is created, you can apply it when running the `infisical scan` command again. Use the following command: + +``` +infisical scan --baseline-path leaks-report.json --report-path findings.json +``` + +After running the `scan` command with the `--baseline-path` flag, the report output in findings.json will only contain new issues. + +# +# +# Configuration file + +To customize the scan, such as specifying your own rules or establishing exceptions for certain files or paths that should not be flagged as risks, you can define these specifications in the configuration file. + + +```toml infisical-scan.toml +# Title for the configuration file +title = "Some title" + + +# This configuration is the foundation that can be expanded. If there are any overlapping rules +# between this base and the expanded configuration, the rules in this base will take priority. +# Another aspect of extending configurations is the ability to link multiple files, up to a depth of 2. +# "Allowlist" arrays get appended and may have repeated elements. +# "useDefault" and "path" cannot be used simultaneously. Please choose one. +[extend] +# useDefault will extend the base configuration with the default config: +# https://raw.githubusercontent.com/Infisical/infisical/main/cli/config/infisical-scan.toml +useDefault = true +# or you can supply a path to a configuration. Path is relative to where infisical cli +# was invoked, not the location of the base config. +path = "common_config.toml" + +# An array of tables that contain information that define instructions +# on how to detect secrets +[[rules]] + +# Unique identifier for this rule +id = "some-identifier-for-rule" + +# Short human readable description of the rule. +description = "awesome rule 1" + +# Golang regular expression used to detect secrets. Note Golang's regex engine +# does not support lookaheads. +regex = '''one-go-style-regex-for-this-rule''' + +# Golang regular expression used to match paths. This can be used as a standalone rule or it can be used +# in conjunction with a valid `regex` entry. +path = '''a-file-path-regex''' + +# Array of strings used for metadata and reporting purposes. +tags = ["tag","another tag"] + +# A regex match may have many groups, this allows you to specify the group that should be used as (which group the secret is contained in) +# its entropy checked if `entropy` is set. +secretGroup = 3 + +# Float representing the minimum shannon entropy a regex group must have to be considered a secret. +# Shannon entropy measures how random a data is. Since secrets are usually composed of many random characters, they typically have high entropy +entropy = 3.5 + +# Keywords are used for pre-regex check filtering. +# If rule has keywords but the text fragment being scanned doesn't have at least one of it's keywords, it will be skipped for processing further. +# Ideally these values should either be part of the idenitifer or unique strings specific to the rule's regex +# (introduced in v8.6.0) +keywords = [ + "auth", + "password", + "token", +] + +# You can include an allowlist table for a single rule to reduce false positives or ignore commits +# with known/rotated secrets +[rules.allowlist] +description = "ignore commit A" +commits = [ "commit-A", "commit-B"] +paths = [ + '''go\.mod''', + '''go\.sum''' +] +# note: (rule) regexTarget defaults to check the _Secret_ in the finding. +# if regexTarget is not specified then _Secret_ will be used. +# Acceptable values for regexTarget are "match" and "line" +regexTarget = "match" +regexes = [ + '''process''', + '''getenv''', +] +# note: stopwords targets the extracted secret, not the entire regex match +# if the extracted secret is found in the stopwords list, the finding will be skipped (i.e not included in report) +stopwords = [ + '''client''', + '''endpoint''', +] + + +# This is a global allowlist which has a higher order of precedence than rule-specific allowlists. +# If a commit listed in the `commits` field below is encountered then that commit will be skipped and no +# secrets will be detected for said commit. The same logic applies for regexes and paths. +[allowlist] +description = "global allow list" +commits = [ "commit-A", "commit-B", "commit-C"] +paths = [ + '''gitleaks\.toml''', + '''(.*?)(jpg|gif|doc)''' +] + +# note: (global) regexTarget defaults to check the _Secret_ in the finding. +# if regexTarget is not specified then _Secret_ will be used. +# Acceptable values for regexTarget are "match" and "line" +regexTarget = "match" + +regexes = [ + '''219-09-9999''', + '''078-05-1120''', + '''(9[0-9]{2}|666)-\d{2}-\d{4}''', +] +# note: stopwords targets the extracted secret, not the entire regex match +# if the extracted secret is found in the stopwords list, the finding will be skipped (i.e not included in report) +stopwords = [ + '''client''', + '''endpoint''', +] +``` + + +# +# +# Ignoring Known Secrets +If you're intentionally committing a test secret that `infisical scan` might flag, you can instruct Infisical to overlook that secret with the methods listed below. + +### infisical-scan:ignore + +To ignore a secret contained in line of code, simply add `infisical-scan:ignore ` at the end of the line as comment in the given programming. + +```js example.js +function helloWorld() { + console.log("8dyfuiRyq=vVc3RRr_edRk-fK__JItpZ"); // infisical-scan:ignore +} +``` + +### .infisicalignore +An alternative method to exclude specific findings involves creating a .infisicalignore file at your repository's root. +You can then add the fingerprints of the findings you wish to exclude. The Infisical scan report provides a unique Fingerprint for each secret found. +By incorporating these Fingerprints into the .infisicalignore file, Infisical will skip the corresponding secret findings in subsequent scans. + +```.ignore .infisicalignore +bea0ff6e05a4de73a5db625d4ae181a015b50855:frontend/components/utilities/attemptLogin.js:stripe-access-token:147 +bea0ff6e05a4de73a5db625d4ae181a015b50855:backend/src/json/integrations.json:generic-api-key:5 +1961b92340e5d2613acae528b886c842427ce5d0:frontend/components/utilities/attemptLogin.js:stripe-access-token:148 +``` \ No newline at end of file diff --git a/docs/cli/token.mdx b/docs/cli/token.mdx index 38acab208..c6cc6dcdd 100644 --- a/docs/cli/token.mdx +++ b/docs/cli/token.mdx @@ -3,7 +3,7 @@ title: "Infisical Token" description: "How to use Infical service token within the CLI." --- -Prerequisite: [Infisical Token and How to Generate One](../../getting-started/dashboard/token). +Prerequisite: [Infisical Token and How to Generate One](/documentation/platform/token). It's possible to use the CLI to sync environment varialbes without manually entering login credentials by using a service token in the prerequisite link above. diff --git a/docs/cli/usage.mdx b/docs/cli/usage.mdx index 6cb460874..f6e06c966 100644 --- a/docs/cli/usage.mdx +++ b/docs/cli/usage.mdx @@ -18,7 +18,7 @@ Prerequisite: [Install the CLI](/cli/overview) To use Infisical CLI in environments where you cannot run the `infisical login` command, you can authenticate via a - Infisical Token instead. Learn more about [Infisical Token](../getting-started/dashboard/token). + Infisical Token instead. Learn more about [Infisical Token](/documentation/platform/token). @@ -34,10 +34,29 @@ infisical init ## Inject environment variables -```bash -# inject environment variables into app -infisical run -- [your application start command] -``` + + ```bash + # inject environment variables into app + infisical run -- [your application start command] + ``` + + + + Custom aliases can utilize secrets from Infisical. Suppose there is a custom alias `yd` in `custom.sh` that runs `yarn dev` and needs the secrets provided by Infisical. + ```bash + #!/bin/sh + + yd() { + yarn dev + } + ``` + + To make the secrets available from Infisical to `yd`, you can run the following command: + + ```bash + infisical run --command="source custom.sh && yd" + ``` + View all available options for `run` command [here](./commands/run) diff --git a/docs/contributing/developing.mdx b/docs/contributing/developing.mdx index 64779587e..1c7708c99 100644 --- a/docs/contributing/developing.mdx +++ b/docs/contributing/developing.mdx @@ -1,16 +1,16 @@ --- title: 'Local development' -description: 'This guide will help you set up and run Infisical in development mode.' +description: 'This guide will help you set up and run Infisical in local development.' --- -## Clone the repo +## Fork and clone the repo -```bash -# navigate location to the path you want Infisical to be installed +[Fork](https://docs.github.com/en/get-started/quickstart/fork-a-repo) the [repository](https://github.com/Infisical/infisical) to your own GitHub account and then [clone](https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository) it to your local device. -# clone the repo and cd to Infisical dir -git clone https://github.com/Infisical/infisical -cd infisical +Once, you've done that, create a new branch: + +```console +git checkout -b MY_BRANCH_NAME ``` ## Set up environment variables @@ -62,8 +62,8 @@ View all available [environment variables](https://infisical.com/docs/self-hosti ## Starting Infisical for development -We use use Docker to easily spin up all required services to have Infisical up and running for development. If you are unfamiliar with Docker, don't worry, all you have to do is install [Docker](https://docs.docker.com/get-docker/) for your -machine and run the commands below to start up the development server. +We use Docker to spin up all required services for Infisical in local development. If you are unfamiliar with Docker, don’t worry, all you have to do is install Docker for your +machine and run the command below to start up the development server. #### Start local server diff --git a/docs/contributing/overview.mdx b/docs/contributing/overview.mdx index 61d52f066..76475862d 100644 --- a/docs/contributing/overview.mdx +++ b/docs/contributing/overview.mdx @@ -3,9 +3,12 @@ title: "Overview" description: "We welcome any contributions to Infisical, big or small." --- +To set a strong foundation, this section outlines how we, the community and members of Infisical, +should approach the development and contribution process. + ## Community -It's the early days of Infisical and we're working hard to build an awesome, inclusive community. In order to grow this, all community members must adhere to our Code of conduct. +We are building an inclusive community, and this means adhering to the [Code of Conduct](/contributing/code-of-conduct). ## Bugs and issues @@ -26,7 +29,9 @@ If you're ever in doubt about whether or not a proposed feature aligns with Infi ## Writing and submitting code -Anyone can contribute code to Infisical. To get started, check out the local development guide, make your changes, and submit a pull request to the main repository. +Anyone can contribute code to Infisical. To get started, check out the [local development guide](/contributing/developing), make your changes, and submit a pull request to the main repository +adhering to the [pull request guide](/). + ## Licensing diff --git a/docs/contributing/pull-requests.mdx b/docs/contributing/pull-requests.mdx new file mode 100644 index 000000000..a06d9f164 --- /dev/null +++ b/docs/contributing/pull-requests.mdx @@ -0,0 +1,47 @@ +--- +title: 'Pull requests' +description: 'This guide walks through the code submission process for Infisical.' +--- + +## Making a pull request + +Once you are done making changes in local development, you can submit a pull request (PR) to the main repository branch. + +We require a few considerations on your part to ensure that PRs are easy to review and up to standard with the code. + +### Title and content + +Start by providing a concise title addressing what your PR achieves such as "add pagination to retrieve environment variables for GitLab integration." + +You should follow the automatically-generated PR template to fill in the PR description. This includes a more detailed description of the changes in the PR, the type of PR, and an acknowledgement that you've read and agreed to the contributing guidelines. + +### Feature PRs + +Give a functional overview of how your feature works, including how the user can use the feature. Then share any technical details in an overview of how the PR works. + +As of `06-01-2023`, all PRs created after this date are required to attach a video of you performing the described functionality. + +### Bug Fix PRs + +Give an overview of the bug at hand and how your PR fixes the it at both a high and low level. + +Feel free to add a short video or screenshots of what your PR achieves. + +## Getting your PR reviewed + +Once your PR is reviewed, one or two relevent members of the Infisical team should review and approve the PR before it is merged. You should coordinate and ping the team member closest to the submitted functionality via our [Slack](https://infisical.com/slack) to review your PR. + +- Vlad: Frontend, Web UI +- Tony: Backend, SDKs, Security +- Maidul: Backend, CI/CD, CLI, Kubernetes Operator + +The team member(s) will start by enabling baseline checks to ensure that there are no leaked secrets, new dependencies are clear, and the frontend/backend services start up. Afterward, they will review your PR thoroughly by testing the code and leave any feedback or work in with you to revise the PR up to standard. + +Once everything is good, the team member(s) will approve the PR to be merged into the `main` branch; all changes will be tested in CI/CD and our staging environment first before being deployed to production. + + + Due to the high volume of issues, PRs, etc. from the community, and limited bandwidth on our end to address everything instantly, we prefer + reviewing PRs once they are fully complete and well-tested. + + In the past, we've often had to review low-quality PRs up to 10 times which severely restricts our capacity to address other issues, PRs, and initiatives in the pipeline. As such, we ask of the community to submit higher-quality PRs that, for example, don't break existing code; in return we'll prioritize the first 3 reviews for PRs. + \ No newline at end of file diff --git a/docs/documentation/getting-started/api.mdx b/docs/documentation/getting-started/api.mdx new file mode 100644 index 000000000..279982911 --- /dev/null +++ b/docs/documentation/getting-started/api.mdx @@ -0,0 +1,59 @@ +--- +title: "REST API" +--- + +Infisical's Public (REST) API is the most flexible, platform-agnostic way to read/write secrets for your application. + +Prerequisites: + +- Have a project with secrets ready in [Infisical Cloud](https://app.infisical.com). +- Create an [Infisical Token](/documentation/platform/token) scoped to an environment in your project in Infisical. + +To keep it simple, we're going to fetch secrets from the API with **End-to-End Encryption (E2EE)** disabled. + + + It's possible to use the API with **E2EE** enabled but this means learning about how encryption works with Infisical and performing client-side encryption/decryption operations yourself. + yourself. + + If **E2EE** is a must for your team, we recommend either using one of the [Infisical SDKs](/documentation/getting-started/sdks) or checking out the [examples for E2EE](/api-reference/overview/examples/e2ee-disabled). + + +## Configuration + +Head to your Project Settings, where you created your service token, and un-check the **E2EE** setting. + +## Retrieve Secret + +Retrieve a secret from the project and environment in Infisical scoped to your service token by making a HTTP request with the following format/details: + +```bash +curl --location --request GET 'https://app.infisical.com/api/v3/secrets/raw/secretName?workspaceId=workspaceId&environment=environment' \ + --header 'Authorization: Bearer serviceToken' +``` + + + Name of secret to retrieve + + + The ID of the workspace + + + The environment slug + + + Path to secrets in workspace + + + The type of the secret. Valid options are “shared” or “personal” + + +Depending on your application requirements, you may wish to use Infisical's API in different ways such as by retaining **E2EE** +or fetching multiple secrets at once instead of one at a time. + +Whatever the case, we recommend glossing over the [API Examples](/api-reference/overview/examples/note) +to gain a deeper understanding of how you to best leverage the Infisical API for your use-case. + +See also: + +- Explore the [API Examples](/api-reference/overview/examples/note) +- [API Reference](/api-reference/overview/introduction) \ No newline at end of file diff --git a/docs/documentation/getting-started/cli.mdx b/docs/documentation/getting-started/cli.mdx new file mode 100644 index 000000000..2e9416ee3 --- /dev/null +++ b/docs/documentation/getting-started/cli.mdx @@ -0,0 +1,128 @@ +--- +title: "CLI" +--- + +The Infisical CLI can be used to inject secrets into any framework like Next.js, Express, Django and more in local development. + +It can also be used to expose secrets from Infisical as environment variables in CI/CD pipelines and [Docker containers](/documentation/getting-started/docker) + +Prerequisites: + +- Have a project with secrets ready in [Infisical Cloud](https://app.infisical.com). + +## Installation + +Follow the instructions for your operating system to install the Infisical CLI. + + + + Use [brew](https://brew.sh/) package manager + + ```console + $ brew install infisical/get-cli/infisical + ``` + + + Use [Scoop](https://scoop.sh/) package manager + + ```console + $ scoop bucket add org https://github.com/Infisical/scoop-infisical.git + ``` + + ```console + $ scoop install infisical + ``` + + + Install prerequisite + ```console + $ apk add --no-cache bash sudo + ``` + + Add Infisical repository + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' \ + | bash + ``` + + Then install CLI + ```console + $ apk update && sudo apk add infisical + ``` + + + + Add Infisical repository + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.rpm.sh' \ + | sudo -E bash + ``` + + Then install CLI + ```console + $ sudo yum install infisical + ``` + + + + Add Infisical repository + + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' \ + | sudo -E bash + ``` + + Then install CLI + ```console + $ sudo apt-get update && sudo apt-get install -y infisical + ``` + + + + Use the `yay` package manager to install from the [Arch User Repository](https://aur.archlinux.org/packages/infisical-bin) + + ```console + $ yay -S infisical-bin + ``` + + + + +## Login + +Authenticate the CLI with the Infisical platform using your email and password. + +```console +$ infisical login +``` + +## Initialization + +Navigate to the root of your project directory and run the `init` command. This step connects your local project to the project on the Infisical platform and creates a `infisical.json` file containing a reference to that latter project. + +```console +$ infisical init +``` + +## Start your app with environment variables injected + +```console +$ infisical run -- +``` + +## Example Start Commands + +```console +$ infisical run -- npm run dev +$ infisical run -- flask run +$ infisical run -- ./your_bash_script.sh +``` + +Your app should now be running with the secrets from Infisical injected as environment variables. + +See also: + +- [Full documentation for the Infisical CLI](/cli/overview) \ No newline at end of file diff --git a/docs/documentation/getting-started/docker.mdx b/docs/documentation/getting-started/docker.mdx new file mode 100644 index 000000000..567745ea4 --- /dev/null +++ b/docs/documentation/getting-started/docker.mdx @@ -0,0 +1,185 @@ +--- +title: "Docker" +--- + +The [Infisical CLI](/cli/overview) can be added to Dockerfiles to fetch secrets from Infisical and make them available as environment variables within containers at runtime. + +Prerequisites: + +- Have a project with secrets ready in [Infisical Cloud](https://app.infisical.com). +- Create an [Infisical Token](/documentation/platform/token) scoped to an environment in your project in Infisical. + + + + + + ## Dockerfile Modification + + Follow the instruction for your specific Linux distrubtion to add the Infisical CLI to your Dockerfile. + + + + ```dockerfile + RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical + ``` + + + + ```dockerfile + RUN curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.rpm.sh' | sh \ + && yum install -y infisical + ``` + + + ```dockerfile + RUN apt-get update && apt-get install -y bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash \ + && apt-get update && apt-get install -y infisical + ``` + + + + Next, modify the start command of your Dockerfile: + + ```dockerfile + CMD ["infisical", "run", "--", "[your service start command]"] + ``` + + ## Launch + + Spin up your container with the `docker run` command and feed in your Infisical Token. + + ```console + docker run --env INFISICAL_TOKEN= + ``` + + Your containerized application should now be up and running with secrets from Infisical exposed as environment variables within your application's process. + + ## Example Dockerfile + + ```dockerfile + # Select your base image (based on your Linux distribution, e.g., Alpine, Debian, Ubuntu, etc.) + FROM alpine + + # Add the Infisical CLI to your Dockerfile (choose the appropriate block based on your base image) + RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical + + # Install any additional dependencies or packages your service requires + # RUN + + # Copy your service files to the container + COPY . /app + + # Set the working directory + WORKDIR /app + + # Modify the start command of your Dockerfile + CMD ["infisical", "run", "--", "npm run start"] + ``` + + + + + ## Dockerfile Modifications + + Follow the instruction for your specific Linux distributions to add the Infisical CLI to your Dockerfiles. + + + + ```dockerfile + RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical + ``` + + + + ```dockerfile + RUN curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.rpm.sh' | sh \ + && yum install -y infisical + ``` + + + ```dockerfile + RUN apt-get update && apt-get install -y bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' | bash \ + && apt-get update && apt-get install -y infisical + ``` + + + + Next, modify the start commands of your Dockerfiles: + + ```dockerfile + CMD ["infisical", "run", "--", "[your service start command]"] + ``` + + ## Example Dockerfile + + ```dockerfile + # Select your base image (based on your Linux distribution, e.g., Alpine, Debian, Ubuntu, etc.) + FROM alpine + + # Add the Infisical CLI to your Dockerfile (choose the appropriate block based on your base image) + RUN apk add --no-cache bash curl && curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' | bash \ + && apk add infisical + + # Install any additional dependencies or packages your service requires + # RUN + + # Copy your service files to the container + COPY . /app + + # Set the working directory + WORKDIR /app + + # Modify the start command of your Dockerfile + CMD ["infisical", "run", "--", "[your service start command]"] + ``` + + ## Docker Compose File Modification + + For each service you want to inject secrets into, set an environment variable called `INFISICAL_TOKEN` equal to a unique identifier variable. For example: + + ```yaml + services: + api: + build: . + image: example-service-2 + environment: + - INFISICAL_TOKEN=${INFISICAL_TOKEN_FOR_API} + ... + ``` + + ## Export shell variables + + Next, set the shell variables you defined in your compose file. Continuing from the previous example: + + ```console + export INFISICAL_TOKEN_FOR_API= + ``` + + ## Launch + + Spin up your containers with the `docker-compose up` command. + + ```console + docker-compose up + ``` + + Your containers should now be running with the secrets from Infisical available inside as environment variables. + + + + +See also: + +- [Documentation for Docker](/integrations/platforms/docker) +- [Documentation for Docker Compose](/integrations/platforms/docker-compose) \ No newline at end of file diff --git a/docs/documentation/getting-started/introduction.mdx b/docs/documentation/getting-started/introduction.mdx new file mode 100644 index 000000000..46a2f48e3 --- /dev/null +++ b/docs/documentation/getting-started/introduction.mdx @@ -0,0 +1,106 @@ +--- +title: "Introduction" +--- + +Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret management platform that enables teams to easily manage and sync their environment variables. + +Start syncing environment variables with [Infisical Cloud](https://app.infisical.com) or learn how to [host Infisical](/self-hosting/overview) yourself. + +## Learn about Infisical + + + Store secrets like API keys, database credentials, environment variables with Infisical + + +## Integrate with Infisical + + + + Inject secrets into any application process/environment + + + Fetch secrets with any programming language on demand + + + Inject secrets into Docker containers + + + Fetch and save secrets as native Kubernetes secrets + + + Fetch secrets via HTTP request + + + +## Resources + + + + Learn how to configure and deploy Infisical + + + Explore guides for every language and stack + + + Explore integrations for GitHub, Vercel, Netlify, and more + + + Explore integrations for Next.js, Express, Django, and more + + + Scan and prevent 140+ secret type leaks in your codebase + + + Questions? Need help setting up? Book a 1x1 meeting with us + + diff --git a/docs/documentation/getting-started/kubernetes.mdx b/docs/documentation/getting-started/kubernetes.mdx new file mode 100644 index 000000000..495f3445e --- /dev/null +++ b/docs/documentation/getting-started/kubernetes.mdx @@ -0,0 +1,83 @@ +--- +title: "Kubernetes" +--- + +The Infisical Secrets Operator fetches secrets from Infisical and saves them as Kubernetes secrets using the custom `InfisicalSecret` resource to define authentication and storage methods. +The operator updates secrets continuously and can reload dependent deployments automatically on secret changes. + +Prerequisites: + +- Connected to your cluster via kubectl +- Have a project with secrets ready in [Infisical Cloud](https://app.infisical.com). +- Create an [Infisical Token](/documentation/platform/token) scoped to an environment in your project in Infisical. + +## Installation + +Follow the instructions for either [Helm](https://helm.sh/) or [kubectl](https://github.com/kubernetes/kubectl) to install the Infisical Secrets Operator. + + + + Install the Infisical Helm repository + + ```console + helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/' + + helm repo update + ``` + + Install the Helm chart + ```console + helm install --generate-name infisical-helm-charts/secrets-operator + ``` + + + + The operator will be installed in `infisical-operator-system` namespace + ``` + kubectl apply -f https://raw.githubusercontent.com/Infisical/infisical/main/k8-operator/kubectl-install/install-secrets-operator.yaml + ``` + + + + +## Usage + +**Step 1: Create Kubernetes secret containing service token** + +Once you have generated the service token, create a Kubernetes secret containing the service token you generated by running the command below. + +``` bash +kubectl create secret generic service-token --from-literal=infisicalToken= +``` + +**Step 2: Fill out the InfisicalSecrets CRD and apply it to your cluster** + +```yaml infisical-secrets-config.yaml +apiVersion: secrets.infisical.com/v1alpha1 +kind: InfisicalSecret +metadata: + # Name of of this InfisicalSecret resource + name: infisicalsecret-sample +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 + authentication: + serviceToken: + serviceTokenSecretReference: # <-- The secret's namespaced name that holds the project token for authentication in step 1 + secretName: service-token + secretNamespace: option + managedSecretReference: + secretName: managed-secret # <-- the name of kubernetes secret that will be created + secretNamespace: default # <-- in what namespace it will be created in +``` + +``` +kubectl apply -f infisical-secrets-config.yaml +``` + +You should now see a new kubernetes secret automatically created in the namespace you defined in the `managedSecretReference` property above. + +See also: + +- [Documentation for the Infisical Kubernetes Operator](../../integrations/platforms/kubernetes) + diff --git a/docs/documentation/getting-started/platform.mdx b/docs/documentation/getting-started/platform.mdx new file mode 100644 index 000000000..a21352a09 --- /dev/null +++ b/docs/documentation/getting-started/platform.mdx @@ -0,0 +1,57 @@ +--- +title: "Platform" +--- + +Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret management platform that enables teams to easily store, manage, and sync secrets like API keys, database credentials, and environment variables across their apps and infrastructure. + +This quickstart provides an overview of the functionalities offered by Infisical. + +## Projects + +Projects hold secrets for applications, which are further organized into environments such as development, testing and production. + +### Secrets Overview + +The secrets overview provides a bird's-eye view of all the secrets in a project and is particularly useful for identifying missing secrets across environments. + +![dashboard secrets overview](../../images/dashboard-secrets-overview.png) + +### Secrets Dashboard + +The secrets dashboard lets you manage secrets for a specific environment in a project. +Here, developers can [override secrets](//project#personal-overrides), [version secrets](/documentation/platform/secret-versioning), [rollback projects to any point in time](/documentation/platform/pit-recovery), and much more. + +![dashboard](../../images/dashboard.png) + +### Integrations + +The integrations page provides native integrations to sync secrets from a project environment to a [host of ever-expanding integrations](/integrations/overview). + + + Depending on your infrastructure setup and compliance requirements, you may or may not prefer to use these native integrations since they break end-to-end encryption (E2EE). + + You will learn about various ways to integrate with Infisical and maintain E2EE in subsequent quickstart sections. + + +![integrations](../../images/integrations.png) + +### Access Control + +The members page lets you add/remove members for a project and provision them access to environments (access levels include `No Access`, `Read Only`, and `Read and Write`). + +![project members](../../images/project-members.png) + +## Organizations + +Organizations house projects and members. + +### Organization Settings + +At the organization-level, you can add/remove members and manage their access to projects. + +![organization name modal open](../../images/dashboard-name-modal-organization.png) +![organization name modal open](../../images/organization.png) + +That's it for the platform quickstart! — We encourage you to continue exploring the documentation to gain a deeper understanding of the extensive features and functionalities that Infisical has to offer. + +Next, head back to [Getting Started > Introduction](/documentation/getting-started/overview) to explore ways to fetch secrets from Infisical to your apps and infrastructure. \ No newline at end of file diff --git a/docs/documentation/getting-started/sdks.mdx b/docs/documentation/getting-started/sdks.mdx new file mode 100644 index 000000000..67608bb81 --- /dev/null +++ b/docs/documentation/getting-started/sdks.mdx @@ -0,0 +1,145 @@ +--- +title: "SDKs" +--- + +From local development to production, Infisical's language-specific SDKs provide the easiest way for your app to fetch back secrets on demand. + +Prerequisites: + +- Have a project with secrets ready in [Infisical Cloud](https://app.infisical.com). +- Create an [Infisical Token](/documentation/platform/token) scoped to an environment in your project in Infisical. + +## Installation + +Follow the instructions for your language to install the SDK for it. + + + + + Run `npm` to add [infisical-node](https://github.com/Infisical/infisical-node) to your project. + + ```console + $ npm install infisical-node --save + ``` + + ## Configuration + + Import the SDK and create a client instance with your [Infisical Token](/documentation/platform/token). + + + + ```js + import InfisicalClient from "infisical-node"; + + const client = new InfisicalClient({ + token: "your_infisical_token" + }); + ``` + + + + ```js + const InfisicalClient = require("infisical-node"); + + const client = new InfisicalClient({ + token: "your_infisical_token" + }); + ```` + + + ## Get a Secret + + ```js + const secret = await client.getSecret("API_KEY"); + const value = secret.secretValue; // get its value + ``` + + ## Basic Usage + + ```js + import express from "express"; + import InfisicalClient from "infisical-node"; + const app = express(); + const PORT = 3000; + + const client = new InfisicalClient({ + token: "YOUR_INFISICAL_TOKEN" + }); + + app.get("/", async (req, res) => { + // access value + const name = await client.getSecret("NAME"); + res.send(`Hello! My name is: ${name.secretValue}`); + }); + + app.listen(PORT, async () => { + console.log(`App listening on port ${port}`); + }); + ``` + + This example demonstrates how to use the Infisical Node SDK with an Express application. The application retrieves a secret named "NAME" and responds to requests with a greeting that includes the secret value. + + + + ## Installation + + Run `pip` to add [infisical-python](https://github.com/Astropilot/infisical-python) to your project + + ```console + $ pip install infisical + ``` + + Note: You need Python 3.7+. + + ## Configuration + + Import the SDK and create a client instance with your [Infisical Token](/documentation/platform/token). + + ```py + from infisical import InfisicalClient + + client = InfisicalClient(token="your_infisical_token") + ``` + + ## Get a Secret + + ```py + secret = client.get_secret("API_KEY") + value = secret.secret_value # get its value + ``` + + ## Basic Usage + + ```py + from flask import Flask + from infisical import InfisicalClient + + app = Flask(__name__) + + client = InfisicalClient(token="your_infisical_token") + + @app.route("/") + def hello_world(): + # access value + name = client.get_secret("NAME") + return f"Hello! My name is: {name.secret_value}" + ``` + + This example demonstrates how to use the Infisical Python SDK with a Flask application. The application retrieves a secret named "NAME" and responds to requests with a greeting that includes the secret value. + + + We're currently working on SDKs for other languages. Follow the GitHub issue for your needed language below: + - [Java](https://github.com/Infisical/infisical/issues/434) + - [Ruby](https://github.com/Infisical/infisical/issues/435) + - [Go](https://github.com/Infisical/infisical/issues/436) + - [Rust](https://github.com/Infisical/infisical/issues/437) + - [PHP](https://github.com/Infisical/infisical/issues/531) + + Missing a language? [Throw in a request](https://github.com/Infisical/infisical/issues). + + + +See also: + +- Explore the [Node SDK](https://github.com/Infisical/infisical-node) +- Explore the [Python SDK](https://github.com/Infisical/infisical-python) \ No newline at end of file diff --git a/docs/documentation/guides/introduction.mdx b/docs/documentation/guides/introduction.mdx new file mode 100644 index 000000000..caa506045 --- /dev/null +++ b/docs/documentation/guides/introduction.mdx @@ -0,0 +1,41 @@ +--- +title: "Introduction" +--- + +Whether you're running a Node application on Heroku, Next.js application with Vercel, or Kubernetes on AWS, Infisical has a secret management strategy from local development to production ready for you. + +## Guides by Language + + + + Manage secrets across your Node stack + + + Manage secrets across your Python stack + + + +## Guides by Stack + + + + Manage secrets for your Next.js + Vercel stack + + + +Want a guide? [Throw in a request](https://github.com/Infisical/infisical/issues). \ No newline at end of file diff --git a/docs/documentation/guides/nextjs-vercel.mdx b/docs/documentation/guides/nextjs-vercel.mdx new file mode 100644 index 000000000..52f5b1e8e --- /dev/null +++ b/docs/documentation/guides/nextjs-vercel.mdx @@ -0,0 +1,254 @@ +--- +title: "Next.js + Vercel" +--- + + +This guide demonstrates how to use Infisical to manage secrets for your Next.js + Vercel stack from local development to production. It uses: + +- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets. + +## Project Setup + +To begin, we need to set up a project in Infisical and add secrets to an environment in it. + +### Create a project + +1. Create a new project in [Infisical](https://app.infisical.com/). + +2. Add a secret to the development environment of this project so we can pull it back for local development. In the **Secrets Overview** page, press **Explore Development** and add a secret with the key `NEXT_PUBLIC_NAME` and value `YOUR_NAME`. + +3. Add a secret to the production environment of this project so we can sync it to Vercel. Switch to the **Production** environment and add a secret with the key `NEXT_PUBLIC_NAME` and value `ANOTHER_NAME`. + +## Create a Next.js app + +Initialize a new Node.js app. + +We can use `create-next-app` to initialize an app called `infisical-nextjs`. + + + + ```console + npx create-next-app@latest --use-npm infisical-nextjs + cd infisical-nextjs + ``` + + + ```console + npx create-next-app@latest --ts --use-npm infisical-nextjs + cd infisical-nextjs + ``` + + + +Next, inside `pages/_app.js`, lets add a `console.log()` to print out the environment variable in the browser console. + + + + ```js + import '@/styles/globals.css' + + export default function App({ Component, pageProps }) { + console.log('Hello, ', process.env.NEXT_PUBLIC_NAME); + return + } + ``` + + + ```tsx + import '@/styles/globals.css' + import type { AppProps } from 'next/app' + + export default function App({ Component, pageProps }: AppProps) { + console.log('Hello, ', process.env.NEXT_PUBLIC_NAME); + return + } + ``` + + + +## Infisical CLI for local development environment variables + +We'll now use the Infisical CLI to fetch secrets from Infisical into your Next.js app for local development. + +### CLI Installation + +Follow the instructions for your operating system to install the Infisical CLI. + + + + Use [brew](https://brew.sh/) package manager + + ```console + $ brew install infisical/get-cli/infisical + ``` + + + Use [Scoop](https://scoop.sh/) package manager + + ```console + $ scoop bucket add org https://github.com/Infisical/scoop-infisical.git + ``` + + ```console + $ scoop install infisical + ``` + + + Install prerequisite + ```console + $ apk add --no-cache bash sudo + ``` + + Add Infisical repository + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.alpine.sh' \ + | bash + ``` + + Then install CLI + ```console + $ apk update && sudo apk add infisical + ``` + + + + Add Infisical repository + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.rpm.sh' \ + | sudo -E bash + ``` + + Then install CLI + ```console + $ sudo yum install infisical + ``` + + + + Add Infisical repository + + ```console + $ curl -1sLf \ + 'https://dl.cloudsmith.io/public/infisical/infisical-cli/setup.deb.sh' \ + | sudo -E bash + ``` + + Then install CLI + ```console + $ sudo apt-get update && sudo apt-get install -y infisical + ``` + + + + Use the `yay` package manager to install from the [Arch User Repository](https://aur.archlinux.org/packages/infisical-bin) + + ```console + $ yay -S infisical-bin + ``` + + + + +### Login + +Authenticate the CLI with the Infisical platform using your email and password. + +```console +$ infisical login +``` + +### Initialization + +Run the `init` command at the root of the Next.js app. This step connects your local project to the project on the Infisical platform and creates a `infisical.json` file containing a reference to that latter project. + +```console +$ infisical init +``` + +### Start the Next.js app with secrets injected as environment variables + +```console +$ infisical run -- npm run dev +``` + +If you open your browser console, **Hello, YOUR_NAME** should be printed out. + +Here, the CLI fetched the secret from Infisical and injected it into the Next.js app upon starting up. By default, +the CLI fetches secrets from the development environment which has the slug `dev`; you can inject secrets from different +environments by modifying the `env` flag as per the [CLI documentation](/cli/usage). + +At this stage, you know how to use the Infisical CLI to inject secrets into your Next.js app for local development. + +## Infisical-Vercel integration for production environment variables + +We'll now use the Infisical-Vercel integration send secrets from Infisical to Vercel as production environment variables. + +### Infisical-Vercel integration + +To begin we have to import the Next.js app into Vercel as a project. [Follow these instructions](https://nextjs.org/learn/basics/deploying-nextjs-app/deploy) to deploy the Next.js app to Vercel. + +Next, navigate to your project's integrations tab in Infisical and press on the Vercel tile to grant Infisical access to your Vercel account. + +![integrations](../../images/integrations.png) + +![integrations vercel authorization](../../images/integrations-vercel-auth.png) + + + Opting in for the Infisical-Vercel integration will break end-to-end encryption since Infisical will be able to read + your secrets. This is, however, necessary for Infisical to sync the secrets to Vercel. + + Your secrets remain encrypted at rest following our [security guide mechanics](/security/mechanics). + + +Now select **Production** for (the source) **Environment** and sync it to the **Production Environment** of the (target) application in Vercel. +Lastly, press create integration to start syncing secrets to Vercel. + +![integrations vercel](../../images/integrations-vercel-create.png) +![integrations vercel](../../images/integrations-vercel.png) + +You should now see your secret from Infisical appear as production environment variables in your Vercel project. + +At this stage, you know how to use the Infisical-Vercel integration to sync production secrets from Infisical to Vercel. + + + The following environment variable names are reserved by Vercel and cannot be + synced: `AWS_SECRET_KEY`, `AWS_EXECUTION_ENV`, `AWS_LAMBDA_LOG_GROUP_NAME`, + `AWS_LAMBDA_LOG_STREAM_NAME`, `AWS_LAMBDA_FUNCTION_NAME`, + `AWS_LAMBDA_FUNCTION_MEMORY_SIZE`, `AWS_LAMBDA_FUNCTION_VERSION`, + `NOW_REGION`, `TZ`, `LAMBDA_TASK_ROOT`, `LAMBDA_RUNTIME_DIR`, + `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`, + `AWS_REGION`, and `AWS_DEFAULT_REGION`. + + +## FAQ + + + + Vercel does not specialize in secret management which means it lacks many useful features for effectively managing environment variables. + Here are some features that teams benefit from by using Infisical together with Vercel: + + - Audit logs: See which team members are creating, reading, updating, and deleting environment variables across all environments. + - Versioning and point in time recovery: Rolling back secrets and an entire project state. + - Overriding secrets that should be unique amongst team members. + + And much more. + + + Yes. Your secrets are still encrypted at rest. To note, most secret managers actually don't support end-to-end encryption. + + Check out the [security guide](/security/overview). + + + Yes. You can also use the Infisical [Node SDK](https://github.com/Infisical/infisical-node) to fetch secrets back to your Next.js app + in both development and production. + + Depending on how you use it, however, it may require certain pages to be server-side rendered. + + + +See also: + +- [Documentation for the Infisical CLI](/cli/overview) +- [Documentation for the Vercel integration](/integrations/cloud/vercel) diff --git a/docs/documentation/guides/node.mdx b/docs/documentation/guides/node.mdx new file mode 100644 index 000000000..323d95072 --- /dev/null +++ b/docs/documentation/guides/node.mdx @@ -0,0 +1,121 @@ +--- +title: "Node" +--- + +This guide demonstrates how to use Infisical to manage secrets for your Node stack from local development to production. It uses: + +- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets. +- The [infisical-node](https://github.com/Infisical/infisical-node) client SDK to fetch secrets back to your Node application on demand. + +## Project Setup + +To begin, we need to set up a project in Infisical and add secrets to an environment in it. + +### Create a project + +1. Create a new project in [Infisical](https://app.infisical.com/). + +2. Add a secret to the development environment of this project so we can pull it back for local development. In the **Secrets Overview** page, press **Explore Development** and add a secret with the key `NAME` and value `YOUR_NAME`. + +### Create an Infisical Token + +Now that we've created a project and added a secret to its development environment, we need to provision an Infisical Token that our Node application can use to access the secret. + +1. Head to the **Project Settings > Service Tokens** and press **Add New Token**. +2. Call the token anything like **My App Token** and select **Development** under **Environment**. +3. Copy the token and keep it handy. + + +## Create a Node app + +For this demonstration, we use a minimal Express application. However, the same principles will apply for any Node application such as those built on Koa or Fastify. + +### Create an Express app + +Initialize a new Node.js project with a default `package.json` file. + +```console +npm init -y +``` + +Install `express` and [infisical-node](https://github.com/Infisical/infisical-node), the client Node SDK for Infisical. + +```console +npm install express infisical-node +``` + +Finally, create an index.js file containing the application code. + +```js +const express = require("express"); +const app = express(); +const PORT = 3000; + +const client = new InfisicalClient({ + token: "YOUR_INFISICAL_TOKEN" +}); + +app.get("/", async (req, res) => { + const name = (await client.getSecret("NAME")).secretValue; + res.send(`Hello, ${name}!`); +}); + +app.listen(PORT, () => { + console.log(`Example app listening on port ${PORT}`); +}); +``` + +Here, we initialized a `client` instance of the Infisical Node SDK with the Infisical Token +that we created earlier, giving access to the secrets in the development environment of the +project in Infisical that we created earlier. + +Finally, start the app and head to `http://localhost:3000` to see the message **Hello, Your Name**. + +```console +node index.js +``` + +The client fetched the secret with the key `NAME` from Infisical that we returned in the response of the endpoint. + +At this stage, you know how to fetch secrets from Infisical back to your Node application. By using Infisical Tokens scoped to different environments, you can easily manage secrets across various stages of your project in Infisical, from local development to production. + +## FAQ + + + + No. Infisical uses end-to-end encryption which ensures that secrets are always encrypted in transit + and decrypted on the client side. In fact, not even the server can decrypt your secrets (unless + that permission is explicitly granted from within the platform). + + Check out the [security guide](/security/overview). + + + The client SDK caches every secret and implements a 5-minute waiting period before + re-requesting it. The waiting period can be controlled by setting the `cacheTTL` parameter at + the time of initializing the client. + + + The SDK caches every secret and falls back to the cached value if a request fails. If no cached + value ever-existed, the SDK falls back to whatever value is on `process.env`. + + + Yes. If no `token` parameter is passed in at the time of initializing the client or nothing is found when requesting for a secret, + then the SDK falls back to whatever value is on `process.env`. + + + The token enables the SDK to authenticate with Infisical to fetch back your secrets. + Although the SDK requires you to pass in a token, it enables greater efficiency and security + than if you managed dozens of secrets yourself without it. Here're some benefits: + + - You always pull in the right secrets because they're fetched on demand from a centralize source that is Infisical. + - You can use the Infisical which comes with tons of benefits like secret versioning, access controls, audit logs, etc. + - You now risk leaking one token that can be revoked instead of dozens of raw secrets. + + And much more. + + + + +See also: + +- Explore the [Node SDK](https://github.com/Infisical/infisical-node) \ No newline at end of file diff --git a/docs/documentation/guides/python.mdx b/docs/documentation/guides/python.mdx new file mode 100644 index 000000000..2c558a69c --- /dev/null +++ b/docs/documentation/guides/python.mdx @@ -0,0 +1,119 @@ +--- +title: "Python" +--- + +This guide demonstrates how to use Infisical to manage secrets for your Python stack from local development to production. It uses: + +- Infisical (you can use [Infisical Cloud](https://app.infisical.com) or a [self-hosted instance of Infisical](https://infisical.com/docs/self-hosting/overview)) to store your secrets. +- The [infisical-python](https://github.com/Infisical/infisical-python) client SDK to fetch secrets back to your Python application on demand. + +## Project Setup + +To begin, we need to set up a project in Infisical and add secrets to an environment in it. + +### Create a project + +1. Create a new project in [Infisical](https://app.infisical.com/). + +2. Add a secret to the development environment of this project so we can pull it back for local development. In the **Secrets Overview** page, press **Explore Development** and add a secret with the key `NAME` and value `YOUR_NAME`. + +### Create an Infisical Token + +Now that we've created a project and added a secret to its development environment, we need to provision an Infisical Token that our Node application can use to access the secret. + +1. Head to the **Project Settings > Service Tokens** and press **Add New Token**. +2. Call the token anything like **My App Token** and select **Development** under **Environment**. +3. Copy the token and keep it handy. + +## Create a Python app + +For this demonstration, we use a minimal Flask application. However, the same principles will apply for any Python application such as those built with Django. + +### Create a Flask app + +First, create a virtual environment and activate it. + +```console +python3 -m venv env +source env/bin/activate +``` + +Install Flask and [infisical-python](https://github.com/Infisical/infisical-python), the client Python SDK for Infisical. + +```console +pip install Flask infisical +``` + +Finally, create an `app.py` file containing the application code. + +```python +from flask import Flask +from infisical import InfisicalClient + +app = Flask(__name__) + +client = InfisicalClient(token="your_infisical_token") + +@app.route("/") +def hello_world(): + # access value + name = client.get_secret("NAME") + return f"Hello, {name.secret_value}!" +``` + +Here, we initialized a `client` instance of the Infisical Python SDK with the Infisical Token +that we created earlier, giving access to the secrets in the development environment of the +project in Infisical that we created earlier. + +Finally, start the app and head to `http://localhost:5000` to see the message **Hello, Your Name**. + +```console +flask run +``` + +The client fetched the secret with the key `NAME` from Infisical that we returned in the response of the endpoint. + +At this stage, you know how to fetch secrets from Infisical back to your Python application. By using Infisical Tokens scoped to different environments, you can easily manage secrets across various stages of your project in Infisical, from local development to production. + +## FAQ + + + + No. Infisical uses end-to-end encryption which ensures that secrets are always encrypted in transit + and decrypted on the client side. In fact, not even the server can decrypt your secrets (unless + that permission is explicitly granted from within the platform). + + Check out the [security guide](/security/overview). + + + The client SDK caches every secret and implements a 5-minute waiting period before + re-requesting it. The waiting period can be controlled by setting the `cacheTTL` parameter at + the time of initializing the client. + + + The SDK caches every secret and falls back to the cached value if a request fails. If no cached + value ever-existed, the SDK falls back to whatever value is on `process.env`. + + + Yes. If no `token` parameter is passed in at the time of initializing the client or nothing is found when requesting for a secret, + then the SDK falls back to whatever value is on `process.env`. + + + The token enables the SDK to authenticate with Infisical to fetch back your secrets. + Although the SDK requires you to pass in a token, it enables greater efficiency and security + than if you managed dozens of secrets yourself without it. Here're some benefits: + + - You always pull in the right secrets because they're fetched on demand from a centralize source that is Infisical. + - You can use the Infisical which comes with tons of benefits like secret versioning, access controls, audit logs, etc. + - You now risk leaking one token that can be revoked instead of dozens of raw secrets. + + And much more. + + + + +See also: + +- Explore the [Python SDK](https://github.com/Infisical/infisical-python) + + diff --git a/docs/getting-started/dashboard/audit-logs.mdx b/docs/documentation/platform/audit-logs.mdx similarity index 100% rename from docs/getting-started/dashboard/audit-logs.mdx rename to docs/documentation/platform/audit-logs.mdx diff --git a/docs/getting-started/dashboard/create-account.mdx b/docs/documentation/platform/create-account.mdx similarity index 100% rename from docs/getting-started/dashboard/create-account.mdx rename to docs/documentation/platform/create-account.mdx diff --git a/docs/getting-started/dashboard/integrations.mdx b/docs/documentation/platform/integrations.mdx similarity index 100% rename from docs/getting-started/dashboard/integrations.mdx rename to docs/documentation/platform/integrations.mdx diff --git a/docs/getting-started/dashboard/mfa.mdx b/docs/documentation/platform/mfa.mdx similarity index 100% rename from docs/getting-started/dashboard/mfa.mdx rename to docs/documentation/platform/mfa.mdx diff --git a/docs/getting-started/dashboard/organization.mdx b/docs/documentation/platform/organization.mdx similarity index 72% rename from docs/getting-started/dashboard/organization.mdx rename to docs/documentation/platform/organization.mdx index 63ec2cd49..161a79f14 100644 --- a/docs/getting-started/dashboard/organization.mdx +++ b/docs/documentation/platform/organization.mdx @@ -24,6 +24,14 @@ To add a member to your organization, scroll down to the "Organization Members" projects by default. +## Service Accounts + +Service accounts represent machine identities such as VMs or application clients that can authenticate with Infisical. They can be provisioned read/write permissions for project(s) and environment(s). + +To add a service account to your organization, scroll down to the "Service Accounts" section and create a service account. Afterwards, you can press on the edit button beside the service account to provision it permissions. + +![organization service accounts](../../images/organization-service-accounts.png) + ## Incident contacts Incident contacts of an organization are alerted if anything abnormal is detected within the operations of an organization. diff --git a/docs/getting-started/dashboard/pit-recovery.mdx b/docs/documentation/platform/pit-recovery.mdx similarity index 100% rename from docs/getting-started/dashboard/pit-recovery.mdx rename to docs/documentation/platform/pit-recovery.mdx diff --git a/docs/getting-started/dashboard/project.mdx b/docs/documentation/platform/project.mdx similarity index 70% rename from docs/getting-started/dashboard/project.mdx rename to docs/documentation/platform/project.mdx index ce7df57e3..065835fb3 100644 --- a/docs/getting-started/dashboard/project.mdx +++ b/docs/documentation/platform/project.mdx @@ -25,16 +25,16 @@ In most cases, environment variables belong to specific environments: developmen ![project environment](../../images/project-environment.png) -### Personal/Shared scoping +### Personal overrides -Every environment variable is classified as either personal or shared. +Every environment variable value can be overriden with a custom value. -- A personal environment variable is one created by a user of a project to be available for that user only. -- A shared environment variable is one created by a user of a project to be available for other users of the project. +- An overriden value can only be read and accesssed by the user that overrode the original shared value. +- A (default) shared value can be read and accesssed by other users in a project. -You can toggle the classification of an environment variable by pressing on its settings: +You can turn overrides on/off by toggling the override/branch icon: -![project variable toggle open](../../images/project-envar-toggle-open.png) +![project variable toggle open](../../images/project-envar-override.png) ### Search @@ -42,12 +42,6 @@ You can search for any environment variable by its key. ![project search](../../images/project-search.png) -### Sort - -You can sort environment variables alphabetically by their keys. - -![project sort](../../images/project-sort.png) - ### Hide/Un-hide You can hide or un-hide the values of your environment variables. By default, the values are hidden for your privacy. diff --git a/docs/getting-started/dashboard/secret-versioning.mdx b/docs/documentation/platform/secret-versioning.mdx similarity index 100% rename from docs/getting-started/dashboard/secret-versioning.mdx rename to docs/documentation/platform/secret-versioning.mdx diff --git a/docs/getting-started/dashboard/token.mdx b/docs/documentation/platform/token.mdx similarity index 100% rename from docs/getting-started/dashboard/token.mdx rename to docs/documentation/platform/token.mdx diff --git a/docs/getting-started/features.mdx b/docs/getting-started/features.mdx deleted file mode 100644 index 9eb1d4faf..000000000 --- a/docs/getting-started/features.mdx +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Features" -description: "A non-exhaustive list of features that Infisical has to offer." ---- - -## Platform - -- Provision members access to organizations and projects. -- Manage secrets by adding, deleting, updating them across environments; search, sort, hide/un-hide, export/import them. -- Sync secrets to platforms via integrations to platforms like GitHub, Vercel, and Netlify. -- Rollback secrets to any point in time. -- Rollback each secrets to any version. -- Track actions through audit logs. - -## CLI - -The [CLI](/cli/overview) is used to inject environment variables into applications and infrastructure. - -- Inject environment variables. -- Inject environment variables into containers via service tokens for Docker. - -## SDKs - -[SDKs](/sdks/overview) enable apps to fetch back secrets using an [Infisical Token](/getting-started/dashboard/token) scoped to a project and environment. - -## Roadmap - -We're building the future of secret management, one that's comprehensive and accessible to all. Check out our [roadmap](https://www.notion.so/infisical/be2d2585a6694e40889b03aef96ea36b?v=5b19a8127d1a4060b54769567a8785fa). - -Interested in contributing? Check out the [guide](/contributing/overview). diff --git a/docs/getting-started/introduction.mdx b/docs/getting-started/introduction.mdx deleted file mode 100644 index cd5022083..000000000 --- a/docs/getting-started/introduction.mdx +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Introduction" -description: "What is Infisical?" ---- - -Infisical is an [open-source](https://opensource.com/resources/what-open-source), [end-to-end encrypted](https://en.wikipedia.org/wiki/End-to-end_encryption) secret manager that enables teams to easily manage and sync their environment variables. - -Start syncing environment variables with [Infisical Cloud](https://app.infisical.com) or learn how to [host Infisical](/self-hosting/overview) yourself. - - - - Tour Infisical in a few minutes. - - - Install the CLI to inject secrets into apps and infra. - - - Install an SDK into your app to fetch secrets. - - - Learn how to configure and deploy Infisical. - - - - - Explore integrations for Docker, AWS, Heroku, etc. - diff --git a/docs/getting-started/quickstart.mdx b/docs/getting-started/quickstart.mdx deleted file mode 100644 index 256ae8f85..000000000 --- a/docs/getting-started/quickstart.mdx +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: "Quickstart" -description: "Start managing your developer secrets and configs with Infisical in 10 minutes." ---- - -These examples demonstrate how to store and fetch environment variables from [Infisical Cloud](https://app.infisical.com) into your application. - -## Set up Infisical Cloud - -1. Login or create an account at `app.infisical.com`. -2. Create a new project. -3. Populate your environment variables as in the image below. - -![project quickstart](../images/project-quickstart.png) - -## Fetch Secrets for Your App - - - - - The Infisical CLI is platform-agnostic and enables you to inject environment variables into your app across many tech stacks and frameworks. - - ### Set up the CLI - - 1. Follow the instructions to [install our platform-agnostic CLI](/cli/overview). - - 2. Initialize Infisical for your project. - - ```bash - # move to your project - cd /path/to/project - - # initialize infisical - infisical init - ``` - - ### Start your app with environment variables injected - - ```bash - # inject environment variables into app - infisical run -- [your application start command] - ``` - - Your app should now be running with the environment variables injected. - - Check out our [integrations](/integrations/overview) for injecting environment variables into frameworks and platforms like Docker. - - - - [Infisical SDKs](/sdks/overview) let your app fetch back secrets using an [Infisical Token](/getting-started/dashboard/token) that is scoped to a project and environment in Infisical. In this example, we demonstrate how to use the [Node SDK](/sdks/languages/node). - - ### Obtain an [Infisical Token](/getting-started/dashboard/token) - - Head to your project settings to create a token scoped to the project and environment you wish to fetch secrets from. - - ![token add](../images/project-token-add.png) - - ### Install the SDK - - ```bash - npm install infisical-node --save - ``` - - ### Initialize the Infisical client - - ```js - await infisical.connect({ - token: "your_infisical_token", - }); - ``` - - ### Get a value - - ```js - const value = infisical.get("SOME_KEY"); - ``` - - ### Example with Express - - ```js - const express = require("express"); - const port = 3000; - const infisical = require("infisical-node"); - - const main = async () => { - await infisical.connect({ - token: "st.xxx.xxx", - }); - - // your application logic - - app.get("/", (req, res) => { - res.send(`Howdy, ${infisical.get("NAME")}!`); - }); - - app.listen(port, async () => { - console.log(`App listening on port ${port}`); - }); - }; - ``` - - - We do not recommend hardcoding your [Infisical - Token](/getting-started/dashboard/token). Setting it as an environment - variable would be best. - - - - Check out our [SDKs](/sdks/overview) for other language SDKs. - - - diff --git a/docs/images/authentication-google-redirect.png b/docs/images/authentication-google-redirect.png new file mode 100644 index 000000000..7c4a2bff6 Binary files /dev/null and b/docs/images/authentication-google-redirect.png differ diff --git a/docs/images/dashboard-name-modal-organization.png b/docs/images/dashboard-name-modal-organization.png index 7fe84675e..59145d21b 100644 Binary files a/docs/images/dashboard-name-modal-organization.png and b/docs/images/dashboard-name-modal-organization.png differ diff --git a/docs/images/dashboard-secrets-overview.png b/docs/images/dashboard-secrets-overview.png new file mode 100644 index 000000000..68b31de72 Binary files /dev/null and b/docs/images/dashboard-secrets-overview.png differ diff --git a/docs/images/dashboard.png b/docs/images/dashboard.png index 961b53587..2188debfc 100644 Binary files a/docs/images/dashboard.png and b/docs/images/dashboard.png differ diff --git a/docs/images/do-k8-install-btn.png b/docs/images/do-k8-install-btn.png new file mode 100644 index 000000000..79b286a48 Binary files /dev/null and b/docs/images/do-k8-install-btn.png differ diff --git a/docs/images/email-gmail-app-access.png b/docs/images/email-gmail-app-access.png new file mode 100644 index 000000000..43f0b63a4 Binary files /dev/null and b/docs/images/email-gmail-app-access.png differ diff --git a/docs/images/integrations-checkly-auth.png b/docs/images/integrations-checkly-auth.png new file mode 100644 index 000000000..b6299aefe Binary files /dev/null and b/docs/images/integrations-checkly-auth.png differ diff --git a/docs/images/integrations-checkly-create.png b/docs/images/integrations-checkly-create.png new file mode 100644 index 000000000..271ca1a9c Binary files /dev/null and b/docs/images/integrations-checkly-create.png differ diff --git a/docs/images/integrations-checkly-dashboard.png b/docs/images/integrations-checkly-dashboard.png new file mode 100644 index 000000000..d600ecc23 Binary files /dev/null and b/docs/images/integrations-checkly-dashboard.png differ diff --git a/docs/images/integrations-checkly-token.png b/docs/images/integrations-checkly-token.png new file mode 100644 index 000000000..80f7bcf19 Binary files /dev/null and b/docs/images/integrations-checkly-token.png differ diff --git a/docs/images/integrations-checkly.png b/docs/images/integrations-checkly.png new file mode 100644 index 000000000..4734d5257 Binary files /dev/null and b/docs/images/integrations-checkly.png differ diff --git a/docs/images/integrations-hashicorp-vault-access-1.png b/docs/images/integrations-hashicorp-vault-access-1.png new file mode 100644 index 000000000..367386709 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-access-1.png differ diff --git a/docs/images/integrations-hashicorp-vault-access-2.png b/docs/images/integrations-hashicorp-vault-access-2.png new file mode 100644 index 000000000..80de8df26 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-access-2.png differ diff --git a/docs/images/integrations-hashicorp-vault-access-3.png b/docs/images/integrations-hashicorp-vault-access-3.png new file mode 100644 index 000000000..d51142541 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-access-3.png differ diff --git a/docs/images/integrations-hashicorp-vault-auth.png b/docs/images/integrations-hashicorp-vault-auth.png new file mode 100644 index 000000000..b587777f9 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-auth.png differ diff --git a/docs/images/integrations-hashicorp-vault-cluster-url.png b/docs/images/integrations-hashicorp-vault-cluster-url.png new file mode 100644 index 000000000..619764b54 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-cluster-url.png differ diff --git a/docs/images/integrations-hashicorp-vault-create.png b/docs/images/integrations-hashicorp-vault-create.png new file mode 100644 index 000000000..7fdef0d4a Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-create.png differ diff --git a/docs/images/integrations-hashicorp-vault-engine-1.png b/docs/images/integrations-hashicorp-vault-engine-1.png new file mode 100644 index 000000000..a65870b44 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-engine-1.png differ diff --git a/docs/images/integrations-hashicorp-vault-engine-2.png b/docs/images/integrations-hashicorp-vault-engine-2.png new file mode 100644 index 000000000..34b03768f Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-engine-2.png differ diff --git a/docs/images/integrations-hashicorp-vault-engine-3.png b/docs/images/integrations-hashicorp-vault-engine-3.png new file mode 100644 index 000000000..624fdc574 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-engine-3.png differ diff --git a/docs/images/integrations-hashicorp-vault-policy-1.png b/docs/images/integrations-hashicorp-vault-policy-1.png new file mode 100644 index 000000000..e2a77654a Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-policy-1.png differ diff --git a/docs/images/integrations-hashicorp-vault-policy-2.png b/docs/images/integrations-hashicorp-vault-policy-2.png new file mode 100644 index 000000000..719659014 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-policy-2.png differ diff --git a/docs/images/integrations-hashicorp-vault-policy-3.png b/docs/images/integrations-hashicorp-vault-policy-3.png new file mode 100644 index 000000000..76fe2de35 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-policy-3.png differ diff --git a/docs/images/integrations-hashicorp-vault-shell.png b/docs/images/integrations-hashicorp-vault-shell.png new file mode 100644 index 000000000..7d63bde40 Binary files /dev/null and b/docs/images/integrations-hashicorp-vault-shell.png differ diff --git a/docs/images/integrations-hashicorp-vault.png b/docs/images/integrations-hashicorp-vault.png new file mode 100644 index 000000000..e556ffc6b Binary files /dev/null and b/docs/images/integrations-hashicorp-vault.png differ diff --git a/docs/images/integrations-railway-authorization.png b/docs/images/integrations-railway-authorization.png new file mode 100644 index 000000000..8608ea6d1 Binary files /dev/null and b/docs/images/integrations-railway-authorization.png differ diff --git a/docs/images/integrations-railway-create.png b/docs/images/integrations-railway-create.png new file mode 100644 index 000000000..548c06c5e Binary files /dev/null and b/docs/images/integrations-railway-create.png differ diff --git a/docs/images/integrations-railway-dashboard.png b/docs/images/integrations-railway-dashboard.png new file mode 100644 index 000000000..0d6b66754 Binary files /dev/null and b/docs/images/integrations-railway-dashboard.png differ diff --git a/docs/images/integrations-railway-token.png b/docs/images/integrations-railway-token.png new file mode 100644 index 000000000..d414289e9 Binary files /dev/null and b/docs/images/integrations-railway-token.png differ diff --git a/docs/images/integrations-railway.png b/docs/images/integrations-railway.png new file mode 100644 index 000000000..0bde672d2 Binary files /dev/null and b/docs/images/integrations-railway.png differ diff --git a/docs/images/integrations-supabase-authorization.png b/docs/images/integrations-supabase-authorization.png new file mode 100644 index 000000000..d6daab30c Binary files /dev/null and b/docs/images/integrations-supabase-authorization.png differ diff --git a/docs/images/integrations-supabase-create.png b/docs/images/integrations-supabase-create.png new file mode 100644 index 000000000..b6c2cd35d Binary files /dev/null and b/docs/images/integrations-supabase-create.png differ diff --git a/docs/images/integrations-supabase-dashboard.png b/docs/images/integrations-supabase-dashboard.png new file mode 100644 index 000000000..4908cfc5a Binary files /dev/null and b/docs/images/integrations-supabase-dashboard.png differ diff --git a/docs/images/integrations-supabase-token.png b/docs/images/integrations-supabase-token.png new file mode 100644 index 000000000..00a3c0b20 Binary files /dev/null and b/docs/images/integrations-supabase-token.png differ diff --git a/docs/images/integrations-supabase.png b/docs/images/integrations-supabase.png new file mode 100644 index 000000000..60808a232 Binary files /dev/null and b/docs/images/integrations-supabase.png differ diff --git a/docs/images/integrations.png b/docs/images/integrations.png index 44a8269dd..368a10c37 100644 Binary files a/docs/images/integrations.png and b/docs/images/integrations.png differ diff --git a/docs/images/organization-ic.png b/docs/images/organization-ic.png index d94f4061a..e45ad2d82 100644 Binary files a/docs/images/organization-ic.png and b/docs/images/organization-ic.png differ diff --git a/docs/images/organization-members.png b/docs/images/organization-members.png index 321808d51..90344b698 100644 Binary files a/docs/images/organization-members.png and b/docs/images/organization-members.png differ diff --git a/docs/images/organization-service-accounts.png b/docs/images/organization-service-accounts.png new file mode 100644 index 000000000..f48e848d3 Binary files /dev/null and b/docs/images/organization-service-accounts.png differ diff --git a/docs/images/organization.png b/docs/images/organization.png index 473c31db0..488d6c4cf 100644 Binary files a/docs/images/organization.png and b/docs/images/organization.png differ diff --git a/docs/images/pit-commits.png b/docs/images/pit-commits.png index 19cfa4976..22599311a 100644 Binary files a/docs/images/pit-commits.png and b/docs/images/pit-commits.png differ diff --git a/docs/images/pit-snapshot.png b/docs/images/pit-snapshot.png index 7e790e875..b7e913108 100644 Binary files a/docs/images/pit-snapshot.png and b/docs/images/pit-snapshot.png differ diff --git a/docs/images/pit-snapshots.png b/docs/images/pit-snapshots.png index f22231648..aa1cd52d3 100644 Binary files a/docs/images/pit-snapshots.png and b/docs/images/pit-snapshots.png differ diff --git a/docs/images/project-download.png b/docs/images/project-download.png index 8750b6cd3..00b02d9bf 100644 Binary files a/docs/images/project-download.png and b/docs/images/project-download.png differ diff --git a/docs/images/project-drag-drop.png b/docs/images/project-drag-drop.png index a283faec6..7ae0ed718 100644 Binary files a/docs/images/project-drag-drop.png and b/docs/images/project-drag-drop.png differ diff --git a/docs/images/project-envar-override.png b/docs/images/project-envar-override.png new file mode 100644 index 000000000..d9e01c8fd Binary files /dev/null and b/docs/images/project-envar-override.png differ diff --git a/docs/images/project-envar-toggle-open.png b/docs/images/project-envar-toggle-open.png deleted file mode 100644 index 297299454..000000000 Binary files a/docs/images/project-envar-toggle-open.png and /dev/null differ diff --git a/docs/images/project-environment.png b/docs/images/project-environment.png index 5b316511c..e2e0d2959 100644 Binary files a/docs/images/project-environment.png and b/docs/images/project-environment.png differ diff --git a/docs/images/project-hide.png b/docs/images/project-hide.png index 69fdb13f0..61aed0bee 100644 Binary files a/docs/images/project-hide.png and b/docs/images/project-hide.png differ diff --git a/docs/images/project-members.png b/docs/images/project-members.png new file mode 100644 index 000000000..87b2a7ee4 Binary files /dev/null and b/docs/images/project-members.png differ diff --git a/docs/images/project-quickstart.png b/docs/images/project-quickstart.png index 6d8d7f664..9a9660d1d 100644 Binary files a/docs/images/project-quickstart.png and b/docs/images/project-quickstart.png differ diff --git a/docs/images/project-search.png b/docs/images/project-search.png index 7388b34ce..bafc0b2c3 100644 Binary files a/docs/images/project-search.png and b/docs/images/project-search.png differ diff --git a/docs/images/project-settings-blind-indices.png b/docs/images/project-settings-blind-indices.png new file mode 100644 index 000000000..d52936ffe Binary files /dev/null and b/docs/images/project-settings-blind-indices.png differ diff --git a/docs/images/project-sort.png b/docs/images/project-sort.png deleted file mode 100644 index 134adc8d5..000000000 Binary files a/docs/images/project-sort.png and /dev/null differ diff --git a/docs/images/secret-versioning.png b/docs/images/secret-versioning.png index ec1734289..96dbfde41 100644 Binary files a/docs/images/secret-versioning.png and b/docs/images/secret-versioning.png differ diff --git a/docs/images/spring-maven-debug-1.png b/docs/images/spring-maven-debug-1.png new file mode 100644 index 000000000..8fc5f5f7d Binary files /dev/null and b/docs/images/spring-maven-debug-1.png differ diff --git a/docs/images/spring-maven-debug-2.png b/docs/images/spring-maven-debug-2.png new file mode 100644 index 000000000..b363ebd15 Binary files /dev/null and b/docs/images/spring-maven-debug-2.png differ diff --git a/docs/images/spring-maven-debug-3.png b/docs/images/spring-maven-debug-3.png new file mode 100644 index 000000000..b21fc722f Binary files /dev/null and b/docs/images/spring-maven-debug-3.png differ diff --git a/docs/images/spring-maven-debug-4.png b/docs/images/spring-maven-debug-4.png new file mode 100644 index 000000000..1d28a08bb Binary files /dev/null and b/docs/images/spring-maven-debug-4.png differ diff --git a/docs/images/spring-maven-debug-5.png b/docs/images/spring-maven-debug-5.png new file mode 100644 index 000000000..89f0401f8 Binary files /dev/null and b/docs/images/spring-maven-debug-5.png differ diff --git a/docs/integrations/cicd/circleci.mdx b/docs/integrations/cicd/circleci.mdx index 7b9298f4b..58b8ae3ff 100644 --- a/docs/integrations/cicd/circleci.mdx +++ b/docs/integrations/cicd/circleci.mdx @@ -1,6 +1,6 @@ --- title: "CircleCI" -description: "How to automatically sync secrets from Infisical into your CircleCI project." +description: "How to sync secrets from Infisical to CircleCI" --- Prerequisites: diff --git a/docs/integrations/cicd/githubactions.mdx b/docs/integrations/cicd/githubactions.mdx index 8f93d8162..5ecf68d03 100644 --- a/docs/integrations/cicd/githubactions.mdx +++ b/docs/integrations/cicd/githubactions.mdx @@ -1,6 +1,6 @@ --- title: "GitHub Actions" -description: "How to automatically sync secrets from Infisical into your GitHub Actions." +description: "How to sync secrets from Infisical to GitHub Actions" --- diff --git a/docs/integrations/cicd/gitlab.mdx b/docs/integrations/cicd/gitlab.mdx index f52afe99f..742eee673 100644 --- a/docs/integrations/cicd/gitlab.mdx +++ b/docs/integrations/cicd/gitlab.mdx @@ -1,6 +1,6 @@ --- title: "GitLab" -description: "How to automatically sync secrets from Infisical into GitLab." +description: "How to sync secrets from Infisical to GitLab" --- Prerequisites: @@ -37,7 +37,7 @@ Select which Infisical environment secrets you want to sync to which GitLab repo ## Generate service token -Generate an [Infisical Token](../../getting-started/dashboard/token) for the specific project and environment in Infisical. +Generate an [Infisical Token](/documentation/platform/token) for the specific project and environment in Infisical. ## Set the Infisical Token in Gitlab diff --git a/docs/integrations/cicd/travisci.mdx b/docs/integrations/cicd/travisci.mdx index 5509ffc7a..79737a2d8 100644 --- a/docs/integrations/cicd/travisci.mdx +++ b/docs/integrations/cicd/travisci.mdx @@ -1,6 +1,6 @@ --- title: "Travis CI" -description: "How to automatically sync secrets from Infisical to your Travis CI repository." +description: "How to sync secrets from Infisical to Travis CI" --- Prerequisites: diff --git a/docs/integrations/cloud/aws-parameter-store.mdx b/docs/integrations/cloud/aws-parameter-store.mdx index 1bb6c40c9..63fd1e1c6 100644 --- a/docs/integrations/cloud/aws-parameter-store.mdx +++ b/docs/integrations/cloud/aws-parameter-store.mdx @@ -1,6 +1,6 @@ --- title: "AWS Parameter Store" -description: "How to automatically sync secrets from Infisical to your AWS Parameter Store." +description: "How to sync secrets from Infisical to AWS Parameter Store" --- Prerequisites: diff --git a/docs/integrations/cloud/aws-secret-manager.mdx b/docs/integrations/cloud/aws-secret-manager.mdx index 9b282c527..a798ae820 100644 --- a/docs/integrations/cloud/aws-secret-manager.mdx +++ b/docs/integrations/cloud/aws-secret-manager.mdx @@ -1,6 +1,6 @@ --- title: "AWS Secret Manager" -description: "How to automatically sync secrets from Infisical to your AWS Secret Manager." +description: "How to sync secrets from Infisical to AWS Secret Manager" --- Prerequisites: diff --git a/docs/integrations/cloud/azure-key-vault.mdx b/docs/integrations/cloud/azure-key-vault.mdx index 3b23f4d52..90c630666 100644 --- a/docs/integrations/cloud/azure-key-vault.mdx +++ b/docs/integrations/cloud/azure-key-vault.mdx @@ -1,6 +1,6 @@ --- title: "Azure Key Vault" -description: "How to automatically sync secrets from Infisical into your Azure Key Vault." +description: "How to sync secrets from Infisical to Azure Key Vault" --- Prerequisites: diff --git a/docs/integrations/cloud/checkly.mdx b/docs/integrations/cloud/checkly.mdx new file mode 100644 index 000000000..54b2e7ac5 --- /dev/null +++ b/docs/integrations/cloud/checkly.mdx @@ -0,0 +1,37 @@ +--- +title: "Checkly" +description: "How to sync secrets from Infisical to Checkly" +--- + +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 Checkly API Key + +Obtain a Checkly API Key in User Settings > API Keys. + +![integrations checkly dashboard](../../images/integrations-checkly-dashboard.png) +![integrations checkly token](../../images/integrations-checkly-token.png) + +Press on the Checkly tile and input your Checkly API Key to grant Infisical access to your Checkly account. + +![integrations checkly authorization](../../images/integrations-checkly-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 Checkly press create integration to start syncing secrets. + +![integrations checkly](../../images/integrations-checkly-create.png) +![integrations checkly](../../images/integrations-checkly.png) \ No newline at end of file diff --git a/docs/integrations/cloud/flyio.mdx b/docs/integrations/cloud/flyio.mdx index 2a1dd7e2c..283c54176 100644 --- a/docs/integrations/cloud/flyio.mdx +++ b/docs/integrations/cloud/flyio.mdx @@ -1,6 +1,6 @@ --- title: "Fly.io" -description: "How to automatically sync secrets from Infisical into your Fly.io project." +description: "How to sync secrets from Infisical to Fly.io" --- Prerequisites: @@ -11,7 +11,7 @@ Prerequisites: ![integrations](../../images/integrations.png) -## Authorize Infisical for Fly.io +## Enter your Fly.io Access Token Obtain a Fly.io access token in Access Tokens diff --git a/docs/integrations/cloud/hashicorp-vault.mdx b/docs/integrations/cloud/hashicorp-vault.mdx new file mode 100644 index 000000000..936a16941 --- /dev/null +++ b/docs/integrations/cloud/hashicorp-vault.mdx @@ -0,0 +1,161 @@ +--- +title: "HashiCorp Vault" +description: "How to sync secrets from Infisical to HashiCorp Vault" +--- + + + Infisical connects to Vault via the AppRole auth method. + + Currently, each Infisical project can only point and sync secrets to one Vault cluster / namespace + but with unlimited integrations to different paths within it. + + This tutorial makes use of Vault's UI but, in principle, instructions can executed via + Vault CLI or API call. + + Lastly, you should note that we provide a simple use-case and, in practice, you should adapt and extend it to your own Vault use-case and follow best practices, for instance when defining fine-grained ACL policies. + + +Prerequisites: + +- Set up and add envars to [Infisical Cloud](https://app.infisical.com) +- Have experience with [HashiCorp Vault](https://www.vaultproject.io/). + +## Navigate to your project's integrations tab + +![integrations](../../images/integrations.png) + +## Prepare Vault + +This section mirrors the latter parts of the [Vault quickstart](https://developer.hashicorp.com/vault/tutorials/cloud/getting-started-intro) provided by HashiCorp and uses sample names/values for demonstration. + +To begin, navigate to the cluster / namespace that you want to sync secrets to in Vault; we'll use the default `admin` namespace (in practice, we recommend creating a namespace and not using the default `admin` namespace). + +### Enable KV Secrets Engine + +In Secrets, enable a KV Secrets Engine at a path for Infisical to sync secrets to; we'll use the path `kv`. + +![integrations hashicorp vault secrets engine](../../images/integrations-hashicorp-vault-engine-1.png) +![integrations hashicorp vault secrets engine](../../images/integrations-hashicorp-vault-engine-2.png) +![integrations hashicorp vault secrets engine](../../images/integrations-hashicorp-vault-engine-3.png) + +### Enable the AppRole auth method + +In Access > Auth Methods, enable the AppRole auth method. + +![integrations hashicorp vault access](../../images/integrations-hashicorp-vault-access-1.png) +![integrations hashicorp vault access](../../images/integrations-hashicorp-vault-access-2.png) +![integrations hashicorp vault access](../../images/integrations-hashicorp-vault-access-3.png) + +### Create an ACL Policy + +Now in Policies, create a new ACL policy scoped to the path(s) you wish Infisical to be able to sync secrets to. + +We'll call the policy `test` and have it grant access to the `dev` path in the KV Secrets Engine where we will be syncing secrets to from Infisical. + +```console +path "kv/data/dev" { + capabilities = [ "create", "read", "update" ] +} + +path "sys/namespaces/*" { + capabilities = [ "create", "read", "update", "delete", "list" ] +} +``` + + + `kv` comes from the path of the KV Secrets Engine that we enabled and `dev` is the chosen path within it + that we want to sync secrets to. + + +![integrations hashicorp vault policy](../../images/integrations-hashicorp-vault-policy-1.png) +![integrations hashicorp vault policy](../../images/integrations-hashicorp-vault-policy-2.png) +![integrations hashicorp vault policy](../../images/integrations-hashicorp-vault-policy-3.png) + +### Create a role with the policy attached + +We now create a `infisical` role with the generated token's time-to-live (TTL) set to 1 hour and can be renewed for up to 4 hours from the time of its creation. + +1. Click the Vault CLI shell icon (`>_`) to open a command shell in the browser. + +![integrations hashicorp vault shell](../../images/integrations-hashicorp-vault-shell.png) + +2. Copy the command below. + +```console +vault write auth/approle/role/infisical token_policies="test" token_ttl=1h token_max_ttl=4h +``` + +3. Paste the command into the command shell in the browser and press the enter button. + +### Generate a RoleID and SecretID + +Finally, we need to generate a **RoleID** and **SecretID** (like a username and password) that Infisical can use +to authenticate with Vault. + +1. Click the Vault CLI shell icon (>_) again to open a command shell. + +2. Read the RoleID. + +```console +vault read auth/approle/role/infisical/role-id +``` + +Example output: + +```console +Key Value +role_id b6ccdcca-183b-ce9c-6b98-b556b9a0edb9 +``` + +3. Generate a new SecretID of the `infisical` role. + +```console +vault write -force auth/approle/role/infisical/secret-id +``` + +Example output: + + +```console +Key Value +secret_id 735a47cc-7a98-77cc-0128-12b1e96a4157 +secret_id_accessor 3ab305d1-1eab-df4b-4079-ef7135635c49 +...snip... +``` + +Great. We're now ready to connect Infisical to Vault! + +## Enter your Vault instance and authentication details + +Back in Infisical, press on the HashiCorp Vault tile and input your Vault instance and `infisical` role RoleID and SecretID. + +![integrations hashicorp vault authorization](../../images/integrations-hashicorp-vault-auth.png) + +For additional details on each field: + +- Vault Cluster URL: The address of your cluster, either HCP or self-hosted. + +If using HCP, you can copy your Cluster URL in the Cluster Overview: + +![integrations hashicorp vault cluster URL](../../images/integrations-hashicorp-vault-cluster-url.png) + +- Vault Namespace: The Vault namespace you wish to connect to. +- Vault RoleID: The RoleID previously created for the `infisical` role. +- Vault SecretID: The SecretID previously created for the `infisical` role. + +## Start integration + +Select which Infisical environment secrets you want to sync to Vault. + +For additional details on each field: + +- Vault KV Secrets Engine Path: the path at which you enabled the intended KV Secrets Engine; in this demonstration, we used `kv`. +- Vault Secret(s) Path: the path in the KV Secrets Engine that you wish to sync secrets to. + +Press create integration to start syncing secrets to Vault. + +![integrations hashicorp vault](../../images/integrations-hashicorp-vault-create.png) +![integrations hashicorp vault](../../images/integrations-hashicorp-vault.png) + + + diff --git a/docs/integrations/cloud/heroku.mdx b/docs/integrations/cloud/heroku.mdx index 9d0c26789..f3c58d27e 100644 --- a/docs/integrations/cloud/heroku.mdx +++ b/docs/integrations/cloud/heroku.mdx @@ -1,6 +1,6 @@ --- title: "Heroku" -description: "How to automatically sync secrets from Infisical into your Heroku project." +description: "How to sync secrets from Infisical to Heroku" --- Prerequisites: diff --git a/docs/integrations/cloud/netlify.mdx b/docs/integrations/cloud/netlify.mdx index b6dc36ba0..acd037417 100644 --- a/docs/integrations/cloud/netlify.mdx +++ b/docs/integrations/cloud/netlify.mdx @@ -1,6 +1,6 @@ --- title: "Netlify" -description: "How to automatically sync secrets from Infisical into your Netlify project." +description: "How to sync secrets from Infisical to Netlify" --- diff --git a/docs/integrations/cloud/railway.mdx b/docs/integrations/cloud/railway.mdx new file mode 100644 index 000000000..e19cfb626 --- /dev/null +++ b/docs/integrations/cloud/railway.mdx @@ -0,0 +1,54 @@ +--- +title: "Railway" +description: "How to sync secrets from Infisical to Railway" +--- + +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 Railway API Token + +Obtain a Railway API Token in your Railway [Account Settings > Tokens](https://railway.app/account/tokens). + +![integrations railway dashboard](../../images/integrations-railway-dashboard.png) +![integrations railway token](../../images/integrations-railway-token.png) + + + If this is your first time creating a Railway API token, then you'll be prompted to join + Railway's Private Boarding Beta program on the Railway Account Settings > Tokens page. + + Note that Railway project tokens will not work for this integration since they don't work with + Railway's Public API. + + +Press on the Railway tile and input your Railway API Key to grant Infisical access to your Railway account. + +![integrations railway authorization](../../images/integrations-railway-authorization.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 Railway project and environment (and optionally service). Lastly, press create integration to start syncing secrets to Railway. + +![integrations create railway](../../images/integrations-railway-create.png) + + + Infisical integrates with both Railway's [shared variables](https://blog.railway.app/p/shared-variables-release) at the project environment level as well as service variables at the service level. + + To sync secrets to a specific service in a project, you can select a service from the Railway Service dropdown; otherwise, leaving it empty will sync secrets to the shared variables of that project. + + +![integrations railway](../../images/integrations-railway.png) + diff --git a/docs/integrations/cloud/render.mdx b/docs/integrations/cloud/render.mdx index 95890e92a..290e39012 100644 --- a/docs/integrations/cloud/render.mdx +++ b/docs/integrations/cloud/render.mdx @@ -1,6 +1,6 @@ --- title: "Render" -description: "How to automatically sync secrets from Infisical into your Render project." +description: "How to sync secrets from Infisical to Render" --- Prerequisites: diff --git a/docs/integrations/cloud/supabase.mdx b/docs/integrations/cloud/supabase.mdx new file mode 100644 index 000000000..14c787f75 --- /dev/null +++ b/docs/integrations/cloud/supabase.mdx @@ -0,0 +1,44 @@ +--- +title: "Supabase" +description: "How to sync secrets from Infisical to Supabase" +--- + + + The Supabase integration is useful if your Supabase project uses sensitive-information such as [environment variables in edge functions](https://supabase.com/docs/guides/functions/secrets). + + Synced envars can be accessed in edge functions using Deno's built-in handler: `Deno.env.get(MY_SECRET_NAME)`. + + +Prerequisites: + +- Have an account and project set up at [Supabase](https://supabase.com/) +- 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 Supabase Access Token + +Obtain a Supabase Access Token in your Supabase [Account > Access Tokens](https://app.supabase.com/account/tokens). +![integrations supabase dashboard](../../images/integrations-supabase-dashboard.png) +![integrations supabase token](../../images/integrations-supabase-token.png) + +Press on the Supabase tile and input your Supabase Access Token to grant Infisical access to your Supabase account. + +![integrations supabase authorization](../../images/integrations-supabase-authorization.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 Supabase project. Lastly, press create integration to start syncing secrets to Supabase. + +![integrations supabase create](../../images/integrations-supabase-create.png) + +![integrations supabase](../../images/integrations-supabase.png) \ No newline at end of file diff --git a/docs/integrations/cloud/vercel.mdx b/docs/integrations/cloud/vercel.mdx index af20c60cf..fb265ec98 100644 --- a/docs/integrations/cloud/vercel.mdx +++ b/docs/integrations/cloud/vercel.mdx @@ -1,6 +1,6 @@ --- title: "Vercel" -description: "How to automatically sync secrets from Infisical into your Vercel project." +description: "How to sync secrets from Infisical to Vercel" --- Prerequisites: diff --git a/docs/integrations/frameworks/spring-boot-maven.mdx b/docs/integrations/frameworks/spring-boot-maven.mdx new file mode 100644 index 000000000..768e819cf --- /dev/null +++ b/docs/integrations/frameworks/spring-boot-maven.mdx @@ -0,0 +1,80 @@ +--- +title: "Spring Boot with Maven" +description: "How to use Infisical to inject environment variables into Java Spring Boot" +--- + +Prerequisites: + +- Set up and add your environment variables to [Infisical Cloud](https://app.infisical.com) +- [Install the CLI](/cli/overview) + +## Initialize Infisical +In order for Infisical to know which secrets to fetch, you'll need to first initialize Infisical at the root of your project. + +```bash +# navigate to the root of your of your project +cd /path/to/project + +# then initialize Infisical +infisical init +``` + + +## Start your application with Maven wrapper +To pass in Infisical secrets into your application, we will utilize the Infisical CLI to inject the secrets into the Maven wrapper executable, which is used to launch your application. +The Maven wrapper executable should already be present in the root directory of your project. + +```bash +infisical run -- ./mvnw spring-boot:run --quiet +``` + +#### Accessing injected secrets +```java example.java + ... + import org.springframework.core.env.Environment; + + @SpringBootApplication + public class DemoApplication { + @Autowired + private Environment env; + + @Bean + public void someMethod() { + System.out.println(env.getProperty("SOME_SECRET_NAME")); + }; + } +``` + + +## Debugging with secrets +During the process of debugging your code, it may be necessary to have certain environment variables available. To inject these variables for the purpose of debugging, please follow the instructions provided below. +Note that these instructions are currently only available for IntelliJ. + +**Step 1:** On the main tool bar, choose Edit Configuration + + + +**Step 2:** Click the plus icon + + + +**Step 3:** Select Shell Script + + + +**Step 4:** Choose Script Text and then paste in the command below. + + + +``` +infisical run -- ./mvnw spring-boot:run -Dspring-boot.run.jvmArguments="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=*:5005" +``` + +**Step 5:** When you need to run a block of code in debug mode, select the Infisical script + + + + + + + diff --git a/docs/integrations/frameworks/terraform.mdx b/docs/integrations/frameworks/terraform.mdx index 7161ec586..0826a833e 100644 --- a/docs/integrations/frameworks/terraform.mdx +++ b/docs/integrations/frameworks/terraform.mdx @@ -1,34 +1,91 @@ --- title: "Terraform" -description: "How to use Infisical to inject environment variables and secrets into terraform." +description: "Fetch Secrets From Infisical With Terraform" --- -Prerequisites: +This guide provides step-by-step guidance on how to fetch secrets from Infisical using Terraform. -- Set up and add envars to [Infisical Cloud](https://app.infisical.com) -- [Install the CLI](/cli/overview) +## Prerequisites -## Initialize Infisical for your [Terraform](https://www.terraform.io/) project +- Basic understanding of Terraform +- Install [Terraform](https://www.terraform.io/downloads.html) -```bash -# navigate to the root of your of your project -cd /path/to/project +## Steps -# then initialize Infisical -infisical init +### 1. Define Required Providers + +Specify `infisical` in the `required_providers` block within the `terraform` block of your configuration file. If you would like to use a specific version of the provider, uncomment and replace `` with the version of the Infisical provider that you want to use. + +```hcl main.tf +terraform { + required_providers { + infisical = { + # version = + source = "infisical/infisical" + } + } +} ``` -## Run terraform as usual but with Infisical +### 2. Configure the Infisical Provider -```bash -infisical run -- +Set up the Infisical provider by specifying the `host` and `service_token`. Replace `<>` in `service_token` with your actual token. The `host` is only required if you are using a self-hosted instance of Infisical. -# Example -infisical run -- terraform plan +```hcl main.tf +provider "infisical" { + host = "https://app.infisical.com" # Only required if using self hosted instance of Infisical, default is https://app.infisical.com + service_token = "<>" # Get token https://infisical.com/docs/documentation/platform/token +} ``` - - To inject any arbitrary variable to terraform, you have - to prefix them with `TF_VAR`. Read more about that - [here](https://developer.hashicorp.com/terraform/cli/config/environment-variables#tf_var_name). - + + It is recommended to use Terraform variables to pass your service token dynamically to avoid hard coding it + + +### 3. Fetch Infisical Secrets + +Use the `infisical_secrets` data source to fetch your secrets. This is defined with an empty block `{}` as the provider automatically fetches all secrets associated with your service token. + +```hcl main.tf +data "infisical_secrets" "my-secrets" {} +``` + +### 4. Define Outputs + +As an example, we are going to output your fetched secrets. Replace `SECRET-NAME` with the actual name of your secret. + +For a single secret: + +```hcl main.tf +output "single-secret" { + value = data.infisical_secrets.my-secrets.secrets["SECRET-NAME"] +} +``` + +For all secrets: + +```hcl +output "all-secrets" { + value = data.infisical_secrets.my-secrets.secrets +} +``` + +### 5. Run Terraform + +Once your configuration is complete, initialize your Terraform working directory: + +```bash +$ terraform init +``` + +Then, run the plan command to view the fetched secrets: + +```bash +$ terraform plan +``` + +Terraform will now fetch your secrets from Infisical and display them as output according to your configuration. + +## Conclusion + +You have now successfully set up and used the Infisical provider with Terraform to fetch secrets. For more information, visit the [Infisical documentation](https://registry.terraform.io/providers/Infisical/infisical/latest/docs). diff --git a/docs/integrations/overview.mdx b/docs/integrations/overview.mdx index 15e5698c1..79db492ea 100644 --- a/docs/integrations/overview.mdx +++ b/docs/integrations/overview.mdx @@ -5,7 +5,7 @@ description: "How to use Infisical to inject secrets and configs into various 3- Integrations allow environment variables to be synced from Infisical into your local development workflow, CI/CD pipelines, and production infrastructure. -Missing an integration? Throw in a [request](https://github.com/Infisical/infisical/issues). +Missing an integration? [Throw in a request](https://github.com/Infisical/infisical/issues). | Integration | Type | Status | | -------------------------------------------------------------- | --------- | ----------- | @@ -18,7 +18,11 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi | [Vercel](/integrations/cloud/vercel) | Cloud | Available | | [Netlify](/integrations/cloud/netlify) | Cloud | Available | | [Render](/integrations/cloud/render) | Cloud | Available | +| [Railway](/integrations/cloud/railway) | Cloud | Available | | [Fly.io](/integrations/cloud/flyio) | Cloud | Available | +| [Supabase](/integrations/cloud/supabase) | 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 | @@ -41,7 +45,5 @@ Missing an integration? Throw in a [request](https://github.com/Infisical/infisi | [Flask](/integrations/frameworks/flask) | Framework | Available | | [Laravel](/integrations/frameworks/laravel) | Framework | Available | | [Ruby on Rails](/integrations/frameworks/rails) | Framework | Available | -| GCP | Cloud | Coming soon | -| DigitalOcean | Cloud | Coming soon | -| GitHub Actions | CI/CD | Coming soon | +| GCP Secret Manager | Cloud | Coming soon | | Jenkins | CI/CD | Coming soon | diff --git a/docs/integrations/platforms/docker-compose.mdx b/docs/integrations/platforms/docker-compose.mdx index e030869e3..e768b0e84 100644 --- a/docs/integrations/platforms/docker-compose.mdx +++ b/docs/integrations/platforms/docker-compose.mdx @@ -13,7 +13,7 @@ Follow this [guide](./docker) to configure the Infisical CLI for each service th ## Generate Infisical Tokens -Generate a unique [Infisical Token](https://infisical.com/docs/getting-started/dashboard/token) for each service. +Generate a unique [Infisical Token](/documentation/platform/token) for each service. ## Add Infisical Tokens to your Docker Compose file diff --git a/docs/integrations/platforms/docker.mdx b/docs/integrations/platforms/docker.mdx index a19562a99..629a81317 100644 --- a/docs/integrations/platforms/docker.mdx +++ b/docs/integrations/platforms/docker.mdx @@ -50,7 +50,7 @@ CMD ["infisical", "run", "--command", "npm run start && ..."] ## Generate an Infisical Token -Head to your project settings in Infisical Cloud to generate an [Infisical Token](https://infisical.com/docs/getting-started/dashboard/token). +Head to your project settings in Infisical Cloud to generate an [Infisical Token](/documentation/platform/token). ## Feed Docker your Infisical Token diff --git a/docs/integrations/platforms/kubernetes.mdx b/docs/integrations/platforms/kubernetes.mdx index 959a4fce2..efe5297ad 100644 --- a/docs/integrations/platforms/kubernetes.mdx +++ b/docs/integrations/platforms/kubernetes.mdx @@ -1,6 +1,6 @@ --- title: 'Kubernetes' -description: "This page explains how to use Infisical to inject secrets into Kubernetes clusters." +description: "How to use Infisical to inject secrets into Kubernetes clusters." --- ![title](../../images/k8-diagram.png) @@ -38,12 +38,10 @@ The operator can be install via [Helm](helm.sh) or [kubectl](https://github.com/ ## Sync Infisical Secrets to your cluster - -To retrieve secrets from an Infisical project and store them in your Kubernetes cluster, you can use the InfisicalSecret custom resource. -This resource is available after installing the Infisical operator. In order to specify the Infisical Token location and the location where the retrieved secrets should be stored, you can use the `tokenSecretReference` and `managedSecretReference` fields within the InfisicalSecret resource. +To retrieve secrets from an Infisical project and save them as native Kubernetes secrets within a specific namespace, utilize the `InfisicalSecret` custom resource definition (CRD). +This resource can be created after installing the Infisical operator. For each new managed secret, you will need to create a new InfisicalSecret CRD. ```yaml - apiVersion: secrets.infisical.com/v1alpha1 kind: InfisicalSecret metadata: @@ -52,46 +50,134 @@ 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 - - # The Kubernetes secret the stores the Infisical token - tokenSecretReference: - # Kubernetes secret name - secretName: service-token - # The secret namespace - secretNamespace: default - - # The Kubernetes secret that Infisical Operator will create and populate with secrets from the above project + authentication: + serviceToken: # <-- option 1 + serviceTokenSecretReference: + secretName: service-token + secretNamespace: option + serviceAccount: # <-- method 2 + serviceAccountSecretReference: + secretName: service-account + secretNamespace: default + projectId: "6439ec224cfbf7ea2a95b651" + environmentName: "dev" managedSecretReference: - # The name of managed Kubernetes secret that should be created - secretName: managed-secret - # The namespace the managed secret should be installed in - secretNamespace: default + secretName: managed-secret # <-- the name of kubernetes secret that will be created + secretNamespace: default # <-- where the kubernetes secret that will be created ``` +### InfisicalSecret CRD properties - - The `tokenSecretReference` field in the InfisicalSecret resource is used to specify the location of the Infisical Token, which is required for authenticating and retrieving secrets from an Infisical project. - - To create a Kubernetes secret containing an [Infisical Token](../../getting-started/dashboard/token), you can run the command below. - ``` bash - kubectl create secret generic service-token --from-literal=infisicalToken= - ``` + + If you are fetching secrets from a self hosted instance of Infisical set the value of `hostAPI` to + ` https://your-self-hosted-instace.com/api` -Once the secret is created, add the name and namespace of the secret under `tokenSecretReference` field in the InfisicalSecret custom resource. + When `hostAPI` is not defined the operator fetches secrets from Infisical Cloud. -{' '} + + If you have installed your Infisical instance within the same cluster as the Infisical operator, you can optionally access the Infisical backend's service directly without having to route through the public internet. + To achieve this, use the following address for the hostAPI field: + + ``` bash + http://..svc.cluster.local:4000/api + ``` - - No matter what the name of the secret is or its namespace, it must contain a - key named `infisicalToken` with a valid Infisical Token as the value - + Make sure to replace `` and `` with the appropriate values for your backend service and namespace. + + + + The `authentication` property tells the operator where it should look to find credentials needed to fetch secrets from Infisical. You can authenticate via two methods as described below. + + + + Authenticating with service tokens is a great option when you have a small number of services you'd like to fetch secrets for and are looking for the least amount of setup. + + #### 1. Generate service token + + You can generate a service token for an Infisical project by heading over to the Infisical dashboard then to Project Settings. + + #### 2. Create Kubernetes secret containing service token + + Once you have generated the service token, you will need to create a Kubernetes secret containing the service token you generated. + To quickly create a Kubernetes secret containing the generated service token, you can run the command below. + + ``` bash + kubectl create secret generic service-token --from-literal=infisicalToken= + ``` + + #### 3. Add reference for the Kubernetes secret containing service token + + Once the secret is created, add the name and namespace of the secret that was just created under `authentication.serviceToken.serviceTokenSecretReference` field in the InfisicalSecret resource. + + ## Example + ```yaml + apiVersion: secrets.infisical.com/v1alpha1 + kind: InfisicalSecret + metadata: + name: infisicalsecret-sample-crd + spec: + authentication: + serviceToken: + serviceTokenSecretReference: + secretName: service-token # <-- name of the Kubernetes secret that stores our service token + secretNamespace: option # <-- namespace of the Kubernetes secret that stores our service token + ... + ``` + + + + We recommend authenticating with service account credentials when you have a large number of services. With this method, instead of creating a service token for each Infisical project you'd like to + fetch secrets from, you can fetch secrets from a number of Infisical projects with just one set of credentials. + + #### 1. Generate service account + + You can generate a service account by heading over to the organization settings. Once you create the service account, keep the credentials at hand for the next steps. + + #### 2. Grant service account access to Infisical projects + + Click on the pencil icon on the service account you just created and add the projects you'd like to be accessible via that service account. + + #### 3. Store service account credentials in K8 secret + Next, we'll need to store the service account credentials in a kubernetes secret so that we can reference it in our InfisicalSecret CRD. + + We recommend you create this kubernetes secret in a new namespace since you may need to reference it many times for each InfisicalSecret CRD you create. + + To quickly create a Kubernetes secret containing the service account details, you can execute the command below after replacing it with your own service account credentials. + + ``` + kubectl create secret generic service-token --from-literal=serviceAccountAccessKey=[REPLACE] --from-literal=serviceAccountPrivateKey=[REPLACE] --from-literal=serviceAccountPublicKey=[REPLACE] + ``` + + Regardless of how you create the kubernetes secret containing the service account credentials, you will need to define values for the following keys in the secret: `serviceAccountAccessKey`, `serviceAccountPrivateKey`, and `serviceAccountPublicKey` + + Once the secret is created, add the name and namespace of the secret that was just created under `authentication.serviceAccount.serviceAccountSecretReference` field in the InfisicalSecret CRD. + + #### 4. Add projectId and environment from which to fetch secrets from + Add the Infisical project id and environment from which to fetch secrets for by providing values under `authentication.serviceAccount.projectId` and `authentication.serviceAccount.environmentName`. + + ## Example + ```yaml + apiVersion: secrets.infisical.com/v1alpha1 + kind: InfisicalSecret + metadata: + name: infisicalsecret-sample-crd + spec: + serviceAccount: + serviceAccountSecretReference: + secretName: service-account + secretNamespace: default + projectId: "6439ec224cfbf7ea2a95b651" + environmentName: "dev" + ``` + + The `managedSecretReference` field in the InfisicalSecret resource is used to specify the location where secrets retrieved from an Infisical project should be stored. You should specify the name and namespace of the Kubernetes secret that will hold these secrets. The operator will create the secret for you, you just need to provide its name and namespace. -It is recommended that the managed secret be created in the same namespace as the deployment that will use it. +The managed secret be should be created in the same namespace as the deployment that will use it. diff --git a/docs/mint.json b/docs/mint.json index 48dc1805c..b4412dfe2 100644 --- a/docs/mint.json +++ b/docs/mint.json @@ -54,6 +54,11 @@ "icon": "cloud", "url": "api-reference" }, + { + "name": "Changelog", + "icon": "timer", + "url": "changelog" + }, { "name": "Contributing", "icon": "code", @@ -67,7 +72,7 @@ { "name": "Slack", "icon": "slack", - "url": "https://join.slack.com/t/infisical-users/shared_invite/zt-1kovn1q6p-p5fvJo7o083naouDkOzgZQ" + "url": "https://join.slack.com/t/infisical-users/shared_invite/zt-1wehzfnzn-1aMo5JcGENJiNAC2SD8Jlg" }, { "name": "GitHub", @@ -79,29 +84,60 @@ { "group": "Overview", "pages": [ - "getting-started/introduction", - "getting-started/quickstart", - "getting-started/features" + { + "group": "Getting Started", + "pages": [ + "documentation/getting-started/introduction", + "documentation/getting-started/platform", + "documentation/getting-started/sdks", + "documentation/getting-started/cli", + "documentation/getting-started/docker", + "documentation/getting-started/kubernetes", + "documentation/getting-started/api" + ] + }, + { + "group": "Guides", + "pages": [ + "documentation/guides/introduction", + "documentation/guides/node", + "documentation/guides/python", + "documentation/guides/nextjs-vercel" + ] + } ] }, { "group": "Platform", "pages": [ - "getting-started/dashboard/organization", - "getting-started/dashboard/project", - "getting-started/dashboard/pit-recovery", - "getting-started/dashboard/secret-versioning", - "getting-started/dashboard/audit-logs", - "getting-started/dashboard/mfa", - "getting-started/dashboard/token" + "documentation/platform/organization", + "documentation/platform/project", + "documentation/platform/pit-recovery", + "documentation/platform/secret-versioning", + "documentation/platform/audit-logs", + "documentation/platform/mfa", + "documentation/platform/token" ] }, { - "group": "Self-hosting", + "group": "Self-host Infisical", "pages": [ - "self-hosting/overview", + { + "group": "Deployment options", + "pages": [ + "self-hosting/overview", + "self-hosting/deployment-options/kubernetes-helm", + "self-hosting/deployment-options/aws-ec2", + "self-hosting/deployment-options/docker-compose", + "self-hosting/deployment-options/standalone-infisical", + "self-hosting/deployment-options/fly.io", + "self-hosting/deployment-options/render", + "self-hosting/deployment-options/digital-ocean-marketplace" + ] + }, "self-hosting/configuration/envars", - "self-hosting/configuration/email" + "self-hosting/configuration/email", + "self-hosting/faq" ] }, { @@ -110,7 +146,7 @@ "cli/overview", "cli/usage", { - "group": "Commands", + "group": "Core commands", "pages": [ "cli/commands/login", "cli/commands/init", @@ -118,9 +154,19 @@ "cli/commands/secrets", "cli/commands/export", "cli/commands/vault", - "cli/commands/reset" + "cli/commands/user", + "cli/commands/reset", + { + "group": "infisical scan", + "pages": [ + "cli/commands/scan", + "cli/commands/scan-git-changes", + "cli/commands/scan-install" + ] + } ] }, + "cli/scanning-overview", "cli/project-config", "cli/faq" ] @@ -149,12 +195,17 @@ "integrations/cloud/vercel", "integrations/cloud/netlify", "integrations/cloud/render", + "integrations/cloud/railway", "integrations/cloud/flyio", + "integrations/cloud/supabase", + "integrations/cloud/checkly", + "integrations/cloud/hashicorp-vault", "integrations/cloud/azure-key-vault", "integrations/cicd/githubactions", "integrations/cicd/gitlab", "integrations/cicd/circleci", "integrations/cicd/travisci", + "integrations/frameworks/spring-boot-maven", "integrations/frameworks/react", "integrations/frameworks/vue", "integrations/frameworks/express", @@ -174,13 +225,6 @@ "integrations/platforms/pm2" ] }, - { - "group": "Deployment options", - "pages": [ - "self-hosting/deployments/linux", - "self-hosting/deployments/kubernetes" - ] - }, { "group": "Overview", "pages": [ @@ -195,7 +239,8 @@ "sdks/languages/java", "sdks/languages/ruby", "sdks/languages/go", - "sdks/languages/rust" + "sdks/languages/rust", + "sdks/languages/php" ] }, { @@ -206,12 +251,12 @@ { "group": "Examples", "pages": [ - "api-reference/overview/examples/create-secrets", - "api-reference/overview/examples/retrieve-secrets", - "api-reference/overview/examples/update-secrets", - "api-reference/overview/examples/delete-secrets" + "api-reference/overview/examples/note", + "api-reference/overview/examples/e2ee-disabled", + "api-reference/overview/examples/e2ee-enabled" ] - } + }, + "api-reference/overview/blind-indices" ] }, { @@ -248,8 +293,9 @@ { "group": "Secrets", "pages": [ - "api-reference/endpoints/secrets/create", "api-reference/endpoints/secrets/read", + "api-reference/endpoints/secrets/create", + "api-reference/endpoints/secrets/read-one", "api-reference/endpoints/secrets/update", "api-reference/endpoints/secrets/delete", "api-reference/endpoints/secrets/versions", @@ -272,16 +318,22 @@ "security/mechanics" ] }, + { + "group": "Overview", + "pages": [ + "changelog/overview" + ] + }, { "group": "Contributing", "pages": [ "contributing/overview", "contributing/code-of-conduct", - "contributing/developing" + "contributing/developing", + "contributing/pull-requests" ] } ], - "backgroundImage": "/images/background.png", "integrations": { "intercom": "hsg644ru" } diff --git a/docs/sdks/languages/go.mdx b/docs/sdks/languages/go.mdx index 0ff2a2dde..b470c5b7d 100644 --- a/docs/sdks/languages/go.mdx +++ b/docs/sdks/languages/go.mdx @@ -1,5 +1,6 @@ --- title: "Go" +icon: "golang" --- Coming soon. diff --git a/docs/sdks/languages/java.mdx b/docs/sdks/languages/java.mdx index 2dd2c3c1d..7bc371bae 100644 --- a/docs/sdks/languages/java.mdx +++ b/docs/sdks/languages/java.mdx @@ -1,5 +1,6 @@ --- title: "Java" +icon: "java" --- Coming soon. diff --git a/docs/sdks/languages/node.mdx b/docs/sdks/languages/node.mdx index 58002392f..d28357c4e 100644 --- a/docs/sdks/languages/node.mdx +++ b/docs/sdks/languages/node.mdx @@ -1,154 +1,207 @@ --- title: "Node" +icon: "node" --- -If you're working with Node.js, the official [infisical-node](https://github.com/Infisical/infisical-node) package is the easiest way to fetch secrets for your application. +If you're working with Node.js, the official [infisical-node](https://github.com/Infisical/infisical-node) package is the easiest way to fetch and work with secrets for your application. + +## Basic Usage + +```js +import express from "express"; +import InfisicalClient from "infisical-node"; +const app = express(); +const PORT = 3000; + +const client = new InfisicalClient({ + token: "YOUR_INFISICAL_TOKEN" +}); + +app.get("/", async (req, res) => { + // access value + const name = await client.getSecret("NAME"); + res.send(`Hello! My name is: ${name.secretValue}`); +}); + +app.listen(PORT, async () => { + console.log(`App listening on port ${PORT}`); +}); +``` + +This example demonstrates how to use the Infisical Node SDK with an Express application. The application retrieves a secret named "NAME" and responds to requests with a greeting that includes the secret value. + + + We do not recommend hardcoding your [Infisical + Token](/documentation/platform/token). Setting it as an environment + variable would be best. + ## Installation Run `npm` to add `infisical-node` to your project. -```bash -npm install infisical-node --save +```console +$ npm install infisical-node --save ``` -## Initialization +## Configuration -Set up the Infisical client asynchronously as early as possible in your application by importing and initializing the global instance with `infisical.connect(options)`. - -This methods fetches back all the secrets in the project and environment accessible by the token passed in `options`. - -### infisical.connect(options) - -Updates the global instance of the Infisical client with a connection to an Infisical project and fetches back secrets if supplied with an [Infisical Token](/getting-started/dashboard/token). - - - - - An [Infisical Token](/getting-started/dashboard/token) scoped to a project - and environment - - - Your self-hosted absolute site URL including the protocol (e.g. - `https://app.infisical.com`) - - - Whether or not debug mode is on - - - Whether or not to attach fetched secrets to `process.env` - - - - -### infisical.createConnection(options) - -Returns a local instance of the Infisical client with a connection to an Infisical project and fetches back secrets if supplied with an [Infisical Token](/getting-started/dashboard/token). - -This method is useful if you wish to connect to two or more Infisical projects within your app. - - - - - An [Infisical Token](/getting-started/dashboard/token) scoped to a project - and environment - - - Your self-hosted absolute site URL including the protocol (e.g. - `https://app.infisical.com`) - - - Whether or not debug mode is on - - - +Import the SDK and create a client instance with your [Infisical Token](/documentation/platform/token). ```js - import infisical from "infisical-node"; - - const main = async () => { - await infisical.connect({ - token: "your_infisical_token", - }); - - // your app logic - } - - main(); + import InfisicalClient from "infisical-node"; + + const client = new InfisicalClient({ + token: "your_infisical_token" + }); ``` ```js - const infisical = require("infisical-node"); + const InfisicalClient = require("infisical-node"); - infisical.connect({ - token: "your_infisical_token" - }) - .then(() => { - // your application logic - }) - .catch(err => { - console.error('Error: ', err); - }) + const client = new InfisicalClient({ + token: "your_infisical_token" + }); ```` -## Usage +### Parameters -To get the value of a secret, use `infisical.get(key)`. + + + + An [Infisical Token](/documentation/platform/token) scoped to a project + and environment + + + Your self-hosted absolute site URL including the protocol (e.g. + `https://app.infisical.com`) + + + Time-to-live (in seconds) for refreshing cached secrets. Default: `300`. + + + Whether or not debug mode is on + + + -### infisical.get(key) +## Caching -Return the value of the secret with the specified `key`. Note that the Infisical client falls back to `process.env` if `token` is `undefined` during the -initialization step or if a value for the secret is not found in the fetched secrets. +The SDK caches every secret and updates it periodically based on the provided `cacheTTL`. For example, if `cacheTTL` of `300` is provided, then a secret will be refetched 5 minutes after the first fetch; if the fetch fails, the cached secret is returned. - - The key of the secret - + + For optimal performance, we recommend creating a single instance of the Infisical client and exporting it to be used across your entire app to take advantage of caching benefits. + + +## Working with Secrets + +### client.getAllSecrets() ```js -const value = infisical.get("SOME_KEY"); +const secrets = await client.getAllSecrets(); ``` -## Example with Express +Retrieve all secrets within the Infisical project and environment that client is connected to + +### client.getSecret(secretName, options) ```js -const express = require("express"); -const port = 3000; -const infisical = require("infisical-node"); - -const main = async () => { - await infisical.connect({ - token: "st.xxx.xxx", - }); - - // your application logic - - app.get("/", (req, res) => { - res.send(`Howdy, ${infisical.get("NAME")}!`); - }); - - app.listen(port, async () => { - console.log(`App listening on port ${port}`); - }); -}; +const secret = await client.getSecret("API_KEY"); +const value = secret.secretValue; // get its value ``` - - We do not recommend hardcoding your [Infisical - Token](/getting-started/dashboard/token). Setting it as an environment - variable would be best. - +Retrieve a secret from Infisical. + +By default, `getSecret()` fetches and returns a personal secret. If not found, it returns a shared secret, or tries to retrieve the value from `process.env`. If a secret is fetched, `getSecret()` caches it to reduce excessive calls and re-fetches periodically based on the `cacheTTL` option (default is `300` seconds) when initializing the client — for more information, see the caching section. + +### Parameters + + + The key of the secret to retrieve + + + + + The type of the secret. Valid options are "shared" or "personal" + + + + +### client.createSecret(secretName, secretValue, options) + +```js +const newApiKey = await client.createSecret("API_KEY", "FOO"); +``` + +Create a new secret in Infisical. + + + The key of the secret to create + + + The value of the secret to create + + + + + The type of the secret. Valid options are "shared" or "personal". A personal secret can only be created if a shared secret with the same name exists. + + + + +### client.updateSecret(secretName, secretValue, options) + +```js +const updatedApiKey = await client.updateSecret("API_KEY", "BAR"); +``` + +Update an existing secret in Infisical. + +### Parameters + + + The key of the secret to update + + + The new value of the secret + + + + + The type of the secret. Valid options are "shared" or "personal" + + + + +### client.deleteSecret(secretName, options) + +```js +const deletedSecret = await client.deleteSecret("API_KEY"); +``` + +Delete a secret in Infisical. + + + The key of the secret to delete + + + + + The type of the secret. Valid options are "shared" or "personal". Note that deleting a shared secret also deletes all associated personal secrets. + + + + + diff --git a/docs/sdks/languages/php.mdx b/docs/sdks/languages/php.mdx new file mode 100644 index 000000000..996b95c74 --- /dev/null +++ b/docs/sdks/languages/php.mdx @@ -0,0 +1,8 @@ +--- +title: "PHP" +icon: "php" +--- + +Coming soon. + +Follow this GitHub [issue](https://github.com/Infisical/infisical/issues/531) to stay updated. \ No newline at end of file diff --git a/docs/sdks/languages/python.mdx b/docs/sdks/languages/python.mdx index 3a9b82152..caf916451 100644 --- a/docs/sdks/languages/python.mdx +++ b/docs/sdks/languages/python.mdx @@ -1,8 +1,169 @@ --- title: "Python" +icon: "python" --- -Coming soon. +If you're working with Python, the official [infisical-python](https://github.com/Infisical/infisical-python) package is the easiest way to fetch and work with secrets for your application. + +## Basic Usage + +```py +from flask import Flask +from infisical import InfisicalClient + +app = Flask(__name__) + +client = InfisicalClient(token="your_infisical_token") + +@app.route("/") +def hello_world(): + # access value + name = client.get_secret("NAME") + return f"Hello! My name is: {name.secret_value}" +``` + +This example demonstrates how to use the Infisical Python SDK with a Flask application. The application retrieves a secret named "NAME" and responds to requests with a greeting that includes the secret value. + + + We do not recommend hardcoding your [Infisical + Token](/documentation/platform/token). Setting it as an environment + variable would be best. + + +## Installation + +Run `pip` to add `infisical-python` to your project + +```console +$ pip install infisical +``` + +Note: You need Python 3.7+. + +## Configuration + +Import the SDK and create a client instance with your [Infisical Token](/documentation/platform/token). + +```py +from infisical import InfisicalClient + +client = InfisicalClient(token="your_infisical_token") +``` + +### Parameters + + + An [Infisical Token](/documentation/platform/token) scoped to a project + and environment + + + Your self-hosted absolute site URL including the protocol (e.g. + `https://app.infisical.com`) + + + Time-to-live (in seconds) for refreshing cached secrets. Default: `300`. + + + Whether or not debug mode is on + + +## Caching + +The SDK caches every secret and updates it periodically based on the provided `cache_ttl`. For example, if `cache_ttl` of `300` is provided, then a secret will be refetched 5 minutes after the first fetch; if the fetch fails, the cached secret is returned. + + + For optimal performance, we recommend creating a single instance of the Infisical client and exporting it to be used across your entire app to take advantage of caching benefits. + + +## Working with Secrets + +### client.get_all_secrets() + +```py +secrets = client.get_all_secrets() +``` + +Retrieve all secrets within the Infisical project and environment that client is connected to + +### client.get_secret(secret_name, options) + +```py +secret = client.get_secret("API_KEY") +value = secret.secret_value # get its value +``` + +By default, `get_secret()` fetches and returns a personal secret. If not found, it returns a shared secret, or tries to retrieve the value from `os.environ`. If a secret is fetched, `get_secret()` caches it to reduce excessive calls and re-fetches periodically based on the `cacheTTL` option (default is 300 seconds) when initializing the client — for more information, see the caching section. + +### Parameters + + + The key of the secret to retrieve + + + The type of the secret. Valid options are "shared" or "personal" + + +### client.create_secret(secret_name, secret_value, options) + +```py +new_api_key = client.create_secret("API_KEY", "FOO"); +``` + +Create a new secret in Infisical. + +### Parameters + + + The key of the secret to create + + + The value of the secret to create + + + The type of the secret. Valid options are "shared" or "personal". A personal secret can only be created if a shared secret with the same name exists. + + +### client.update_secret(secret_name, secret_value, options) + +```py +updated_api_key = client.update_secret("API_KEY", "BAR"); +``` + +Update an existing secret in Infisical. + +### Parameters + + + The key of the secret to update + + + The new value of the secret + + + The type of the secret. Valid options are "shared" or "personal" + + +### client.delete_secret(secret_name, options) + +```py +deleted_secret = client.delete_secret("API_KEY"); +``` + +Delete a secret in Infisical. + +### Parameters + + + The key of the secret to delete + + + The type of the secret. Valid options are "shared" or "personal" + Follow this GitHub [issue](https://github.com/Infisical/infisical/issues/433) to stay updated. diff --git a/docs/sdks/languages/ruby.mdx b/docs/sdks/languages/ruby.mdx index 80dab508a..1233e44bd 100644 --- a/docs/sdks/languages/ruby.mdx +++ b/docs/sdks/languages/ruby.mdx @@ -1,5 +1,6 @@ --- title: "Ruby" +icon: "gem" --- Coming soon. diff --git a/docs/sdks/languages/rust.mdx b/docs/sdks/languages/rust.mdx index 8fa9b3b5b..5d5b770ca 100644 --- a/docs/sdks/languages/rust.mdx +++ b/docs/sdks/languages/rust.mdx @@ -1,5 +1,6 @@ --- title: "Rust" +icon: "rust" --- Coming soon. diff --git a/docs/sdks/overview.mdx b/docs/sdks/overview.mdx index fd27ad902..429a27140 100644 --- a/docs/sdks/overview.mdx +++ b/docs/sdks/overview.mdx @@ -1,18 +1,105 @@ --- -title: "Overview" -description: "How to use Infisical SDKs to fetch back secrets for your app" +title: "Introduction" --- -Infisical SDKs provide the easiest way for your app to fetch back secrets using an [Infisical Token](/getting-started/dashboard/token) and has a few benefits: +From local development to production, Infisical SDKs provide the easiest way for your app to fetch back secrets from Infisical on demand. -- Local development: Replace 10s of environment variables in your `.env` file with 1 environment variable (the [Infisical Token](/getting-started/dashboard/token)). -- Production: Fetch secrets back to any cloud regardless of if an integration exists between Infisical and the cloud platform. +- Install and initialize a language-specific client SDK into your application +- Provision the client scoped-access to a project and environment in Infisical +- Fetch secrets on demand -We currently only have the [Node SDK](/sdks/languages/node) available but more language SDKs are coming out soon: + + + Manage secrets for your Node application on demand + + + Manage secrets for your Python application on demand + + + Manage secrets for your Java application on demand + + + Manage secrets for your Ruby application on demand + + + Manage secrets for your Go application on demand + + + Manage secrets for your Rust application on demand + + + Manage secrets for your PHP application on demand + + -- [Node](/sdks/languages/node) -- [Python](/sdks/languages/python) -- [Java](/sdks/languages/java) -- [Ruby](/sdks/languages/ruby) -- [Go](/sdks/languages/go) -- [Rust](/sdks/languages/rust) +## FAQ + + + + No. Infisical uses end-to-end encryption which ensures that secrets are always encrypted in transit + and decrypted on the client side. In fact, not even the server can decrypt your secrets (unless + that permission is explicitly granted from within the platform). + + Check out the [security guide](/security/overview). + + + The client SDK caches every secret and implements a 5-minute waiting period before + re-requesting it. The waiting period can be controlled by setting the `cacheTTL` parameter at + the time of initializing the client. + + + The SDK caches every secret and falls back to the cached value if a request fails. If no cached + value ever-existed, the SDK falls back to whatever value is on `process.env`. + + + Yes. If no `token` parameter is passed in at the time of initializing the client or nothing is found when requesting for a secret, + then the SDK falls back to whatever value is on `process.env`. + + + The token enables the SDK to authenticate with Infisical to fetch back your secrets. + Although the SDK requires you to pass in a token, it enables greater efficiency and security + than if you managed dozens of secrets yourself without it. Here're some benefits: + + - You always pull in the right secrets because they're fetched on demand from a centralize source that is Infisical. + - You can use the Infisical which comes with tons of benefits like secret versioning, access controls, audit logs, etc. + - You now risk leaking one token that can be revoked instead of dozens of raw secrets. + + And much more. + + + \ No newline at end of file diff --git a/docs/security/data-model.mdx b/docs/security/data-model.mdx index 9f79cd254..af4adeb24 100644 --- a/docs/security/data-model.mdx +++ b/docs/security/data-model.mdx @@ -21,21 +21,30 @@ Infisical makes a usability-security tradeoff that is to give users convenient a ## Secrets -The `Secret` model includes the fields `workspace`, `type`, `user`, `environment`, `secretKeyCiphertext`, `secretKeyIV`, `secretKeyTag`, `secretValueCiphertext`, `secretValueIV`, and `secretValueTag`. +The `Secret` model includes the fields `workspace`, `type`, `user`, `environment`, `secretBlindIndex`, `secretKeyCiphertext`, `secretKeyIV`, `secretKeyTag`, `secretValueCiphertext`, `secretValueIV`, and `secretValueTag`. -Each secret is symmetrically encrypted by the key of the project that it belongs to; that key's encrypted copies are stored in a separate `Key` collection. +Each secret consists of a key name and value pair and is symmetrically encrypted by the key of the project that it belongs to; that key's encrypted copies are stored in a separate `Key` collection. + +The `secretBlindIndex` enables users to query secrets by their names; it is a blind index computed by applying `argon2id` with a 128-bit random salt (unique to each project) and the name of the secret. The salt itself is symmetrically encrypted under the server key and stored in the `SecretBlindIndexData` collection. + +## Blind Index Data + +The `SecretBlindIndexData` model includes the fields `workspace`, `encryptedSaltCiphertext`, `saltIV`, and `saltTag`. + +Infisical stores salts (unique to each project) symmetrically encrypted under the server key. The salts are used to compute blind indices for secrets that enable +users to query secrets by name. ## Project Keys The `Key` model includes the fields `encryptedKey`, `nonce`, `sender`, `receiver`, and `workspace`. -Infisical stores copies of project keys, one for each member of a project, encrypted under each member's public key. +Infisical stores copies of project keys, one for each member of a project, asymmetrically encrypted under each member's public key. ## Bots The `Bot` model contains the fields `name`, `workspace`, `isActive`, `publicKey`, `encryptedPrivateKey`, `iv`, and `tag`. -Each project comes with a bot that has its own public-private key pair; its private key is encrypted by the server's symmetric key. If needed, a user can opt-in to share their project key with the bot (i.e. Infisical) to give the platform access to the project's secrets. +Each project comes with a bot that has its own public-private key pair; its private key is symmetrically encrypted by the server's key. If needed, a user can opt-in to share their project key with the bot (i.e. Infisical) to give the platform access to the project's secrets. Sharing secrets with Infisical so they can be synced to integrations like diff --git a/docs/security/mechanics.mdx b/docs/security/mechanics.mdx index 325224f90..97cd570f1 100644 --- a/docs/security/mechanics.mdx +++ b/docs/security/mechanics.mdx @@ -27,3 +27,20 @@ After signing up, a user can invite other users to their organization to partake To push secrets, a sender randomly-generates a symmetric encryption key, uses that key to encrypt their secret keys and values separately, asymmetrically encrypts the key with the receivers’ public keys, and uploads the encrypted secrets and keys to the server. To pull secrets, a receiver obtains encrypted secret keys and values and their encrypted copy of the project key to decrypt the secrets from the server — they asymmetrically decrypt the key using their private key and use the decrypted key to decrypt the secrets. This public-key mechanism prevents the server-side from reading any secrets. + +When dealing with individual secrets (e.g. pulling one secret by name) or creating new secrets, a user passes the name of the secret to the server which is then converted to a blind index by applying `argon2id` with the name of the secret and a 128-bit random salt unique to each project; the salt itself is encrypted by the server key and stored in the database. + + + Infisical ensures that the name of any secret is never stored in plaintext and instead only a blind index generated from the name. It is infeasible to reverse back a blind index to the name of a secret without knowledge of the server key. + + +## Bot + +To use some features like integrations, users must opt out of E2EE (this means sharing access to secrets with Infisical). + +Infisical employs the concept of a bot which is a cryptographic abstraction for how Infisical interacts with secrets when users opt out of E2EE. In this model, each project is assigned a bot with its own public-private key pair where each bot's private key is stored symmetrically encrypted under the server key. When a user opts out of E2EE, they share the project key with the bot by encrypting a copy of it under the public key of the bot. + +When users wish to sync secrets from a project and environment Infisical to other platform integrations like Vercel or GitHub, Infisical decrypts the intended secrets and uses the integration platform's APIs to send secrets over. It should be noted that opting out of E2EE is optional and it is entirely possible to use Infisical to manage secrets across your team and infrastructure without opting out of E2EE. + + + diff --git a/docs/security/overview.mdx b/docs/security/overview.mdx index 643a54b38..bddff608b 100644 --- a/docs/security/overview.mdx +++ b/docs/security/overview.mdx @@ -5,7 +5,7 @@ description: "Infisical's security statement." ## Summary -Infisical uses end-to-end encryption (E2EE) whenever possible to securely store and share secrets. It uses secure remote password (SRP) to handle authentication and public-key cryptography for secret sharing and syncing; secrets are symmetrically encrypted at rest by keys decryptable only by members of the project. +Infisical uses end-to-end encryption (E2EE) whenever possible to securely store and share secret values. It uses secure remote password (SRP) to handle authentication and public-key cryptography for secret sharing and syncing; secrets are symmetrically encrypted by keys decryptable only by members of the project. Infisical uses AES256-GCM for symmetric encryption and x25519-xsalsa20-poly1305 for asymmetric encryption operations mentioned in this brief; key generation and asymmetric algorithms are implemented with the [TweetNaCl.js](https://tweetnacl.js.org/#/) library which has been well-audited and recommended for use by cybersecurity firm Cure53. Lastly, the secure remote password (SRP) implementation uses [jsrp](https://github.com/alax/jsrp) package for user authentication. As part of our commitment to user privacy and security, we aim to conduct formal security and compliance audits in the following year. diff --git a/docs/self-hosting/authentication/google.mdx b/docs/self-hosting/authentication/google.mdx new file mode 100644 index 000000000..dc3de4089 --- /dev/null +++ b/docs/self-hosting/authentication/google.mdx @@ -0,0 +1,18 @@ +--- +title: "Google" +description: "Learn to configure Google signin/signup when self-hosting Infisical." +--- +To enable Google Auth for your Infisical project, you first need to set up a Google OAuth application. +Follow Google's Setting up OAuth 2.0 documentation [here](https://support.google.com/googleapi/answer/6158849). After the setup, copy the Client ID and Client secret. You will need them below. + +## Configure Redirect URI +Add the following URI to the Authorized redirect URIs section in the OAuth Client credentials page - `BASE_URL/api/v1/auth/callback/google`. Replace BASE_URL with the URL of your hosted Infisical instance. +![google redirect](../../images/authentication-google-redirect.png) + +## General Configuration +You wil need to configure the following [environment variables](https://infisical.com/docs/self-hosting/configuration/envars): + +- `CLIENT_ID_GOOGLE`: OAuth 2.0 Client ID obtained from the credentials page +- `CLIENT_SECRET_GOOGLE`: OAuth 2.0 Client Secret obtained from the credentials page +- `JWT_PROVIDER_AUTH_SECRET`: Secret Key for signing OAuth 2.0 access token +- `JWT_PROVIDER_AUTH_LIFETIME`: Lifetime for OAuth 2.0 access token \ No newline at end of file diff --git a/docs/self-hosting/configuration/email.mdx b/docs/self-hosting/configuration/email.mdx index a6b13fa0b..4c6e13a49 100644 --- a/docs/self-hosting/configuration/email.mdx +++ b/docs/self-hosting/configuration/email.mdx @@ -3,17 +3,16 @@ title: "Configure email service" description: "How to configure your email when self-hosting Infisical." --- -Infisical requires you to configure your own SMTP server for certain functionality like: +By default, the core functions of Infisical work without any email service configuration. Without email service, basic sign up/login and secret operations will function without any issue. +However, the following functionality will be disabled. -- Sending email confirmation links to sign up. -- Sending invite links for projects. -- Sending alerts. - -We strongly recommend using an email service to act as your email server and provide examples for common providers. +- Multi-factor authentication +- Sending invite links via email for projects to teammates +- Sending alerts such as suspicious login attempts ## General configuration -By default, you need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars): +If you choose to setup email service, you need to configure the following SMTP [environment variables](https://infisical.com/docs/self-hosting/configuration/envars): - `SMTP_HOST`: Hostname to connect to for establishing SMTP connections. - `SMTP_USERNAME`: Credential to connect to host (e.g. team@infisical.com) @@ -23,7 +22,7 @@ By default, you need to configure the following SMTP [environment variables](htt - `SMTP_FROM_ADDRESS`: Email address to be used for sending emails (e.g. team@infisical.com). - `SMTP_FROM_NAME`: Name label to be used in `From` field (e.g. Team). -Below you will find details on how to configure common email providers (not in any particular order). +Below you will find details on how to configure common email providers: @@ -135,6 +134,34 @@ SMTP_FROM_NAME=Infisical + + +Create an account and enable "less secure app access" in Gmail Account Settings > Security. This will allow +applications like Infisical to authenticate with Gmail via your username and password. + +![Gmail secure app access](../../images/email-gmail-app-access.png) + +With your Gmail username and password, you can set your SMTP environment variables: + +``` +SMTP_HOST=smtp.gmail.com +SMTP_USERNAME=hey@gmail.com # your email +SMTP_PASSWORD=password # your password +SMTP_PORT=587 +SMTP_SECURE=true +SMTP_FROM_ADDRESS=hey@gmail.com +SMTP_FROM_NAME=Infisical +``` + + + As per the [notice](https://support.google.com/accounts/answer/6010255?hl=en) by Google, you should note that using Gmail credentials for SMTP configuration + will only work for Google Workspace or Google Cloud Identity customers as of May 30, 2022. + + Put differently, the SMTP configuration is only possible with business (not personal) Gmail credentials. + + + + 1. Create an account and configure [Zoho Mail](https://www.zoho.com/mail/) to send emails. diff --git a/docs/self-hosting/configuration/envars.mdx b/docs/self-hosting/configuration/envars.mdx index 6bcb67d55..ef9fc1fd0 100644 --- a/docs/self-hosting/configuration/envars.mdx +++ b/docs/self-hosting/configuration/envars.mdx @@ -69,7 +69,7 @@ Other environment variables are listed below to increase the functionality of yo Name label to be used in From field (e.g. Team) - + To sync secret to third party services, provide value for the related services @@ -108,6 +108,18 @@ Other environment variables are listed below to increase the functionality of yo OAuth2 slug for Netlify integration + + To integrate with external auth providers, provide value for the related keys + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + OAuth2 client ID for Google auth integration + + + OAuth2 client secret for Google auth integration + + #### JWT @@ -126,6 +138,10 @@ Other environment variables are listed below to increase the functionality of yo JWT token lifetime expressed in seconds or a string describing a time span + + JWT token lifetime expressed in seconds or a string describing a time span + + diff --git a/docs/self-hosting/deployment-options/aws-ec2.mdx b/docs/self-hosting/deployment-options/aws-ec2.mdx new file mode 100644 index 000000000..303df2009 --- /dev/null +++ b/docs/self-hosting/deployment-options/aws-ec2.mdx @@ -0,0 +1,21 @@ +--- +title: "AWS EC2" +description: "Learn to install Infisical on EC2 using Cloud Formation template" +--- + + +This deployment option will use AWS Cloudformation to auto deploy an instance of Infisical on a single EC2 via Docker Compose. + +**Resources that will be provisioned** +- 1 EC2 instance +- 1 DocumentDB cluster +- 1 DocumentDB instance +- Security groups + + +Once installation is complete, you will have to create the first account. No default account is provided. + + + + + \ No newline at end of file diff --git a/docs/self-hosting/deployment-options/digital-ocean-marketplace.mdx b/docs/self-hosting/deployment-options/digital-ocean-marketplace.mdx new file mode 100644 index 000000000..8049cd3e5 --- /dev/null +++ b/docs/self-hosting/deployment-options/digital-ocean-marketplace.mdx @@ -0,0 +1,27 @@ +--- +title: "Digital Ocean" +description: "Learn to install Infisical on Digital Ocean" +--- + +Infisical can be deployed on a Kubernetes cluster with a single click through our Digital Ocean marketplace application. +The initiation of the installation process triggers the creation of a Kubernetes cluster, followed by the installation of Infisical onto that cluster. + +This automated deploymnet method uses the same proccess under the hood as the manual [Kubernetes installation guide](./kubernetes-helm). + +### Initiate the installation + +To start the process, click the following button and follow the instructions there. + + + + + +### Access Infisical Web +Once the installation finishes, head to the `Networking` section via the sidebar and select `Load Balancers`. +Within this section, you'll find the newly created load balancer for Infisical. You can access Infisical at the IP address allocated to that load balancer. + +### Adjusting configurations +If you need to either upgrade or downgrade Infisical, or modify environment variables to alter its functionality, refer to our [Kubernetes installation](./kubernetes-helm) page for detailed instructions. + +Because Digital Ocean deploys the same Helm application as described in our [Kubernetes installation](./kubernetes-helm) guide, you can utilize that guide to implement the required changes. +It's important to note that any modifications requires familiarly with Helm package manager. \ No newline at end of file diff --git a/docs/self-hosting/deployment-options/docker-compose.mdx b/docs/self-hosting/deployment-options/docker-compose.mdx new file mode 100644 index 000000000..05ce5fe74 --- /dev/null +++ b/docs/self-hosting/deployment-options/docker-compose.mdx @@ -0,0 +1,51 @@ +--- +title: "Docker Compose" +description: "Learn to install Infisical using our Docker Compose template" +--- + +## Install Docker on your VM + +```bash +# Example in ubuntu +apt-get update +apt-get upgrade +apt install docker-compose +``` + +## Download the required files + +```bash +# Download env file template +wget -O .env https://raw.githubusercontent.com/Infisical/infisical/main/.env.example + +# Download docker compose template +wget -O docker-compose.yml https://raw.githubusercontent.com/Infisical/infisical/main/docker-compose.yml + +# Download nginx config +mkdir nginx && wget -O ./nginx/default.conf https://raw.githubusercontent.com/Infisical/infisical/main/nginx/default.dev.conf +``` + +## Update .env file +Tweak the `.env` according to your preferences. Refer to the available [environment variables](/self-hosting/configuration/envars) + +```bash +# update environment variables like mongo login +nano .env +``` + + + Infisical assumes that you have configured HTTPS. If you didn't configure HTTPS, set `HTTPS_ENABLED` to `false` in the .env file to avoid frequent logouts. + + +## Get the service up and running + +```bash +# Start up services in detached mode +docker-compose -f docker-compose.yml up -d +``` + +Your Infisical installation is complete and should be running on [http://localhost:80](http://localhost:80). Please note that the containers are not exposed to the internet and only bind to the localhost. It's up to you to configure a firewall, SSL certificates, and implement any additional security measures. + + +Once installation is complete, you will have to create the first account. No default account is provided. + \ No newline at end of file diff --git a/docs/self-hosting/deployment-options/fly.io.mdx b/docs/self-hosting/deployment-options/fly.io.mdx new file mode 100644 index 000000000..4f43c9f46 --- /dev/null +++ b/docs/self-hosting/deployment-options/fly.io.mdx @@ -0,0 +1,63 @@ +--- +title: "Fly.io" +description: "Learn to install Infisical on Fly.io" +--- + +**Prerequisites** +- Familiar with Fly.io deployment +- Logged in via fly CLI + +#### 1. Make a copy of the deployment config +To begin, you'll to make a copy of the following file on your local machine + +```toml fly.toml +# fly.toml app configuration file generated for infisical on 2023-05-05T08:57:03-04:00 +# +# See https://fly.io/docs/reference/configuration/ for information about how to use this file. +# + +app = "infisical" +primary_region = "iad" + +[build] + image = "infisical/infisical:latest" + +[env] + ENCRYPTION_KEY = <> + JWT_AUTH_SECRET = <> + JWT_REFRESH_SECRET = <> + JWT_SERVICE_SECRET = <> + JWT_SIGNUP_SECRET = <> + MONGO_URL = <> + +[http_service] + internal_port = 80 + +``` + +#### 2. Add environment variables + +Before we can deploy Infisical, we'll need to provide values for the keys under `[env]` config block. For each of the following keys + +- `ENCRYPTION_KEY` +- `JWT_AUTH_SECRET` +- `JWT_REFRESH_SECRET` +- `JWT_SERVICE_SECRET` +- `JWT_SIGNUP_SECRET` + +you will need to generate a random 16 byte hex string. This can can be generated with `openssl rand -hex 16`. + + +Lastly, the `MONGO_URL` environment variable requires a document database connection URL. +You can obtain this URL by creating a document database using services such as [MongoDB](https://www.mongodb.com/), [AWS DocumentDB](https://aws.amazon.com/documentdb/), and others. + +#### 3. Deploy + +Run `fly launch` in the directory where you have the local version of config from step 1 and follow the instructions. +Once done, your very own instance of Infisical should be up and running on Fly.io. + +Please note that this version of Infisical requires at least 250MB of memory to operate smoothly. + + +Once installation is complete, you will have to create the first account. No default account is provided. + diff --git a/docs/self-hosting/deployment-options/kubernetes-helm.mdx b/docs/self-hosting/deployment-options/kubernetes-helm.mdx new file mode 100644 index 000000000..36b3c5213 --- /dev/null +++ b/docs/self-hosting/deployment-options/kubernetes-helm.mdx @@ -0,0 +1,219 @@ +--- +title: "Kubernetes via Helm Chart" +description: "Use our Helm chart to Install Infisical on your Kubernetes cluster" +--- +**Prerequisites** +- You have understanding of [Kubernetes](https://kubernetes.io/) +- Installed [Helm package manager](https://helm.sh/) version v3.11.3 or greater +- You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster + + + + +By deploying Infisical on Kubernetes, you can take advantage of its features to ensure that the application is fault-tolerant, highly available, and scalable. +To make the installation process easier and more streamlined, we have created a Helm chart that you can use to install Infisical on Kubernetes. + +Helm is a package manager for Kubernetes that simplifies the installation and management of Kubernetes applications. +With our Helm chart, you can easily install Infisical on Kubernetes, configure it to your liking, and scale it up or down as needed. + +## Install Infisical Helm repository + +```bash +helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/' + +helm repo update +``` + +## Add Helm values + +Create a values.yaml file to configure various installation settings, such as the docker image tags and environment variables for both the frontend and backend. To explore all configurable properties for your values file, [visit this page](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical). + +#### Set image tags + +By default, the application will use the latest tag to retrieve the required Docker images, which may be appropriate for most cases. +However, it's important to specify a particular version of Infisical during installation to prevent any significant updates from disrupting your deployment. +View [properties for frontend and backend](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical#parameters). + + +To determine the appropriate versions to use for the docker images, follow the links bellow +- [frontend Docker image](https://hub.docker.com/r/infisical/frontend/tags) +- [backend Docker image](https://hub.docker.com/r/infisical/backend/tags) + +```yaml simple-values-example.yaml +frontend: + name: frontend + replicaCount: 2 + image: + repository: infisical/frontend + tag: "v0.1.3" + pullPolicy: Always + +backend: + replicaCount: 2 + image: + repository: infisical/backend + tag: "v0.1.3" + pullPolicy: Always +``` + +#### Configure environment variables + +You can configure environment variables for the frontend and backend in your Helm values file under the property `frontendEnvironmentVariables` and `backendEnvironmentVariables` respectively. View configurable [environment variables](../configuration/envars). + +Infisical requires the following backend environment variables to be defined: _`ENCRYPTION_KEY`_, _`JWT_SIGNUP_SECRET`_, _`JWT_REFRESH_SECRET`_, _`JWT_AUTH_SECRET`_, _`JWT_MFA_SECRET`_ and _`JWT_SERVICE_SECRET`_. + + +Each of the above environment variables can be generated by running the command `openssl rand -hex 16` in your terminal. + + +However, when the above environment variables are not defined, the Helm chart +will automatically generate these environment variables for you. The generated environment variables will be saved to a Kubernetes secret and will be preserved between upgrades or uninstalls. + +```yaml simple-values-example.yaml +... +backendEnvironmentVariables: + HTTPS_ENABLED: true + INVITE_ONLY_SIGNUP: false + ... +``` + + + Infisical assumes that you have configured HTTPS. If you didn't configure HTTPS, set `HTTPS_ENABLED` to `false` in the backend environment variable to avoid frequent logouts. + + +#### Routing external traffic +By default, Infisical takes all traffic coming to your external load balancer's IP address and routes them Infisical's services. +Infisical uses Nginx to route external traffic. You can install Nginx along with Infisical by setting `ingress.enabled` to `true` in the Helm values file. View all [properties for ingress](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical). + +```yaml simple-values-example.yaml +... +ingress: + nginx: + enabled: false #<-- if you would like to install nginx along with Infisical +``` + +#### Database +Infisical uses a document database as its persistence layer. With this Helm chart, you spin up a MongoDB instance power by Bitnami along side other Infisical services in your cluster. +When persistence is enabled, the data will be stored a Kubernetes Persistence Volume. View all [properties for mongodb](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical). + +```yaml simple-values-example.yaml +mongodb: + enabled: false + persistence: + enabled: false +``` + +To increase data redundancy, we recommend that you use a managed document database service such as AWS Document DB, MongoDB or similar services instead. +Managed database connection string can be set in the `backendEnvironmentVariables`. + +#### Example helm values +```yaml simple-values-example.yaml +frontend: + name: frontend + replicaCount: 2 + image: + repository: infisical/frontend + tag: "v0.1.3" + pullPolicy: Always + +backend: + replicaCount: 2 + image: + repository: infisical/backend + tag: "v0.1.3" + pullPolicy: Always + +backendEnvironmentVariables: + HTTPS_ENABLED: true + +ingress: + nginx: + enabled: false #<-- if you would like to install nginx along with Infisical + +``` + + + ```yaml values.yaml + ingress: + nginx: + enabled: true + + frontend: + enabled: true + name: frontend + podAnnotations: {} + deploymentAnnotations: {} + replicaCount: 4 + image: + repository: infisical/frontend + tag: "v0.1.3" + pullPolicy: IfNotPresent + kubeSecretRef: null + service: + annotations: {} + type: ClusterIP + nodePort: "" + + backend: + enabled: true + name: backend + podAnnotations: {} + deploymentAnnotations: {} + replicaCount: 4 + image: + repository: infisical/backend + tag: "v0.1.3" + pullPolicy: IfNotPresent + kubeSecretRef: null + service: + annotations: {} + type: ClusterIP + nodePort: "" + + # View all environment variables https://infisical.com/docs/self-hosting/configuration/envars + backendEnvironmentVariables: + MONGO_URL: <> + HTTPS_ENABLED: <> + + + ## Mongo DB persistence + mongodb: + enabled: false + persistence: + enabled: false + + ingress: + enabled: true + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" # <-- if you are setting up HTTPS + hostName: app.infisical.com ## <- Replace with your own domain + frontend: + path: / + pathType: Prefix + backend: + path: /api + pathType: Prefix + tls: # <-- if you are setting up HTTPS + - secretName: echo-tls + hosts: + - app.infisical.com + + ``` + + +## Install the Helm chart + +By default, the helm chart will be installed on your default namespace. If you wish to install the Chart on a different namespace, you may specify +that by adding the `--namespace ` to your `helm install` command. + +```bash +## Installs to default namespace +helm install infisical-helm-charts/infisical --generate-name --values /path/to/values.yaml +``` + +## Access Infisical +Allow 3-5 minutes for the deployment to complete. Once done, you should now be able to access Infisical on the IP address exposed via Ingress on your load balancer. If you are not sure what the IP address is run `kubectl get ingress` to view the external IP address exposing Infisical. + + +Once installation is complete, you will have to create the first account. No default account is provided. + \ No newline at end of file diff --git a/docs/self-hosting/deployment-options/render.mdx b/docs/self-hosting/deployment-options/render.mdx new file mode 100644 index 000000000..17faf060a --- /dev/null +++ b/docs/self-hosting/deployment-options/render.mdx @@ -0,0 +1,21 @@ +--- +title: "Render.com" +description: "Learn to install Infisical Render.com" +--- + +**Prerequisites** +- An account at Render.com +- A document DB instance + +Deploying on Render is one of the quickest ways to have Infisical running in production. +Before you start deployment, you will need to obtain document db connection string. This will be used for `MONGO_URL` environment variable required during installation. + +You can create a document db database using services such as [MongoDB](https://www.mongodb.com/), [AWS DocumentDB](https://aws.amazon.com/documentdb/), and others. Once done, click the link below to start deployment. + +### **[Deploy to Render](https://render.com/deploy?repo=https://github.com/Infisical/infisical)** + +# + + +Once installation is complete, you will have to create the first account. No default account is provided. + \ No newline at end of file diff --git a/docs/self-hosting/deployment-options/standalone-infisical.mdx b/docs/self-hosting/deployment-options/standalone-infisical.mdx new file mode 100644 index 000000000..6cff9ff9c --- /dev/null +++ b/docs/self-hosting/deployment-options/standalone-infisical.mdx @@ -0,0 +1,76 @@ +--- +title: "Docker" +description: "Learn to install Infisical purely on docker" +--- + +The Infisical standalone version combines all the essential components of the application into a single container, making deployment and management more straightforward than using Kubernetes or Docker Compose. + +Since all the components are bundled into one image, running this version of Infisical requires a minimum of **230MB of memory**. + +This guide assumes you have basic knowledge of Docker and have it installed on your system. If you don't have Docker installed, please follow the official installation guide: https://docs.docker.com/get-docker/ + +## Pull the Infisical Docker image + +Open your terminal or command prompt and enter the following command to pull the Infisical Docker image: + +``` +docker pull infisical/infisical:latest +``` + +## Run with docker +The Infisical Docker image requires several required environment variables. +Add the required environment variables listed below to your docker run command. View [all configurable environment variables](../configuration/envars) + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + Must be a random 16 byte hex string. Can be generated with `openssl rand -hex 16` + + + + *TLS based connection string is not yet supported + + + +Once you have added the required environment variables to your docker run command, execute it in your terminal. + +```bash +docker run -p 80:80 \ +-e ENCRYPTION_KEY=f40c9178624764ad85a6830b37ce239a \ +-e JWT_SIGNUP_SECRET=38ea90fb7998b92176080f457d890392 \ +-e JWT_REFRESH_SECRET=7764c7bbf3928ad501591a3e005eb364 \ +-e JWT_AUTH_SECRET=5239fea3a4720c0e524f814a540e14a2 \ +-e JWT_SERVICE_SECRET=8509fb8b90c9b53e9e61d1e35826dcb5 \ +-e MONGO_URL="<>" \ +infisical/infisical:latest +``` + + + The sample environment variables listed above are only to be used as an example and should not be used in production + + +## Verify the installation: +Once the container is running, open a web browser and navigate to http://localhost:80. That's it! You have successfully installed the Infisical application using a single Docker image. + + +Once installation is complete, you will have to create the first account. No default account is provided. + \ No newline at end of file diff --git a/docs/self-hosting/faq.mdx b/docs/self-hosting/faq.mdx new file mode 100644 index 000000000..6cef86b9c --- /dev/null +++ b/docs/self-hosting/faq.mdx @@ -0,0 +1,27 @@ +--- +title: "FAQ" +description: "Frequently Asked Questions about Infisical self hosting" +--- + +Frequently asked questions about self hosted instance of Infisical can be found on this page. +If you can't find the answer you are looking for, please create an issue on our GitHub repository or join our Slack channel for additional support. + + +This issue is typically seen when you haven't set up SSL for your self hosted instance of Infisical. When SSL is not enabled, you can't receive secure cookies, preventing the session data to not be saved. + +To fix this, we highly recommend that you set up SSL for your instance. +However, in the event you choose to use Infisical without SSL, you can do so by setting the `HTTPS_ENABLED` environment variable to `"false"` for the backend application. + +[Learn more about secure cookies](https://really-simple-ssl.com/definition/what-are-secure-cookies/) + + + + Infisical leverages the robust container orchestration capabilities of Kubernetes and the inherent high availability features of Bitnami MongoDB to ensure resilience and fault tolerance. + By deploying multiple replicas of Infisical application on Kubernetes, operations can continue even if a single instance fails. + + Additionally, Bitnami MongoDB supports replica sets, which provide data redundancy and automatic failover for the underlying database. + Kubernetes Services facilitate load balancing, effectively distributing traffic across your application's instances and ensuring optimal performance. + The combination of Kubernetes' self-healing mechanisms and Bitnami MongoDB's failover capabilities work together to create a highly available and fault-tolerant application capable of recovering gracefully from unexpected failures. + + To further increase data redundancy, we recommend that you use a managed MongoDB service for your self hosted instance of Infisical. + diff --git a/docs/self-hosting/overview.mdx b/docs/self-hosting/overview.mdx index 995fe93a0..4bfba612c 100644 --- a/docs/self-hosting/overview.mdx +++ b/docs/self-hosting/overview.mdx @@ -1,103 +1,32 @@ --- -title: "Deployment options" +title: "Introduction" description: "Explore deployment options for self hosting Infisical" --- To meet various compliance requirements, you may want to self-host Infisical instead of using [Infisical Cloud](https://app.infisical.com/). -Self-hosted Infisical allows you to maintain your sensitive information within your own infrastructure and network, ensuring complete control over your data. +Self-hosted Infisical allows you to maintain your sensitive information within your own infrastructure and network, ensuring complete control over your data. +Choose from a variety of deployment options listed below to get started. - - - - This deployment option will use AWS Cloudformation to auto deploy an instance of Infisical on a single EC2 via Docker Compose. - - **Resources that will be provisioned** - - 1 EC2 instance - - 1 DocumentDB cluster - - 1 DocumentDB instance - - Security groups - - - - - - - - This deployment option is highly available - Coming soon - - - This deployment option is highly available - - **Prerequisites** - - You have understanding of [Kubernetes](https://kubernetes.io/) - - You have understanding of [Helm package manager](https://helm.sh/) - - You have [kubectl](https://kubernetes.io/docs/reference/kubectl/kubectl/) installed and connected to your kubernetes cluster - - - #### 1. Install Infisical Helm repository - - ```bash - helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/' - - helm repo update - ``` - - #### 2. Install the Helm chart - - By default, the helm chart will be installed on your default namespace. If you wish to install the Chart on a different namespace, you may specify - that by adding the `--namespace ` to your `helm install` command. - - ```bash - ## Installs to default namespace - helm install infisical-helm-charts/infisical --generate-name - ``` - - #### 3. Access Infisical - Allow 3-5 minutes for the deployment to complete. Once done, you should now be able to access Infisical on the IP address exposed via Ingress on your load balancer. If you are not sure what the IP address is run `kubectl get ingress` to view the external IP address exposing Infisical. - - #### Custom configuration - To configure environment variables, database and deployments, you'll need to set the parameters in a `values.yaml` file. To view all available parameters [visit here](https://github.com/Infisical/infisical/tree/main/helm-charts/infisical#parameters) - - - - 1. Install Docker on your VM - - ```bash - # Example in ubuntu - apt-get update - apt-get upgrade - apt install docker-compose - ``` - - 2. Download the required files - - ```bash - # Download env file template - wget -O .env https://raw.githubusercontent.com/Infisical/infisical/main/.env.example - - # Download docker compose template - wget -O docker-compose.yml https://raw.githubusercontent.com/Infisical/infisical/main/docker-compose.yml - - # Download nginx config - mkdir nginx && wget -O ./nginx/default.conf https://raw.githubusercontent.com/Infisical/infisical/main/nginx/default.dev.conf - ``` - - 3. Tweak the `.env` according to your preferences. Refer to the available [environment variables](/self-hosting/configuration/envars) - - ```bash - # update environment variables like mongo login - nano .env - ``` - - 4. Get the service up and running. - - ```bash - # Start up services in detached mode - docker-compose -f docker-compose.yml up -d - ``` - - 5. Your Infisical installation is complete and should be running on [http://localhost:80](http://localhost:80). Please note that the containers are not exposed to the internet and only bind to the localhost. It's up to you to configure a firewall, SSL certificates, and implement any additional security measures. - - - + + Use our Helm chart to Install Infisical on your Kubernetes cluster + + + + Automatically create and deploy Infisical on to a Kubernetes cluster + + + Use our standalone docker image to deploy on Fly.io + + + Install on Render using our standalone docker image + + + Install infisical with just a few clicks using our Cloud Formation template + + + Install Infisical using our Docker Compose template + + + Use the fully packaged, single docker image Infisical to deploy anywhere + + \ No newline at end of file diff --git a/docs/spec.yaml b/docs/spec.yaml index b57caf89a..89f01e8da 100644 --- a/docs/spec.yaml +++ b/docs/spec.yaml @@ -940,7 +940,11 @@ paths: /api/v1/invite-org/signup: post: description: '' - parameters: [] + parameters: + - name: host + in: header + schema: + type: string responses: '200': description: OK @@ -1277,6 +1281,12 @@ paths: example: any targetEnvironment: example: any + targetEnvironmentId: + example: any + targetService: + example: any + targetServiceId: + example: any owner: example: any path: @@ -1415,11 +1425,75 @@ paths: required: true schema: type: string + - name: teamId + in: query + schema: + type: string responses: '200': description: OK '400': description: Bad Request + /api/v1/integration-auth/{integrationAuthId}/teams: + get: + description: '' + parameters: + - name: integrationAuthId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + /api/v1/integration-auth/{integrationAuthId}/vercel/branches: + get: + description: '' + parameters: + - name: integrationAuthId + in: path + required: true + schema: + type: string + - name: appId + in: query + schema: + type: string + responses: + '200': + description: OK + /api/v1/integration-auth/{integrationAuthId}/railway/environments: + get: + description: '' + parameters: + - name: integrationAuthId + in: path + required: true + schema: + type: string + - name: appId + in: query + schema: + type: string + responses: + '200': + description: OK + /api/v1/integration-auth/{integrationAuthId}/railway/services: + get: + description: '' + parameters: + - name: integrationAuthId + in: path + required: true + schema: + type: string + - name: appId + in: query + schema: + type: string + responses: + '200': + description: OK /api/v2/signup/complete-account/signup: post: description: '' @@ -1771,10 +1845,20 @@ paths: items: $ref: '#/components/schemas/Project' description: Projects of organization - '400': - description: Bad Request security: - apiKeyAuth: [] + /api/v2/organizations/{organizationId}/service-accounts: + get: + description: '' + parameters: + - name: organizationId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK /api/v2/workspace/{workspaceId}/environments: post: description: '' @@ -2467,8 +2551,6 @@ paths: responses: '200': description: OK - '400': - description: Bad Request requestBody: content: application/json: @@ -2503,8 +2585,139 @@ paths: responses: '200': description: OK + /api/v2/service-accounts/me: + get: + description: '' + parameters: [] + responses: + '200': + description: OK + /api/v2/service-accounts/{serviceAccountId}: + get: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + delete: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + /api/v2/service-accounts/: + post: + description: '' + parameters: [] + responses: + '200': + description: OK + /api/v2/service-accounts/{serviceAccountId}/name: + patch: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + requestBody: + content: + application/json: + schema: + type: object + properties: + name: + example: any + /api/v2/service-accounts/{serviceAccountId}/permissions/workspace: + get: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + post: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK '400': description: Bad Request + requestBody: + content: + application/json: + schema: + type: object + properties: + environment: + example: any + workspaceId: + example: any + read: + example: any + write: + example: any + encryptedKey: + example: any + nonce: + example: any + /api/v2/service-accounts/{serviceAccountId}/permissions/workspace/{serviceAccountWorkspacePermissionId}: + delete: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + - name: serviceAccountWorkspacePermissionId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + /api/v2/service-accounts/{serviceAccountId}/keys: + get: + description: '' + parameters: + - name: serviceAccountId + in: path + required: true + schema: + type: string + - name: workspaceId + in: query + schema: + type: string + responses: + '200': + description: OK /api/v2/api-key/: get: description: '' @@ -2546,6 +2759,182 @@ paths: description: OK '400': description: Bad Request + /api/v3/secrets/: + get: + description: '' + parameters: + - name: workspaceId + in: query + schema: + type: string + - name: environment + in: query + schema: + type: string + responses: + '200': + description: OK + /api/v3/secrets/{secretName}: + post: + description: '' + parameters: + - name: secretName + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + requestBody: + content: + application/json: + schema: + type: object + properties: + workspaceId: + example: any + environment: + example: any + type: + example: any + secretKeyCiphertext: + example: any + secretKeyIV: + example: any + secretKeyTag: + example: any + secretValueCiphertext: + example: any + secretValueIV: + example: any + secretValueTag: + example: any + secretCommentCiphertext: + example: any + secretCommentIV: + example: any + secretCommentTag: + example: any + get: + description: '' + parameters: + - name: secretName + in: path + required: true + schema: + type: string + - name: workspaceId + in: query + schema: + type: string + - name: environment + in: query + schema: + type: string + - name: type + in: query + schema: + type: string + responses: + '200': + description: OK + patch: + description: '' + parameters: + - name: secretName + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + requestBody: + content: + application/json: + schema: + type: object + properties: + workspaceId: + example: any + environment: + example: any + type: + example: any + secretValueCiphertext: + example: any + secretValueIV: + example: any + secretValueTag: + example: any + delete: + description: '' + parameters: + - name: secretName + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + requestBody: + content: + application/json: + schema: + type: object + properties: + workspaceId: + example: any + environment: + example: any + type: + example: any + /api/v3/workspaces/{workspaceId}/secrets/blind-index-status: + get: + description: '' + parameters: + - name: workspaceId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + /api/v3/workspaces/{workspaceId}/secrets: + get: + description: '' + parameters: + - name: workspaceId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + /api/v3/workspaces/{workspaceId}/secrets/names: + post: + description: '' + parameters: + - name: workspaceId + in: path + required: true + schema: + type: string + responses: + '200': + description: OK + requestBody: + content: + application/json: + schema: + type: object + properties: + secretsToUpdate: + example: any /api/status: get: description: '' diff --git a/ecosystem.config.js b/ecosystem.config.js new file mode 100644 index 000000000..5c8cc6832 --- /dev/null +++ b/ecosystem.config.js @@ -0,0 +1,32 @@ +module.exports = { + apps: [ + { + name: 'frontend', + script: "./scripts/start.sh", + instances: 1, + cwd: "./app", + interpreter: 'sh', + exec_mode: "fork", + autorestart: true, + watch: false, + max_memory_restart: '500M', + }, + { + name: 'backend', + script: 'npm', + args: 'run start', + cwd: "./backend", + instances: 1, + exec_mode: "fork", + autorestart: true, + watch: false, + max_memory_restart: '500M', + }, + { + name: "nginx", + script: "nginx", + args: "-g 'daemon off;'", + exec_interpreter: "none", + }, + ], +}; \ No newline at end of file diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 520f0fb7f..b33d63b4f 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -28,6 +28,8 @@ ARG POSTHOG_HOST ENV NEXT_PUBLIC_POSTHOG_HOST $POSTHOG_HOST ARG POSTHOG_API_KEY ENV NEXT_PUBLIC_POSTHOG_API_KEY $POSTHOG_API_KEY +ARG INTERCOM_ID +ENV NEXT_PUBLIC_INTERCOM_ID $INTERCOM_ID # Build RUN npm run build @@ -46,6 +48,9 @@ VOLUME /app/.next/cache/images ARG POSTHOG_API_KEY ENV NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY \ BAKED_NEXT_PUBLIC_POSTHOG_API_KEY=$POSTHOG_API_KEY +ARG INTERCOM_ID +ENV NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID \ + BAKED_NEXT_PUBLIC_INTERCOM_ID=$INTERCOM_ID COPY --chown=nextjs:nodejs --chmod=555 scripts ./scripts COPY --from=builder /app/public ./public diff --git a/frontend/README.md b/frontend/README.md index d97bb4bef..a0bcd1ef0 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -8,7 +8,7 @@ Please ensure you have Docker and Docker Compose installed for your OS. - `CD` into the repo - run command `docker-compose -f docker-compose.dev.yml up --build --force-recreate` -- Visit localhost:3000 and the website should be live +- Visit localhost:8080 and the website should be live ### Steps to shutdown this Docker compose diff --git a/frontend/next-i18next.config.js b/frontend/next-i18next.config.js deleted file mode 100644 index e8046b755..000000000 --- a/frontend/next-i18next.config.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check - -/** - * @type {import('next-i18next').UserConfig} - */ -module.exports = { - // https://www.i18next.com/overview/configuration-options#logging - debug: false, - i18n: { - defaultLocale: "en", - locales: ["en", "ko", "fr", "pt-BR", "pt-PT", "es"], - }, - fallbackLng: { - default: ["en"], - }, - - reloadOnPrerender: process.env.NODE_ENV === "development", - - /** - * @link https://github.com/i18next/next-i18next#6-advanced-configuration - */ - // saveMissing: false, - // strictMode: true, - // serializeConfig: false, - // react: { useSuspense: false } -}; \ No newline at end of file diff --git a/frontend/next.config.js b/frontend/next.config.js index 5e7c81270..0816161ff 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -1,84 +1,87 @@ - // @ts-check /** * @type {import('next').NextConfig} **/ -const { i18n } = require("./next-i18next.config.js"); const path = require('path'); const ContentSecurityPolicy = ` default-src 'self'; - script-src 'self' https://app.posthog.com https://js.stripe.com https://api.stripe.com 'unsafe-inline' 'unsafe-eval'; + script-src 'self' https://app.posthog.com https://js.stripe.com https://api.stripe.com https://widget.intercom.io https://js.intercomcdn.com 'unsafe-inline' 'unsafe-eval'; style-src 'self' https://rsms.me 'unsafe-inline'; child-src https://api.stripe.com; - frame-src https://js.stripe.com/ https://api.stripe.com; - connect-src 'self' https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com; - img-src 'self' https://*.stripe.com https://i.ytimg.com/ data:; - media-src; - font-src 'self' https://maxcdn.bootstrapcdn.com https://rsms.me https://fonts.gstatic.com; + frame-src https://js.stripe.com/ https://api.stripe.com https://www.youtube.com/; + connect-src 'self' wss://nexus-websocket-a.intercom.io https://api-iam.intercom.io https://api.heroku.com/ https://id.heroku.com/oauth/authorize https://id.heroku.com/oauth/token https://checkout.stripe.com https://app.posthog.com https://api.stripe.com; + img-src 'self' https://static.intercomassets.com https://js.intercomcdn.com https://downloads.intercomcdn.com https://*.stripe.com https://i.ytimg.com/ data:; + media-src https://js.intercomcdn.com; + font-src 'self' https://fonts.intercomcdn.com/ https://maxcdn.bootstrapcdn.com https://rsms.me https://fonts.gstatic.com; `; // You can choose which headers to add to the list // after learning more below. const securityHeaders = [ { - key: "X-DNS-Prefetch-Control", - value: "on", + key: 'X-DNS-Prefetch-Control', + value: 'on' }, { - key: "Strict-Transport-Security", - value: "max-age=63072000; includeSubDomains; preload", + key: 'Strict-Transport-Security', + value: 'max-age=63072000; includeSubDomains; preload' }, { - key: "X-XSS-Protection", - value: "1; mode=block", + key: 'X-XSS-Protection', + value: '1; mode=block' }, { - key: "X-Frame-Options", - value: "SAMEORIGIN", + key: 'X-Frame-Options', + value: 'SAMEORIGIN' }, { - key: "Permissions-Policy", - value: "camera=(), microphone=()", + key: 'Permissions-Policy', + value: 'camera=(), microphone=()' }, { - key: "X-Content-Type-Options", - value: "nosniff", + key: 'X-Content-Type-Options', + value: 'nosniff' }, { - key: "Referrer-Policy", - value: "strict-origin-when-cross-origin", + key: 'Referrer-Policy', + value: 'strict-origin-when-cross-origin' }, { - key: "Content-Security-Policy", - value: ContentSecurityPolicy.replace(/\s{2,}/g, " ").trim(), - }, + key: 'Content-Security-Policy', + value: ContentSecurityPolicy.replace(/\s{2,}/g, ' ').trim() + } ]; module.exports = { - output: "standalone", + output: 'standalone', + i18n: { + locales: ['en', 'ko', 'fr', 'pt-BR', 'pt-PT', 'es'], + defaultLocale: 'en' + }, async headers() { return [ { // Apply these headers to all routes in your application. - source: "/:path*", - headers: securityHeaders, - }, + source: '/:path*', + headers: securityHeaders + } ]; }, - webpack: (config, { isServer, webpack }) => { // config + webpack: (config, { isServer, webpack }) => { + // config config.module.rules.push({ test: /\.wasm$/, - loader: "base64-loader", - type: "javascript/auto", + loader: 'base64-loader', + type: 'javascript/auto' }); config.module.noParse = /\.wasm$/; config.module.rules.forEach((rule) => { (rule.oneOf || []).forEach((oneOf) => { - if (oneOf.loader && oneOf.loader.indexOf("file-loader") >= 0) { + if (oneOf.loader && oneOf.loader.indexOf('file-loader') >= 0) { oneOf.exclude.push(/\.wasm$/); } }); @@ -89,12 +92,9 @@ module.exports = { } // Perform customizations to webpack config - config.plugins.push( - new webpack.IgnorePlugin({ resourceRegExp: /\/__tests__\// }) - ); + config.plugins.push(new webpack.IgnorePlugin({ resourceRegExp: /\/__tests__\// })); // Important: return the modified config return config; - }, - i18n, + } }; diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ad099a70d..9b257843e 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -12,7 +12,7 @@ "@fortawesome/free-brands-svg-icons": "^6.1.2", "@fortawesome/free-regular-svg-icons": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.2", - "@fortawesome/react-fontawesome": "^0.1.19", + "@fortawesome/react-fontawesome": "^0.2.0", "@headlessui/react": "^1.7.7", "@hookform/resolvers": "^2.9.10", "@octokit/rest": "^19.0.7", @@ -24,11 +24,13 @@ "@radix-ui/react-hover-card": "^1.0.3", "@radix-ui/react-label": "^2.0.0", "@radix-ui/react-popover": "^1.0.3", + "@radix-ui/react-popper": "^1.1.1", "@radix-ui/react-progress": "^1.0.1", "@radix-ui/react-select": "^1.2.0", "@radix-ui/react-switch": "^1.0.1", "@radix-ui/react-tabs": "^1.0.2", "@radix-ui/react-toast": "^1.1.2", + "@radix-ui/react-tooltip": "^1.0.4", "@reduxjs/toolkit": "^1.8.3", "@stripe/react-stripe-js": "^1.16.3", "@stripe/stripe-js": "^1.46.0", @@ -42,17 +44,21 @@ "classnames": "^2.3.1", "cookies": "^0.8.0", "cva": "npm:class-variance-authority@^0.4.0", - "fs": "^0.0.1-security", + "framer-motion": "^6.2.3", + "fs": "^0.0.2", "gray-matter": "^4.0.3", "http-proxy": "^1.18.1", - "i18next": "^22.4.9", + "i18next": "^22.4.15", + "i18next-browser-languagedetector": "^7.0.1", + "i18next-http-backend": "^2.2.0", "infisical-node": "^1.0.37", "jspdf": "^2.5.1", "jsrp": "^0.2.4", + "jwt-decode": "^3.1.2", + "lottie-react": "^2.4.0", "markdown-it": "^13.0.1", "next": "^12.3.4", - "next-i18next": "^13.0.2", - "posthog-js": "^1.39.4", + "posthog-js": "^1.58.0", "query-string": "^7.1.3", "react": "^17.0.2", "react-beautiful-dnd": "^13.1.1", @@ -60,20 +66,20 @@ "react-dom": "^17.0.2", "react-grid-layout": "^1.3.4", "react-hook-form": "^7.43.0", - "react-i18next": "^12.1.1", + "react-i18next": "^12.2.2", "react-mailchimp-subscribe": "^2.1.3", "react-markdown": "^8.0.3", "react-redux": "^8.0.2", "react-table": "^7.8.0", "set-cookie-parser": "^2.5.1", - "sharp": "^0.31.2", + "sharp": "^0.32.0", "styled-components": "^5.3.7", "tailwind-merge": "^1.8.1", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", "uuid": "^8.3.2", "uuidv4": "^6.2.13", - "yaml": "^2.2.0", + "yaml": "^2.2.2", "yup": "^0.32.11" }, "devDependencies": { @@ -115,29 +121,18 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" } }, - "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@aw-web-design/x-default-browser": { "version": "1.4.88", "resolved": "https://registry.npmjs.org/@aw-web-design/x-default-browser/-/x-default-browser-1.4.88.tgz", @@ -151,9 +146,9 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "dependencies": { "@babel/highlight": "^7.18.6" }, @@ -162,32 +157,34 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", - "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.9.tgz", + "integrity": "sha512-FUGed8kfhyWvbYug/Un/VPJD41rDIgoVVcR+FuzhzOYyRz5uED+Gd3SLZml0Uw2l2aHFb7ZgdW5mGA3G2cCCnQ==", + "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", - "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", + "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", + "dev": true, "dependencies": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helpers": "^7.21.5", + "@babel/parser": "^7.21.8", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" }, "engines": { @@ -198,42 +195,14 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.9.tgz", + "integrity": "sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==", "dependencies": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -252,25 +221,25 @@ } }, "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.21.5.tgz", + "integrity": "sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==", "dev": true, "dependencies": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", + "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" @@ -282,41 +251,21 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz", - "integrity": "sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.8.tgz", + "integrity": "sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-replace-supers": "^7.21.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-split-export-declaration": "^7.18.6", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -326,13 +275,14 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", - "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.8.tgz", + "integrity": "sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.2.1" + "regexpu-core": "^5.3.1", + "semver": "^6.3.0" }, "engines": { "node": ">=6.9.0" @@ -358,65 +308,21 @@ "@babel/core": "^7.4.0-0" } }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.18.6" - }, + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", + "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "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==", "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -434,41 +340,42 @@ } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz", - "integrity": "sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.5.tgz", + "integrity": "sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==", "dev": true, "dependencies": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "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==", "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", + "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-environment-visitor": "^7.21.5", + "@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.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -487,9 +394,10 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==", + "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==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -513,28 +421,29 @@ } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.21.5.tgz", + "integrity": "sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==", "dev": true, "dependencies": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "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==", + "dev": true, "dependencies": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -564,9 +473,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "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==", "engines": { "node": ">=6.9.0" } @@ -580,9 +489,10 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==", + "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==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -603,13 +513,14 @@ } }, "node_modules/@babel/helpers": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", - "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", + "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -629,9 +540,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.9.tgz", + "integrity": "sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==", "bin": { "parser": "bin/babel-parser.js" }, @@ -706,12 +617,12 @@ } }, "node_modules/@babel/plugin-proposal-class-static-block": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz", - "integrity": "sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-class-static-block": "^7.14.5" }, @@ -854,9 +765,9 @@ } }, "node_modules/@babel/plugin-proposal-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz", - "integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2", @@ -887,13 +798,13 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", - "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" }, @@ -932,6 +843,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", @@ -984,12 +907,12 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", - "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.21.4.tgz", + "integrity": "sha512-l9xd3N+XG4fZRxEP3vXdK6RW7vN1Uf5dxzRC/09wV86wqZ/YYQooBIGNsiRdfNR3/q2/5pPzV4B54J/9ctX5jw==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1013,6 +936,18 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -1026,11 +961,12 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", + "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1142,12 +1078,12 @@ } }, "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", + "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==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0" + "@babel/helper-plugin-utils": "^7.20.2" }, "engines": { "node": ">=6.9.0" @@ -1157,12 +1093,12 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz", + "integrity": "sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1204,9 +1140,9 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz", - "integrity": "sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" @@ -1219,15 +1155,15 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz", - "integrity": "sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-replace-supers": "^7.20.7", @@ -1242,12 +1178,12 @@ } }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz", + "integrity": "sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "@babel/template": "^7.20.7" }, "engines": { @@ -1258,9 +1194,9 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", - "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", + "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" @@ -1320,12 +1256,12 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.19.0.tgz", - "integrity": "sha512-sgeMlNaQVbCSpgLSKP4ZZKfsJVnFnNQlUSk6gPYzR/q7tzCgQF2t8RBKAP6cKJeZdveei7Q7Jm527xepI8lNLg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz", + "integrity": "sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-flow": "^7.18.6" }, "engines": { @@ -1336,12 +1272,12 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz", + "integrity": "sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1414,14 +1350,14 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", - "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz", + "integrity": "sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==", "dev": true, "dependencies": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-simple-access": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1512,9 +1448,9 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", - "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", + "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", "dev": true, "dependencies": { "@babel/helper-plugin-utils": "^7.20.2" @@ -1557,16 +1493,16 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz", - "integrity": "sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.5.tgz", + "integrity": "sha512-ELdlq61FpoEkHO6gFRpfj0kUgSwQTGoaEU8eMRoS8Dv3v6e7BjEAj5WMtIBRdHUeAioMhKP5HyxNzNnP+heKbA==", "dev": true, "dependencies": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7" + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1607,12 +1543,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz", + "integrity": "sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "regenerator-transform": "^0.15.1" }, "engines": { @@ -1637,6 +1573,26 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.4.tgz", + "integrity": "sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-transform-shorthand-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", @@ -1714,12 +1670,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz", - "integrity": "sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", + "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", "dev": true, "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-typescript": "^7.20.0" }, @@ -1731,12 +1688,12 @@ } }, "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.21.5.tgz", + "integrity": "sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.21.5" }, "engines": { "node": ">=6.9.0" @@ -1762,31 +1719,31 @@ } }, "node_modules/@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.5.tgz", + "integrity": "sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", + "@babel/plugin-proposal-async-generator-functions": "^7.20.7", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.21.0", "@babel/plugin-proposal-dynamic-import": "^7.18.6", "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.0", "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", @@ -1794,6 +1751,7 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -1803,40 +1761,40 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.21.5", + "@babel/plugin-transform-async-to-generator": "^7.20.7", "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-block-scoping": "^7.21.0", + "@babel/plugin-transform-classes": "^7.21.0", + "@babel/plugin-transform-computed-properties": "^7.21.5", + "@babel/plugin-transform-destructuring": "^7.21.3", "@babel/plugin-transform-dotall-regex": "^7.18.6", "@babel/plugin-transform-duplicate-keys": "^7.18.9", "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-for-of": "^7.21.5", "@babel/plugin-transform-function-name": "^7.18.9", "@babel/plugin-transform-literals": "^7.18.9", "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-amd": "^7.20.11", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", + "@babel/plugin-transform-modules-systemjs": "^7.20.11", "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", "@babel/plugin-transform-new-target": "^7.18.6", "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-parameters": "^7.21.3", "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.21.5", "@babel/plugin-transform-reserved-words": "^7.18.6", "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-spread": "^7.20.7", "@babel/plugin-transform-sticky-regex": "^7.18.6", "@babel/plugin-transform-template-literals": "^7.18.9", "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-escapes": "^7.21.5", "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", + "@babel/types": "^7.21.5", "babel-plugin-polyfill-corejs2": "^0.3.3", "babel-plugin-polyfill-corejs3": "^0.6.0", "babel-plugin-polyfill-regenerator": "^0.4.1", @@ -1850,24 +1808,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/preset-flow": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.18.6.tgz", - "integrity": "sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.21.4.tgz", + "integrity": "sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-flow-strip-types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-transform-flow-strip-types": "^7.21.0" }, "engines": { "node": ">=6.9.0" @@ -1913,14 +1862,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.5.tgz", + "integrity": "sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==", "dev": true, "dependencies": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-typescript": "^7.18.6" + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", + "@babel/plugin-transform-typescript": "^7.21.3" }, "engines": { "node": ">=6.9.0" @@ -1930,9 +1881,9 @@ } }, "node_modules/@babel/register": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", - "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.21.0.tgz", + "integrity": "sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw==", "dev": true, "dependencies": { "clone-deep": "^4.0.1", @@ -2066,10 +2017,16 @@ "semver": "bin/semver" } }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "node_modules/@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "dependencies": { "regenerator-runtime": "^0.13.11" }, @@ -2078,31 +2035,31 @@ } }, "node_modules/@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", + "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", - "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", + "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.5", + "@babel/helper-environment-visitor": "^7.21.5", + "@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.20.7", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.5", + "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -2110,33 +2067,12 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@babel/traverse/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", + "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "dependencies": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" }, @@ -2176,126 +2112,90 @@ } }, "node_modules/@emotion/babel-plugin": { - "version": "11.10.2", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz", - "integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "dependencies": { "@babel/helper-module-imports": "^7.16.7", - "@babel/plugin-syntax-jsx": "^7.17.12", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/serialize": "^1.1.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "4.0.13" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@emotion/babel-plugin/node_modules/@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - }, - "node_modules/@emotion/babel-plugin/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "stylis": "4.2.0" } }, "node_modules/@emotion/cache": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz", - "integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "dependencies": { - "@emotion/memoize": "^0.8.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "stylis": "4.0.13" + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, - "node_modules/@emotion/cache/node_modules/@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - }, "node_modules/@emotion/css": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.10.0.tgz", - "integrity": "sha512-dH9f+kSCucc8ilMg0MUA1AemabcyzYpe5EKX24F528PJjD7HyIY/VBNJHxfUdc8l400h2ncAjR6yEDu+DBj2cg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.0.tgz", + "integrity": "sha512-m4g6nKzZyiKyJ3WOfdwrBdcujVcpaScIWHAnyNKPm/A/xJKwfXPfQAbEVi1kgexWTDakmg+r2aDj0KvnMTo4oQ==", "dependencies": { - "@emotion/babel-plugin": "^11.10.0", - "@emotion/cache": "^11.10.0", - "@emotion/serialize": "^1.1.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - }, - "peerDependenciesMeta": { - "@babel/core": { - "optional": true - } + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" } }, "node_modules/@emotion/hash": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", - "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "node_modules/@emotion/is-prop-valid": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz", - "integrity": "sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, "dependencies": { - "@emotion/memoize": "^0.7.4" + "@emotion/memoize": "0.7.4" } }, + "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@emotion/memoize": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", - "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" }, "node_modules/@emotion/serialize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz", - "integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "dependencies": { - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/unitless": "^0.8.0", - "@emotion/utils": "^1.2.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", "csstype": "^3.0.2" } }, - "node_modules/@emotion/serialize/node_modules/@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - }, - "node_modules/@emotion/serialize/node_modules/@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" - }, "node_modules/@emotion/server": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.10.0.tgz", - "integrity": "sha512-MTvJ21JPo9aS02GdjFW4nhdwOi2tNNpMmAM/YED0pkxzjDNi5WbiTwXqaCnvLc2Lr8NFtjhT0az1vTJyLIHYcw==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.11.0.tgz", + "integrity": "sha512-6q89fj2z8VBTx9w93kJ5n51hsmtYuFPtZgnc1L8VzRx9ti4EU6EyvF6Nn1H1x3vcCQCF7u2dB2lY4AYJwUW4PA==", "dependencies": { - "@emotion/utils": "^1.2.0", + "@emotion/utils": "^1.2.1", "html-tokenize": "^2.0.0", "multipipe": "^1.0.2", "through": "^2.3.8" @@ -2310,9 +2210,9 @@ } }, "node_modules/@emotion/sheet": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz", - "integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "node_modules/@emotion/stylis": { "version": "0.8.5", @@ -2320,33 +2220,81 @@ "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" }, "node_modules/@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "dev": true, "peerDependencies": { "react": ">=16.8.0" } }, "node_modules/@emotion/utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", - "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" }, "node_modules/@emotion/weak-memoize": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", - "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", - "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", "cpu": [ "arm64" ], @@ -2359,15 +2307,327 @@ "node": ">=12" } }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -2388,27 +2648,10 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "node_modules/@eslint/eslintrc/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -2432,11 +2675,26 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/@eslint/eslintrc/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } }, "node_modules/@fal-works/esbuild-plugin-global-externals": { "version": "2.1.2", @@ -2476,78 +2734,78 @@ "integrity": "sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==" }, "node_modules/@fortawesome/fontawesome-common-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz", - "integrity": "sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==", "hasInstallScript": true, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz", - "integrity": "sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-brands-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.1.2.tgz", - "integrity": "sha512-b2eMfXQBsSxh52pcPtYchURQs6BWNh3zVTG8XH8Lv6V4kDhEg7D0kHN+K1SZniDiPb/e5tBlaygsinMUvetITA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz", + "integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.1.2.tgz", - "integrity": "sha512-xR4hA+tAwsaTHGfb+25H1gVU/aJ0Rzu+xIUfnyrhaL13yNQ7TWiI2RvzniAaB+VGHDU2a+Pk96Ve+pkN3/+TTQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz", + "integrity": "sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.2.tgz", - "integrity": "sha512-lTgZz+cMpzjkHmCwOG3E1ilUZrnINYdqMmrkv30EC3XbRsGlbIOL8H9LaNp5SV4g0pNJDfQ4EdTWWaMvdwyLiQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", "hasInstallScript": true, "dependencies": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" }, "engines": { "node": ">=6" } }, "node_modules/@fortawesome/react-fontawesome": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz", - "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", "dependencies": { "prop-types": "^15.8.1" }, "peerDependencies": { "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "react": ">=16.x" + "react": ">=16.3" } }, "node_modules/@headlessui/react": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.7.tgz", - "integrity": "sha512-BqDOd/tB9u2tA0T3Z0fn18ktw+KbVwMnkxxsGPIH2hzssrQhKB5n/6StZOyvLYP/FsYtvuXfi9I0YowKPv2c1w==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.14.tgz", + "integrity": "sha512-znzdq9PG8rkwcu9oQ2FwIy0ZFtP9Z7ycS+BAqJ3R5EIqC/0bJGvhT7193rFf+45i9nnPsYvCQVW4V/bB9Xc+gA==", "dependencies": { "client-only": "^0.0.1" }, @@ -2560,9 +2818,9 @@ } }, "node_modules/@hookform/resolvers": { - "version": "2.9.10", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.9.10.tgz", - "integrity": "sha512-JIL1DgJIlH9yuxcNGtyhsWX/PgNltz+5Gr6+8SX9fhXc/hPbEIk6wPI82nhgvp3uUb6ZfAM5mqg/x7KR7NAb+A==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.9.11.tgz", + "integrity": "sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ==", "peerDependencies": { "react-hook-form": "^7.0.0" } @@ -2581,29 +2839,6 @@ "node": ">=10.10.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", @@ -2691,15 +2926,6 @@ "node": ">=8" } }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@istanbuljs/schema": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", @@ -2710,38 +2936,38 @@ } }, "node_modules/@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, "dependencies": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.25.16" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/@jest/transform": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", - "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "dependencies": { "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "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.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" @@ -2806,12 +3032,12 @@ } }, "node_modules/@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "dependencies": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -2875,9 +3101,9 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dependencies": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -2904,9 +3130,9 @@ } }, "node_modules/@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", + "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.0", @@ -2914,23 +3140,34 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "dependencies": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" } }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "dev": true + }, "node_modules/@mdx-js/react": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.2.1.tgz", - "integrity": "sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", + "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", "dev": true, "dependencies": { "@types/mdx": "^2.0.0", @@ -2944,25 +3181,138 @@ "react": ">=16" } }, + "node_modules/@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "dependencies": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "dependencies": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "dependencies": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "dependencies": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "node_modules/@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "dependencies": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@ndelangen/get-tarball": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.7.tgz", + "integrity": "sha512-NqGfTZIZpRFef1GoVaShSSRwDC3vde3ThtTeqFdcYd6ipKqnfEVhjK2hUeHjCQUcptyZr2TONqcloFXM+5QBrQ==", + "dev": true, + "dependencies": { + "gunzip-maybe": "^1.4.2", + "pump": "^3.0.0", + "tar-fs": "^2.1.1" + } + }, "node_modules/@next/env": { "version": "12.3.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.4.tgz", "integrity": "sha512-H/69Lc5Q02dq3o+dxxy5O/oNxFsZpdL6WREtOOtOM1B/weonIwDXkekr1KV5DPVPr12IHFPrMrcJQ6bgPMfn7A==" }, "node_modules/@next/eslint-plugin-next": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.0.5.tgz", - "integrity": "sha512-H9U9B1dFnCDmylDZ6/dYt95Ie1Iu+SLBMcO6rkIGIDcj5UK+DNyMiWm83xWBZ1gREM8cfp5Srv1g6wqf8pM4lw==", + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.3.tgz", + "integrity": "sha512-5B0uOnh7wyUY9vNNdIA6NUvWozhrZaTMZOzdirYAefqD0ZBK5C/h3+KMYdCKrR7JrXGvVpWnHtv54b3dCzwICA==", "dev": true, "dependencies": { "glob": "7.1.7" } }, - "node_modules/@next/font": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.2.tgz", - "integrity": "sha512-NXGXGFGiOKEnvBIHq9cdFTKbHO2/4B3Zd9K27M7j1DioIQVar7oVRqZMYs0h3XMVEZLwjjkdAtqRPCzzd3RtXg==", - "dev": true + "node_modules/@next/eslint-plugin-next/node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@next/swc-android-arm-eabi": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.4.tgz", + "integrity": "sha512-cM42Cw6V4Bz/2+j/xIzO8nK/Q3Ly+VSlZJTa1vHzsocJRYz8KT6MrreXaci2++SIZCF1rVRCDgAg5PpqRibdIA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-android-arm64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.4.tgz", + "integrity": "sha512-5jf0dTBjL+rabWjGj3eghpLUxCukRhBcEJgwLedewEA/LJk2HyqCvGIwj5rH+iwmq1llCWbOky2dO3pVljrapg==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } }, "node_modules/@next/swc-darwin-arm64": { "version": "12.3.4", @@ -2979,6 +3329,156 @@ "node": ">= 10" } }, + "node_modules/@next/swc-darwin-x64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.4.tgz", + "integrity": "sha512-PPF7tbWD4k0dJ2EcUSnOsaOJ5rhT3rlEt/3LhZUGiYNL8KvoqczFrETlUx0cUYaXe11dRA3F80Hpt727QIwByQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-freebsd-x64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.4.tgz", + "integrity": "sha512-KM9JXRXi/U2PUM928z7l4tnfQ9u8bTco/jb939pdFUHqc28V43Ohd31MmZD1QzEK4aFlMRaIBQOWQZh4D/E5lQ==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm-gnueabihf": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.4.tgz", + "integrity": "sha512-3zqD3pO+z5CZyxtKDTnOJ2XgFFRUBciOox6EWkoZvJfc9zcidNAQxuwonUeNts6Xbm8Wtm5YGIRC0x+12YH7kw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.4.tgz", + "integrity": "sha512-kiX0vgJGMZVv+oo1QuObaYulXNvdH/IINmvdZnVzMO/jic/B8EEIGlZ8Bgvw8LCjH3zNVPO3mGrdMvnEEPEhKA==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.4.tgz", + "integrity": "sha512-EETZPa1juczrKLWk5okoW2hv7D7WvonU+Cf2CgsSoxgsYbUCZ1voOpL4JZTOb6IbKMDo6ja+SbY0vzXZBUMvkQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.4.tgz", + "integrity": "sha512-4csPbRbfZbuWOk3ATyWcvVFdD9/Rsdq5YHKvRuEni68OCLkfy4f+4I9OBpyK1SKJ00Cih16NJbHE+k+ljPPpag==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.4.tgz", + "integrity": "sha512-YeBmI+63Ro75SUiL/QXEVXQ19T++58aI/IINOyhpsRL1LKdyfK/35iilraZEFz9bLQrwy1LYAR5lK200A9Gjbg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.4.tgz", + "integrity": "sha512-Sd0qFUJv8Tj0PukAYbCCDbmXcMkbIuhnTeHm9m4ZGjCf6kt7E/RMs55Pd3R5ePjOkN7dJEuxYBehawTR/aPDSQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.4.tgz", + "integrity": "sha512-rt/vv/vg/ZGGkrkKcuJ0LyliRdbskQU+91bje+PgoYmxTZf/tYs6IfbmgudBJk6gH3QnjHWbkphDdRQrseRefQ==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.4.tgz", + "integrity": "sha512-DQ20JEfTBZAgF8QCjYfJhv2/279M6onxFjdG/+5B0Cyj00/EdBxiWb2eGGFgQhrBbNv/lsvzFbbi0Ptf8Vw/bg==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -3026,9 +3526,9 @@ } }, "node_modules/@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "dependencies": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -3056,9 +3556,9 @@ } }, "node_modules/@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "dependencies": { "@octokit/request": "^6.0.0", "@octokit/types": "^9.0.0", @@ -3069,16 +3569,17 @@ } }, "node_modules/@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" }, "node_modules/@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "dependencies": { - "@octokit/types": "^9.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" }, "engines": { "node": ">= 14" @@ -3096,11 +3597,11 @@ } }, "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "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==", "dependencies": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" }, "engines": { @@ -3111,9 +3612,9 @@ } }, "node_modules/@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "dependencies": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -3140,39 +3641,44 @@ } }, "node_modules/@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "dependencies": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" }, "engines": { "node": ">= 14" } }, + "node_modules/@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" + }, "node_modules/@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "dependencies": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^17.2.0" } }, "node_modules/@pkgr/utils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", - "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.0.tgz", + "integrity": "sha512-2OCURAmRtdlL8iUDTypMrrxfwe8frXTeXaxGsVOaYtc/wrUyk8Z/0OBetM7cdlsy7ZFWlMX72VogKeh+A4Xcjw==", "dev": true, "dependencies": { "cross-spawn": "^7.0.3", + "fast-glob": "^3.2.12", "is-glob": "^4.0.3", - "open": "^8.4.0", + "open": "^9.1.0", "picocolors": "^1.0.0", - "tiny-glob": "^0.2.9", - "tslib": "^2.4.0" + "tslib": "^2.5.0" }, "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" @@ -3181,6 +3687,36 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/@pkgr/utils/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@pkgr/utils/node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@pmmmwh/react-refresh-webpack-plugin": { "version": "0.5.10", "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.10.tgz", @@ -3271,19 +3807,19 @@ } }, "node_modules/@radix-ui/react-accordion": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.0.tgz", - "integrity": "sha512-CNN9ZBgCK4i4SX7gFk5s8095j55DUWi85vwRNfkfBLs0QdAG5Tb4ku6sBeugCAiLvsmxw481GyNl+C3stoJVBQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.1.tgz", + "integrity": "sha512-TQtyyRubYe8DD6DYCovNLTjd2D+TFrNCpr99T5M3cYUbR7BsRxWsxfInjbQ1nHsdy2uPTcnJS5npyXPVfP0piw==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collapsible": "1.0.1", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collapsible": "1.0.2", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" }, "peerDependencies": { @@ -3292,16 +3828,16 @@ } }, "node_modules/@radix-ui/react-alert-dialog": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.2.tgz", - "integrity": "sha512-0MtxV53FaEEBOKRgyLnEqHZKKDS5BldQ9oUBsKVXWI5FHbl2jp35qs+0aJET+K5hJDsc40kQUzP7g+wC7tqrqA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.3.tgz", + "integrity": "sha512-QXFy7+bhGi0u+paF2QbJeSCHZs4gLMJIPm6sajUamyW0fro6g1CaSGc5zmc4QmK2NlSGUrq8m+UsUqJYtzvXow==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dialog": "1.0.2", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-dialog": "1.0.3", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1" }, "peerDependencies": { @@ -3310,12 +3846,12 @@ } }, "node_modules/@radix-ui/react-arrow": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz", - "integrity": "sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.2.tgz", + "integrity": "sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3323,16 +3859,16 @@ } }, "node_modules/@radix-ui/react-checkbox": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.1.tgz", - "integrity": "sha512-TisH0B8hWmYP3ONRduYCyN04rR9yLPIw/Rwyn1RoC1suSoGCa8Wn+YPdSSSarSszeIbcg3p2lBkDp2XXit4sZw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.3.tgz", + "integrity": "sha512-55B8/vKzTuzxllH5sGJO4zaBf9gYpJuJRRzaOKm+0oAefRnMvbf+Kgww7IOANVN0w3z7agFJgtnXaZl8Uj95AA==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", "@radix-ui/react-use-size": "1.0.0" @@ -3343,9 +3879,9 @@ } }, "node_modules/@radix-ui/react-collapsible": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.1.tgz", - "integrity": "sha512-0maX4q91iYa4gjt3PsNf7dq/yqSR+HGAE8I5p54dQ6gnveS+ETWlMoijxrhmgV1k8svxpm34mQAtqIrJt4XZmA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.2.tgz", + "integrity": "sha512-QNiDT6Au8jUU0K1WV+HEd4loH7C5CKQjeXxskwqyiyAkyCmW7qlQM5vSSJCIoQC+OVPyhgafSmGudRP8Qm1/gA==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", @@ -3353,7 +3889,7 @@ "@radix-ui/react-context": "1.0.0", "@radix-ui/react-id": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0" }, @@ -3363,14 +3899,14 @@ } }, "node_modules/@radix-ui/react-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.1.tgz", - "integrity": "sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.2.tgz", + "integrity": "sha512-s8WdQQ6wNXpaxdZ308KSr8fEWGrg4un8i4r/w7fhiS4ElRNjk5rRcl0/C6TANG2LvLOGIxtzo/jAg6Qf73TEBw==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1" }, "peerDependencies": { @@ -3401,21 +3937,21 @@ } }, "node_modules/@radix-ui/react-dialog": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.2.tgz", - "integrity": "sha512-EKxxp2WNSmUPkx4trtWNmZ4/vAYEg7JkAfa1HKBUnaubw9eHzf1Orr9B472lJYaYz327RHDrd4R95fsw7VR8DA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.3.tgz", + "integrity": "sha512-owNhq36kNPqC2/a+zJRioPg6HHnTn5B/sh/NjTY8r4W9g1L5VJlrzZIVcBr7R9Mg8iLjVmh6MGgMlfoVf/WO/A==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-controllable-state": "1.0.0", "aria-hidden": "^1.1.1", @@ -3438,14 +3974,14 @@ } }, "node_modules/@radix-ui/react-dismissable-layer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz", - "integrity": "sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.3.tgz", + "integrity": "sha512-nXZOvFjOuHS1ovumntGV7NNoLaEp9JEvTht3MBjP44NSW5hUKj/8OnfN3+8WmB+CEhN44XaGhpHoSsUIEl5P7Q==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-escape-keydown": "1.0.2" }, @@ -3455,17 +3991,17 @@ } }, "node_modules/@radix-ui/react-dropdown-menu": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.2.tgz", - "integrity": "sha512-r0kN0fstrSi+uAdK2GkLxnnbhqVBy/9Q4o4PvGOYipW0BldQlYBMSmZprvCNj2i2mAATx16kvzIn12GnaGjbMw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.4.tgz", + "integrity": "sha512-y6AT9+MydyXcByivdK1+QpjWoKaC7MLjkS/cH1Q3keEyMvDkiY85m8o2Bi6+Z1PPUlCsMULopxagQOSfN0wahg==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-menu": "2.0.2", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-menu": "2.0.4", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" }, "peerDependencies": { @@ -3485,13 +4021,13 @@ } }, "node_modules/@radix-ui/react-focus-scope": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz", - "integrity": "sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.2.tgz", + "integrity": "sha512-spwXlNTfeIprt+kaEWE/qYuYT3ZAqJiAGjN/JgdvgVDTu8yc+HuX+WOWXrKliKnLnwck0F6JDkqIERncnih+4A==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0" }, "peerDependencies": { @@ -3500,19 +4036,19 @@ } }, "node_modules/@radix-ui/react-hover-card": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.3.tgz", - "integrity": "sha512-rr2+DxPlMhR57IPcNvZ85X8chytdfj7kyVToyR5Ge0r4IJEFiyPs0Cs8/K8oe5zt+yo0F8f29vtC8tNNK+ZIkA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.5.tgz", + "integrity": "sha512-jXRuZEkxSWdHZbVyL0J46cm7pQjmOMpwJEFKY+VqAJnV+FxS+zIZExI1OCeIiDwCBzUy6If1FfouOsfqBxr86g==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" }, "peerDependencies": { @@ -3533,12 +4069,12 @@ } }, "node_modules/@radix-ui/react-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.0.tgz", - "integrity": "sha512-7qCcZ3j2VQspWjy+gKR4W+V/z0XueQjeiZnlPOtsyiP9HaS8bfSU7ECoI3bvvdYntQj7NElW7OAYsYRW4MQvCg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.1.tgz", + "integrity": "sha512-qcfbS3B8hTYmEO44RNcXB6pegkxRsJIbdxTMu0PEX0Luv5O2DvTIwwVYxQfUwLpM88EL84QRPLOLgwUSApMsLQ==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3546,25 +4082,25 @@ } }, "node_modules/@radix-ui/react-menu": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.2.tgz", - "integrity": "sha512-H5dtBi/k3tc45IMd2Pu+Q2PyONFlsYJ5sWUlflSs8BQRghh5GhJHLRuB1yb88VOywuzzvGkaR/HUJJ65Jf2POA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.4.tgz", + "integrity": "sha512-mzKR47tZ1t193trEqlQoJvzY4u9vYfVH16ryBrVrCAGZzkgyWnMQYEZdUkM7y8ak9mrkKtJiqB47TlEnubeOFQ==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", - "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-roving-focus": "1.0.3", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "aria-hidden": "^1.1.1", @@ -3576,22 +4112,22 @@ } }, "node_modules/@radix-ui/react-popover": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.3.tgz", - "integrity": "sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.5.tgz", + "integrity": "sha512-GRHZ8yD12MrN2NLobHPE8Rb5uHTxd9x372DE9PPNnBjpczAQHcZ5ne0KXG4xpf+RDdXSzdLv9ym6mYJCDTaUZg==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-controllable-state": "1.0.0", "aria-hidden": "^1.1.1", @@ -3603,16 +4139,16 @@ } }, "node_modules/@radix-ui/react-popper": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.0.tgz", - "integrity": "sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.1.tgz", + "integrity": "sha512-keYDcdMPNMjSC8zTsZ8wezUMiWM9Yj14wtF3s0PTIs9srnEPC9Kt2Gny1T3T81mmSeyDjZxsD9N5WCwNNb712w==", "dependencies": { "@babel/runtime": "^7.13.10", "@floating-ui/react-dom": "0.7.2", - "@radix-ui/react-arrow": "1.0.1", + "@radix-ui/react-arrow": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", "@radix-ui/react-use-rect": "1.0.0", @@ -3625,12 +4161,12 @@ } }, "node_modules/@radix-ui/react-portal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.1.tgz", - "integrity": "sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.2.tgz", + "integrity": "sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3652,9 +4188,9 @@ } }, "node_modules/@radix-ui/react-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz", - "integrity": "sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz", + "integrity": "sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-slot": "1.0.1" @@ -3665,13 +4201,13 @@ } }, "node_modules/@radix-ui/react-progress": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.0.1.tgz", - "integrity": "sha512-QbDf9eguM5QtkvGcGHe/nUgloM9yfRGpJTB/Te5cn4WmVHvcbhHyHw39/rbCZxNX4E+GEPp5Vs6+mEoyIotUbg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.0.2.tgz", + "integrity": "sha512-c16RVM43ct2koRcMmPw4b47JWFNs89qe5p4Um9dwoPs0yi+d7It1MJ35EpsX+93o31Mqdwe4vQyu0SrHrygdCg==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3679,18 +4215,18 @@ } }, "node_modules/@radix-ui/react-roving-focus": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz", - "integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.3.tgz", + "integrity": "sha512-stjCkIoMe6h+1fWtXlA6cRfikdBzCLp3SnVk7c48cv/uy3DTGoXhN76YaOYUJuy3aEDvDIKwKR5KSmvrtPvQPQ==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0" }, @@ -3700,30 +4236,30 @@ } }, "node_modules/@radix-ui/react-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.0.tgz", - "integrity": "sha512-MmXKsIBrG9GKxt8JKIn75LEPiX/zejBmj/Z36Hxtm9cdmCFzTo78QJ0Q3buLGzr0c3lzXdfgeKntmgCzaGxgkw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.1.tgz", + "integrity": "sha512-GULRMITaOHNj79BZvQs3iZO0+f2IgI8g5HDhMi7Bnc13t7IlG86NFtOCfTLme4PNZdEtU+no+oGgcl6IFiphpQ==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.0", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", - "@radix-ui/react-visually-hidden": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.2", "aria-hidden": "^1.1.1", "react-remove-scroll": "2.5.5" }, @@ -3745,15 +4281,15 @@ } }, "node_modules/@radix-ui/react-switch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.1.tgz", - "integrity": "sha512-tTxGluMtwrc5ffgAiOSMrYIx0r3vSTcgM4Vl8rqfpXcHt6ryB9B0OlFKUOiDpKASXlhvzfHf4Y0AYKJdpzjL8w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.2.tgz", + "integrity": "sha512-BcG/LKehxt36NXG0wPnoCitIfSMtU9Xo7BmythYA1PAMLtsMvW7kALfBzmduQoHTWcKr0AVcFyh0gChBUp9TiQ==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", "@radix-ui/react-use-size": "1.0.0" @@ -3764,9 +4300,9 @@ } }, "node_modules/@radix-ui/react-tabs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz", - "integrity": "sha512-gOUwh+HbjCuL0UCo8kZ+kdUEG8QtpdO4sMQduJ34ZEz0r4922g9REOBM+vIsfwtGxSug4Yb1msJMJYN2Bk8TpQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.3.tgz", + "integrity": "sha512-4CkF/Rx1GcrusI/JZ1Rvyx4okGUs6wEenWA0RG/N+CwkRhTy7t54y7BLsWUXrAz/GRbBfHQg/Odfs/RoW0CiRA==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", @@ -3774,8 +4310,8 @@ "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", - "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-roving-focus": "1.0.3", "@radix-ui/react-use-controllable-state": "1.0.0" }, "peerDependencies": { @@ -3784,23 +4320,47 @@ } }, "node_modules/@radix-ui/react-toast": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.2.tgz", - "integrity": "sha512-Kpr4BBYoP0O5A1UeDBmao87UnCMNdAKGNioQH5JzEm6OYTUVGhuDRbOwoZxPwOZ6vsjJHeIpdUrwbiHEB65CCw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.3.tgz", + "integrity": "sha512-yHFgpxi9wjbfPvpSPdYAzivCqw48eA1ofT8m/WqYOVTxKPdmQMuVKRYPlMmj4C1d6tJdFj/LBa1J4iY3fL4OwQ==", "dependencies": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", - "@radix-ui/react-visually-hidden": "1.0.1" + "@radix-ui/react-visually-hidden": "1.0.2" + }, + "peerDependencies": { + "react": "^16.8 || ^17.0 || ^18.0", + "react-dom": "^16.8 || ^17.0 || ^18.0" + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.5.tgz", + "integrity": "sha512-cDKVcfzyO6PpckZekODJZDe5ZxZ2fCZlzKzTmPhe4mX9qTHRfLcKgqb0OKf22xLwDequ2tVleim+ZYx3rabD5w==", + "dependencies": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-slot": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0", + "@radix-ui/react-visually-hidden": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3889,12 +4449,12 @@ } }, "node_modules/@radix-ui/react-visually-hidden": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.1.tgz", - "integrity": "sha512-K1hJcCMfWfiYUibRqf3V8r5Drpyf7rh44jnrwAbdvI5iCCijilBBeyQv9SKidYNZIopMdCyR9FnIjkHxHN0FcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.2.tgz", + "integrity": "sha512-qirnJxtYn73HEk1rXL12/mXnu2rwsNHDID10th2JGtdK25T9wX+mxRmGt7iPSahw512GbZOc0syZX1nLQGoEOg==", "dependencies": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" }, "peerDependencies": { "react": "^16.8 || ^17.0 || ^18.0", @@ -3910,14 +4470,14 @@ } }, "node_modules/@reduxjs/toolkit": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.3.tgz", - "integrity": "sha512-lU/LDIfORmjBbyDLaqFN2JB9YmAT1BElET9y0ZszwhSBa5Ef3t6o5CrHupw5J1iOXwd+o92QfQZ8OJpwXvsssg==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz", + "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==", "dependencies": { - "immer": "^9.0.7", - "redux": "^4.1.2", - "redux-thunk": "^2.4.1", - "reselect": "^4.1.5" + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" }, "peerDependencies": { "react": "^16.9.0 || ^17.0.0 || ^18", @@ -3933,39 +4493,31 @@ } }, "node_modules/@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz", + "integrity": "sha512-IthPJsJR85GhOkp3Hvp8zFOPK5ynKn6STyHa/WZpioK7E1aYDiBzpqQPrngc14DszIUkIrdd3k9Iu0XSzlP/1w==", "dev": true }, - "node_modules/@sentry/types": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.22.0.tgz", - "integrity": "sha512-LhCL+wb1Jch+OesB2CIt6xpfO1Ab6CRvoNYRRzVumWPLns1T3ZJkarYfhbLaOEIb38EIbPgREdxn2AJT560U4Q==", - "engines": { - "node": ">=8" - } - }, "node_modules/@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", "dev": true }, "node_modules/@storybook/addon-actions": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.0.0-beta.30.tgz", - "integrity": "sha512-hk7e0B6kSPD/m5+pU6lKS3CzBBYf3n74m33cFjTRyhk8vO8x5QC5tni8nZdzmqREthoIOIf+1zHxYDO8SLE5zg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.0.12.tgz", + "integrity": "sha512-f07Mc3qwcG9heGsuUUTIJbWF2nw/Ite3mvyIZY2VbgwhMUMVHj4knY4fh/LojwcUmmmc7CNZu3sJN/wIqpaHCQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "dequal": "^2.0.2", "lodash": "^4.17.21", "polished": "^4.2.2", @@ -3973,7 +4525,7 @@ "react-inspector": "^6.0.0", "telejson": "^7.0.3", "ts-dedent": "^2.0.0", - "uuid-browser": "^3.1.0" + "uuid": "^9.0.0" }, "funding": { "type": "opencollective", @@ -3992,20 +4544,29 @@ } } }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/@storybook/addon-backgrounds": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.0.0-beta.30.tgz", - "integrity": "sha512-UDPWQEwreK1TXjBjAmZN40uu5+7hC5dobdZhZr+i/4W+xswFMgprT4PtvfcoVyFTdOjRIsIDd0doLurvB5c1ng==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.0.12.tgz", + "integrity": "sha512-sAZSxsbj3CcabowALKTafpdnqXMBZB8C42s4Uxv11FCP50GqrP8jp2TqsIiDZxUbeXwI094W/gHnw41MSphG8Q==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" }, @@ -4027,20 +4588,20 @@ } }, "node_modules/@storybook/addon-controls": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.0.0-beta.30.tgz", - "integrity": "sha512-5ybbmFH+gcrBRfJnRTdSgNbCYMJMHQY2QTNqukUHO0CjAPEZMpPCFkiQNdIBLslsju9+bunVo1S/MBfwH3Ku7Q==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.0.12.tgz", + "integrity": "sha512-/+yBhswN1N7ttR1NGN94HE/25VELm4YuBtrkh+LJeKP/eQ5CZpLjexASN2GZcfmdnkwIYZAEH0X/AImLaCJAWA==", "dev": true, "dependencies": { - "@storybook/blocks": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/blocks": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" }, @@ -4062,28 +4623,29 @@ } }, "node_modules/@storybook/addon-docs": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.0.0-beta.30.tgz", - "integrity": "sha512-++SN8wmtiKE+bKbhscO8656GPZOFIEv31a3qYgId3W8wg/9YmTKUmXrejjUi3SZmO3xKVZ0bskJUw16oBWddug==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.0.12.tgz", + "integrity": "sha512-zgg4sq34Zz8TN74+kSogxRHsIZ5gsIazJpa0osZp91nJQvsKUEfldjBtQWbBWzjVCrWmzOhW5/RLCnmCNm9y/w==", "dev": true, "dependencies": { "@babel/core": "^7.20.2", "@babel/plugin-transform-react-jsx": "^7.19.0", "@jest/transform": "^29.3.1", "@mdx-js/react": "^2.1.5", - "@storybook/blocks": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/csf-plugin": "7.0.0-beta.30", - "@storybook/csf-tools": "7.0.0-beta.30", + "@storybook/blocks": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/csf-plugin": "7.0.12", + "@storybook/csf-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/mdx2-csf": "next", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/postinstall": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", - "fs-extra": "^9.0.1", + "@storybook/mdx2-csf": "^1.0.0", + "@storybook/node-logger": "7.0.12", + "@storybook/postinstall": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/react-dom-shim": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", + "fs-extra": "^11.1.0", "remark-external-links": "^8.0.0", "remark-slug": "^6.0.0", "ts-dedent": "^2.0.0" @@ -4098,24 +4660,24 @@ } }, "node_modules/@storybook/addon-essentials": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.0.0-beta.30.tgz", - "integrity": "sha512-3X4WMrf4TCSN9iDrGAQlIM7bj8r+aov4O1Q/fM73n3B6puOG25uMzhT2V8MB4aJdGOXeYvvjAh5rMBdHxfQjPQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.0.12.tgz", + "integrity": "sha512-Js2cxvauAf8fkA5D0QrqPPe/FvpY1DbJp61VNGh82Xu0zZrczCGYP3jkWG79vl0zllJNs7hnkV8W6xY1JWgLoA==", "dev": true, "dependencies": { - "@storybook/addon-actions": "7.0.0-beta.30", - "@storybook/addon-backgrounds": "7.0.0-beta.30", - "@storybook/addon-controls": "7.0.0-beta.30", - "@storybook/addon-docs": "7.0.0-beta.30", - "@storybook/addon-highlight": "7.0.0-beta.30", - "@storybook/addon-measure": "7.0.0-beta.30", - "@storybook/addon-outline": "7.0.0-beta.30", - "@storybook/addon-toolbars": "7.0.0-beta.30", - "@storybook/addon-viewport": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", + "@storybook/addon-actions": "7.0.12", + "@storybook/addon-backgrounds": "7.0.12", + "@storybook/addon-controls": "7.0.12", + "@storybook/addon-docs": "7.0.12", + "@storybook/addon-highlight": "7.0.12", + "@storybook/addon-measure": "7.0.12", + "@storybook/addon-outline": "7.0.12", + "@storybook/addon-toolbars": "7.0.12", + "@storybook/addon-viewport": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", "ts-dedent": "^2.0.0" }, "funding": { @@ -4128,14 +4690,14 @@ } }, "node_modules/@storybook/addon-highlight": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.0.0-beta.30.tgz", - "integrity": "sha512-wyOl7mHGBB6u9I4uqn8PMlAGbZEfa0LeeDLqzzxZWzGFrFUVqjthQ+BAIbb8C+wOs9eb0CTGEecJQhurbV+UuA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.0.12.tgz", + "integrity": "sha512-ccIsBVjUlZ7cM1adSSFTqqWXiELPdDqfZLz4dWfDbiLyG3InC953ugtvoUWCIZpC2OOnjVLpF7Rbshq2O/QoMw==", "dev": true, "dependencies": { - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/preview-api": "7.0.12" }, "funding": { "type": "opencollective", @@ -4143,21 +4705,21 @@ } }, "node_modules/@storybook/addon-interactions": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.0.0-beta.30.tgz", - "integrity": "sha512-mulmrEmDr9vynVVjmJ0OLiHd8NhGvrnTSrN6eMYLKp/VpOEOV0KgE28z+lqkeuAgRdcFG65ddV9AE8h1+rYxyg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.0.12.tgz", + "integrity": "sha512-Rb1mv1RQrTd3sA/WwNTdv00rW+7APfvZEeZks6+8+kS1C4EFMDmLnVBZlPllFdo1BOnTCyer4GZZ5ncVkWNLyQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/instrumenter": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "jest-mock": "^27.0.6", "polished": "^4.2.2", "ts-dedent": "^2.2.0" @@ -4180,19 +4742,19 @@ } }, "node_modules/@storybook/addon-links": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.0.0-beta.30.tgz", - "integrity": "sha512-Uyj/WwUOGOTmDvYygM24vP0Zfj28ebYxtd07CYAlhvJ6P7yOb6H9v2cM/a2cJc1h7VmH9eohPNuTFDbv1P+QMQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.0.12.tgz", + "integrity": "sha512-6kGClsIpX9dRKc5bUAPNcp/4wlgPIxMrieUV+6k1dTsRQqbaEfxih/Fq259D5+yVBDNi3YAnvRjMiIibl8fa5A==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/router": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/router": "7.0.12", + "@storybook/types": "7.0.12", "prop-types": "^15.7.2", "ts-dedent": "^2.0.0" }, @@ -4214,18 +4776,18 @@ } }, "node_modules/@storybook/addon-measure": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.0.0-beta.30.tgz", - "integrity": "sha512-tlY+CcZleoxMV5F50LLY/GFcWU8X5g9Td5K/pYqVw25jZFeqBZCZs+k0eqct1HeWKY64uutAYmljzrrwgpsUmw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.0.12.tgz", + "integrity": "sha512-Uq9cj9QmN7WKBQ6wqeneFmTqo1UQKXIc4CpGBEtJtfsYNLsERrVzOs/tRUf66Zl3lWgfFZxs1B5Ij6RDsYEjRw==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30" + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12" }, "funding": { "type": "opencollective", @@ -4245,18 +4807,18 @@ } }, "node_modules/@storybook/addon-outline": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.0.0-beta.30.tgz", - "integrity": "sha512-qvJh05sc40NfF9RZ5KCVRHh3hRb0XCdxXP95qg7P0QF/BCRIrLTP8/94rT56IwhaMKDTttoU1x2PST0FDxQZaQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.0.12.tgz", + "integrity": "sha512-eZPkm3mECdqx1EDJ0S6DAzZ9WZLPIsZH7fRy6vdJJuAgvnOSzkt7AEpA0hlgiNyXcFpE1Cav6/g12FUf4Zo82g==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12", "ts-dedent": "^2.0.0" }, "funding": { @@ -4294,9 +4856,9 @@ } }, "node_modules/@storybook/addon-postcss/node_modules/@storybook/node-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.15.tgz", - "integrity": "sha512-LQjjbfMuUXm7wZTBKb+iGeCNnej4r1Jb2NxG3Svu2bVhaoB6u33jHAcbmhXpXW1jghzW3kQwOU7BoLuJiRRFIw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.16.tgz", + "integrity": "sha512-YjhBKrclQtjhqFNSO+BZK+RXOx6EQypAELJKoLFaawg331e8VUfvUuRCNB3fcEWp8G9oH13PQQte0OTjLyyOYg==", "dev": true, "dependencies": { "@types/npmlog": "^4.1.2", @@ -4341,64 +4903,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@storybook/addon-postcss/node_modules/css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "dependencies": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/css-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/css-loader/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@storybook/addon-postcss/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -4408,44 +4912,6 @@ "node": ">=8" } }, - "node_modules/@storybook/addon-postcss/node_modules/icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "dependencies": { - "postcss": "^7.0.14" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - }, - "engines": { - "node": ">=4.0.0" - } - }, "node_modules/@storybook/addon-postcss/node_modules/picocolors": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", @@ -4469,106 +4935,6 @@ "url": "https://opencollective.com/postcss/" } }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", - "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", - "dev": true, - "dependencies": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.4", - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.4" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-loader/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "dependencies": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "dependencies": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "dependencies": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, "node_modules/@storybook/addon-postcss/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4578,70 +4944,6 @@ "node": ">=0.10.0" } }, - "node_modules/@storybook/addon-postcss/node_modules/style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "dev": true, - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/style-loader/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/style-loader/node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/@storybook/addon-postcss/node_modules/style-loader/node_modules/schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/@storybook/addon-postcss/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -4655,16 +4957,16 @@ } }, "node_modules/@storybook/addon-toolbars": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.0.0-beta.30.tgz", - "integrity": "sha512-b+aOu6lT9OR8WhqXDJwzV/u3DFvB3/Cl31UD1W6BrnqkoMJ7WbZy74stsNx0Kb2g6WqGzqHuErRtS2YMpCMUZA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.0.12.tgz", + "integrity": "sha512-7xRxk+999NVdEwzn2z1O9Tg5iuUSEXQ5jo+hiyK934VvuyqUsZnflKbSvwVEHb2W+DroaaXu8bdHWxGSH+6moQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12" }, "funding": { "type": "opencollective", @@ -4684,18 +4986,18 @@ } }, "node_modules/@storybook/addon-viewport": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.0.0-beta.30.tgz", - "integrity": "sha512-ugk44rt07zyj4kUNt8aNHGxMFbrqjygGk+MznASrOd4F4G4LzM09O+a/YqGGKSJQlb90gadW7Xj1iy4HP28NtA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.0.12.tgz", + "integrity": "sha512-pMgqtDQF8e9AErnRKbbSK9m1lcKn1dFSOkk0PgSBwIIjmha6q+GeT45EHQrQGtkLdtWT0iTktC8ivzIiGKmHkg==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", "memoizerific": "^1.11.3", "prop-types": "^15.7.2" }, @@ -4717,14 +5019,14 @@ } }, "node_modules/@storybook/addons": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.0.0-beta.30.tgz", - "integrity": "sha512-J0/tiaEPXNVbjUAgSNuLirfRfhUwQ5PC4LvNLYO//OKpRn/pvsh5jlFWKVoXG5Km711atS6P7aOt7vTTAH8Akg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.0.12.tgz", + "integrity": "sha512-yVADbWCFdb12cSpspeb+/6lfTNarPtZZLql49Bhu6E7PxECw/Q3kfHu0LXBLcSnU7f4QqQvQjp88ultt01ABBQ==", "dev": true, "dependencies": { - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30" + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12" }, "funding": { "type": "opencollective", @@ -4736,44 +5038,57 @@ } }, "node_modules/@storybook/api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.0.0-beta.30.tgz", - "integrity": "sha512-D7ggwRM6yDrHBDI8IXoRA6XVWrrqNL0E1m+M2uBK9RoKfgVJr9TMapFl3u46LTIC76EsFigJCFdNnlPmnIwlhQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.0.12.tgz", + "integrity": "sha512-wki9B7ZXOGwUq/FowDgEnkkX92oNpSg/6ES5Rh19NF3wV0ObLlgXMZ8cZKOLM6G0m/8lkKHGeNBunaLUnX7Yhw==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/manager-api": "7.0.12" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, "node_modules/@storybook/blocks": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.0.0-beta.30.tgz", - "integrity": "sha512-kwH9Xlr8GeGvJPjbuvlC4aGkZq/1Xz5S5Cnapfs3vnDSD76/30XvFj+QUV+clf3aPAbbKI1QJIXy2lCzUME46w==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.0.12.tgz", + "integrity": "sha512-MbJKjuTJ7xVbkUVwkEwb6vTYGrkRk4+Xtx1UGo+512o91ubqFs8hXwCHP+x/49RCIIQs5zl93Ig8fTtm+MejWw==", "dev": true, "dependencies": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", - "@storybook/docs-tools": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", + "@storybook/docs-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "@types/lodash": "^4.14.167", "color-convert": "^2.0.1", "dequal": "^2.0.2", "lodash": "^4.17.21", - "markdown-to-jsx": "^7.1.3", + "markdown-to-jsx": "^7.1.8", "memoizerific": "^1.11.3", "polished": "^4.2.2", "react-colorful": "^5.1.2", + "telejson": "^7.0.3", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" }, @@ -4787,27 +5102,26 @@ } }, "node_modules/@storybook/builder-manager": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.0.0-beta.30.tgz", - "integrity": "sha512-hBiF7LE4Ojsgh7E9LRPgwHATQuV/izY8F/tFKCbWO3g5yzElEHcspEDJmbxh9HnAhNcYFvshCwFBBC1CTc8sTQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.0.12.tgz", + "integrity": "sha512-bkZPSDH38/dUSsO087oQ8+goyaEDP/xD0/O61QcQ8EbaVeT6s6Qt7mMhqsLrtmEZHvPMQwKeIXhOJlRNNXB+SA==", "dev": true, "dependencies": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/manager": "7.0.12", + "@storybook/node-logger": "7.0.12", "@types/ejs": "^3.1.1", "@types/find-cache-dir": "^3.2.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", "ejs": "^3.1.8", - "esbuild": "^0.16.4", + "esbuild": "^0.17.0", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", "find-cache-dir": "^3.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "process": "^0.11.10", - "slash": "^3.0.0", "util": "^0.12.4" }, "funding": { @@ -4816,31 +5130,31 @@ } }, "node_modules/@storybook/builder-webpack5": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.0.0-beta.30.tgz", - "integrity": "sha512-7SS+F9tyIL9N2iUNapCFy0aSxrXRI2byXuKM/xCXgYnMq04z3MbPuG6ymaYUoRZQ2zMYoHkMA8iaLthHsIoRAQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.0.12.tgz", + "integrity": "sha512-msrDWgNFu0kkQ8AOuOCqO+Z+b6iB2kNMhpTyreFbZfUwnEv35aXdULeSa/2mCD0/PFUUFZu+cVYflMyENZxe5w==", "dev": true, "dependencies": { "@babel/core": "^7.12.10", - "@storybook/addons": "7.0.0-beta.30", - "@storybook/api": "7.0.0-beta.30", - "@storybook/channel-postmessage": "7.0.0-beta.30", - "@storybook/channel-websocket": "7.0.0-beta.30", - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-api": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/core-webpack": "7.0.0-beta.30", + "@storybook/addons": "7.0.12", + "@storybook/api": "7.0.12", + "@storybook/channel-postmessage": "7.0.12", + "@storybook/channel-websocket": "7.0.12", + "@storybook/channels": "7.0.12", + "@storybook/client-api": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/core-webpack": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/router": "7.0.0-beta.30", - "@storybook/store": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/router": "7.0.12", + "@storybook/store": "7.0.12", + "@storybook/theming": "7.0.12", "@types/node": "^16.0.0", "@types/semver": "^7.3.4", "babel-loader": "^9.0.0", @@ -4850,12 +5164,11 @@ "css-loader": "^6.7.1", "express": "^4.17.3", "fork-ts-checker-webpack-plugin": "^7.2.8", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "html-webpack-plugin": "^5.5.0", "path-browserify": "^1.0.1", "process": "^0.11.10", "semver": "^7.3.7", - "slash": "^3.0.0", "style-loader": "^3.3.1", "terser-webpack-plugin": "^5.3.1", "ts-dedent": "^2.0.0", @@ -4881,20 +5194,166 @@ } }, "node_modules/@storybook/builder-webpack5/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", + "dev": true + }, + "node_modules/@storybook/builder-webpack5/node_modules/css-loader": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.4.tgz", + "integrity": "sha512-0Y5uHtK5BswfaGJ+jrO+4pPg1msFBc0pwPIE1VqfpmVn6YbDfYfXMj8rfd7nt+4goAhJueO+H/I40VWJfcP1mQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.1", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/postcss-modules-local-by-default": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.1.tgz", + "integrity": "sha512-Zr/dB+IlXaEqdoslLHhhqecwj73vc3rDmOpsBNBEVk7P2aqAlz+Ijy0fFbU5Ie9PtreDOIgGa9MsLWakVGl+fA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@storybook/builder-webpack5/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/@storybook/channel-postmessage": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-7.0.0-beta.30.tgz", - "integrity": "sha512-szCRSlMZr0ii/j+kIHKim1kCpmVblhvLl8vW25sbUkW0lSJ7F0VQ1mQSNjXDWhZHEMb9/1ZYCbN7HOsXp9oCRg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-7.0.12.tgz", + "integrity": "sha512-Tc7kQZ5yxlZ44Nmmzec92JaDJ6UZ3Ze4cBfiHik4XcnM1PtN8hr8VFoC6a2AIm1ybfIRenfT5w9TH5yriiPIhw==", "dev": true, "dependencies": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.0.3" @@ -4905,13 +5364,13 @@ } }, "node_modules/@storybook/channel-websocket": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-7.0.0-beta.30.tgz", - "integrity": "sha512-Q+bShSf8ueKw5H3vN76lgAqzl+bG7rqjQhgG7ALYUPDgNGFf+7dFoe2/g5byjhZAZGomObhmIRjpPkCmUzx4Uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-7.0.12.tgz", + "integrity": "sha512-UV6b9gX2mQLtXlKaFKCHcy+6MaK2od6BYqSJfainnBjDsMIXyhcf7fJaj0XQkJrbNnRBwGhw+6s8JxL98xp7Ew==", "dev": true, "dependencies": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", "@storybook/global": "^5.0.0", "telejson": "^7.0.3" }, @@ -4921,9 +5380,9 @@ } }, "node_modules/@storybook/channels": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.0.0-beta.30.tgz", - "integrity": "sha512-XIlFxLKy0MGpWIGondLHf92Aku57SpIxZXmjLbM2iAeG0UljzdL+d8BoMp5Yo0CVMmMBGGZEoM7INrhf6p2WKw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.0.12.tgz", + "integrity": "sha512-KDdDmDs8kxAJU+vndTqTNazjLO+XoIPiTRlfP7mk7cgHiQXSjMYy3JSCQ7W0of0Q+9VSl/ve9CNbnGbcQF7rNQ==", "dev": true, "funding": { "type": "opencollective", @@ -4931,20 +5390,21 @@ } }, "node_modules/@storybook/cli": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.0.0-beta.30.tgz", - "integrity": "sha512-nwgHQysnL67VZ/fP99BR16E9WRH634pg2hbRqzC1DCzEWAfAcnlZPbnOUmbVhpL6MdJw6i5nyVdk4ugUcFI8pA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.0.12.tgz", + "integrity": "sha512-OABCRIujxsszIJ0CCpKg8Uj4C1UlAwBpBQhv2aMX3lA/pur6Od524syv2ypWu6J2FyvK/ooeyMbjoP7330cIuA==", "dev": true, "dependencies": { "@babel/core": "^7.20.2", "@babel/preset-env": "^7.20.2", - "@storybook/codemod": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-server": "7.0.0-beta.30", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/telemetry": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@ndelangen/get-tarball": "^3.0.7", + "@storybook/codemod": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-server": "7.0.12", + "@storybook/csf-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/telemetry": "7.0.12", + "@storybook/types": "7.0.12", "@types/semver": "^7.3.4", "boxen": "^5.1.2", "chalk": "^4.1.0", @@ -4955,12 +5415,14 @@ "execa": "^5.0.0", "express": "^4.17.3", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", + "get-npm-tarball-url": "^2.0.3", "get-port": "^5.1.1", "giget": "^1.0.0", "globby": "^11.0.2", - "jscodeshift": "^0.13.1", + "jscodeshift": "^0.14.0", "leven": "^3.1.0", + "prettier": "^2.8.0", "prompts": "^2.4.0", "puppeteer-core": "^2.1.1", "read-pkg-up": "^7.0.1", @@ -5030,6 +5492,33 @@ "node": ">=8" } }, + "node_modules/@storybook/cli/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/cli/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@storybook/cli/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5042,14 +5531,20 @@ "node": ">=8" } }, + "node_modules/@storybook/cli/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@storybook/client-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.0-beta.30.tgz", - "integrity": "sha512-FPRmBmRRzsA9ZNXBwoOVEMze8dp/U1DxA0OKw9y24v/ijgg+P6GAqpX3WFrx3eQWn3I3oMg/8kJwANvOv38ZDw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.12.tgz", + "integrity": "sha512-kcB0wX9+pL9NW8+xFVABFZJeChsql9i2A69yUQQ8OCaJhB7LS3gl1Ri4zJhVHSuTTWBlbNUSPbu1yEkFiAWt/g==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" }, "funding": { "type": "opencollective", @@ -5057,9 +5552,9 @@ } }, "node_modules/@storybook/client-logger": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.0.0-beta.30.tgz", - "integrity": "sha512-50JKxy0E2jUfGcfHwBp+NnlVLqaELSTjB5CjxckUExLfsU/u3dzTPrMmxevBw3ojqaCtyGKZE0yY0ndn/QbeuA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.0.12.tgz", + "integrity": "sha512-MQMtIgGEgdixvxnBvZ2m8hhc0DGJWeCpHtxg7oqBLBEBmCYFueTqDZHl4Z6SoCrK0a2YS5X/BIXOcEtP1ulMKw==", "dev": true, "dependencies": { "@storybook/global": "^5.0.0" @@ -5070,25 +5565,24 @@ } }, "node_modules/@storybook/codemod": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.0.0-beta.30.tgz", - "integrity": "sha512-kJmzhLVavUB5wTkL1RfnZZml6uSMtwTExMAAoMl1q8ie1KVIXEjO7vrQYz8xRFsQJ/y36TeJWY8w45kjBie0Aw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.0.12.tgz", + "integrity": "sha512-eGbGZSglvbnY1omzRyEC4XP0FbpuCFKgjXmdHn9faGQUU5EJHwcGYYrRW8JZL3nEVIvNDuRAKzM3p0BVo1xeSQ==", "dev": true, "dependencies": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/types": "^7.20.7", - "@storybook/csf": "next", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@babel/core": "~7.21.0", + "@babel/preset-env": "~7.21.0", + "@babel/types": "~7.21.2", + "@storybook/csf": "^0.1.0", + "@storybook/csf-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "cross-spawn": "^7.0.3", "globby": "^11.0.2", - "jscodeshift": "^0.13.1", + "jscodeshift": "^0.14.0", "lodash": "^4.17.21", "prettier": "^2.8.0", - "recast": "^0.23.1", - "util": "^0.12.4" + "recast": "^0.23.1" }, "funding": { "type": "opencollective", @@ -5096,17 +5590,18 @@ } }, "node_modules/@storybook/components": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.0.0-beta.30.tgz", - "integrity": "sha512-CrGZY97t0lcjM/kevTVUYrZ35Civnpyyn4Q5uPbHv9cilmSGxbGg3r1yH8s6+FfbSobb77ZiCCbZXCWrSCiwnQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.0.12.tgz", + "integrity": "sha512-6TxByzYS4+LxwZRioGpP6Zh9If5ctjQs5OnR2UmQvP6HDjmMWYTntoHKIbDwAL9C6MrnQYpPOGCPkqrtODQ4/w==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/client-logger": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "memoizerific": "^1.11.3", + "use-resize-observer": "^9.1.0", "util-deprecate": "^1.0.2" }, "funding": { @@ -5119,13 +5614,13 @@ } }, "node_modules/@storybook/core-client": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.0.0-beta.30.tgz", - "integrity": "sha512-4F2TMNjV8YpEJoCUGa9yfD+3zv60/pG1xjt6NP5uoMKsvqjfDOXCXXQGcUd6lnidGu/xoYvhR8r0KsRmsIzRYQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.0.12.tgz", + "integrity": "sha512-m0r+Vl3LfU8cJl8UqIwzh0sEN9I//nMaT8UIIm481AINhQTNihQcnYi9jRw7USjfz2fv5CYkg8cEr4KhI8QlRA==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" }, "funding": { "type": "opencollective", @@ -5133,33 +5628,29 @@ } }, "node_modules/@storybook/core-common": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.0.0-beta.30.tgz", - "integrity": "sha512-46U4cHOgKQBxFBZO19lx0eR7F/fJgzBr4Nhx4Ws6vhdW5492aa8NPjHM+59jXOMpU8ZM3zHvhObaL/VMwnTJWg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.0.12.tgz", + "integrity": "sha512-PFVjYXHUxDQO1oqfqwQe7S3XoLNO0aZYEr9Zl0LiexlxxnU1v+TQjEfNd/H3T0xxpXlsgzhtEcagdzJeAKyh2g==", "dev": true, "dependencies": { - "@babel/core": "^7.20.2", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", - "@types/babel__core": "^7.1.20", - "@types/express": "^4.7.0", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "@types/node": "^16.0.0", "@types/pretty-hrtime": "^1.0.0", "chalk": "^4.1.0", - "esbuild": "^0.16.4", - "esbuild-register": "^3.3.3", - "express": "^4.17.3", + "esbuild": "^0.17.0", + "esbuild-register": "^3.4.0", "file-system-cache": "^2.0.0", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", + "fs-extra": "^11.1.0", + "glob": "^8.1.0", + "glob-promise": "^6.0.2", "handlebars": "^4.7.7", - "lazy-universal-dotenv": "^3.0.1", + "lazy-universal-dotenv": "^4.0.0", "picomatch": "^2.3.0", "pkg-dir": "^5.0.0", "pretty-hrtime": "^1.0.3", "resolve-from": "^5.0.0", - "slash": "^3.0.0", "ts-dedent": "^2.0.0" }, "funding": { @@ -5168,9 +5659,9 @@ } }, "node_modules/@storybook/core-common/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, "node_modules/@storybook/core-common/node_modules/ansi-styles": { @@ -5213,15 +5704,6 @@ "node": ">=8" } }, - "node_modules/@storybook/core-common/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@storybook/core-common/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5235,9 +5717,9 @@ } }, "node_modules/@storybook/core-events": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.0-beta.30.tgz", - "integrity": "sha512-Q+psogB1KJFU6m+Zz4QqJBDVsTsR9vceVaUDceGogGbZEjBXpIAKwAJzVVi62pJKeFHclcCI4JbquYoOu2vK9w==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.12.tgz", + "integrity": "sha512-VTmb/zjbz3o1bg+bATzLigVXMVDC/S1FP8CqIrz4mkiys52139FGzMandL2Y2AecPZPGss7ZRdfma28HKVYTRg==", "dev": true, "funding": { "type": "opencollective", @@ -5245,24 +5727,25 @@ } }, "node_modules/@storybook/core-server": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.0.0-beta.30.tgz", - "integrity": "sha512-GfOg7P53OMR/Qa/DAz9IdRpu0sUJlZdrKv53otu4TnI8OxW+Wcom6Ef16aiwaONivQG78zKPzB5w+0+1f2N5uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.0.12.tgz", + "integrity": "sha512-X35Kmg7y35Ph4J+gCDJrnVgBwlz4/DzOQofUS6rAbi4KvrPWDJXeM2OzOgx6B0abKl4CeMmjuc0tjbg4vbUFuA==", "dev": true, "dependencies": { "@aw-web-design/x-default-browser": "1.4.88", "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/docs-mdx": "next", + "@storybook/builder-manager": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", + "@storybook/csf-tools": "7.0.12", + "@storybook/docs-mdx": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/telemetry": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/telemetry": "7.0.12", + "@storybook/types": "7.0.12", "@types/detect-port": "^1.3.0", "@types/node": "^16.0.0", "@types/node-fetch": "^2.5.7", @@ -5275,7 +5758,7 @@ "compression": "^1.7.4", "detect-port": "^1.3.0", "express": "^4.17.3", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "globby": "^11.0.2", "ip": "^2.0.0", "lodash": "^4.17.21", @@ -5286,7 +5769,6 @@ "read-pkg-up": "^7.0.1", "semver": "^7.3.7", "serve-favicon": "^2.5.0", - "slash": "^3.0.0", "telejson": "^7.0.3", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2", @@ -5299,9 +5781,9 @@ } }, "node_modules/@storybook/core-server/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, "node_modules/@storybook/core-server/node_modules/ansi-styles": { @@ -5344,6 +5826,33 @@ "node": ">=8" } }, + "node_modules/@storybook/core-server/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/core-server/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@storybook/core-server/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -5356,15 +5865,21 @@ "node": ">=8" } }, + "node_modules/@storybook/core-server/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@storybook/core-webpack": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.0.0-beta.30.tgz", - "integrity": "sha512-zVlXka9WlJovzNmtAnuGMPBnQBvOdP2Qi62TXdqRh1ctrCX4obRtleyDJVnzdev9awn6Z+Rfbe/zqOvwISr2vw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.0.12.tgz", + "integrity": "sha512-71tLTurZg5rYfjHuSUtnT8mcKc4CugvXh6DrJSf/1lTFarWvOZkYha9oh4gVokFWpAiK3GM9LE2DlCAozc9Xnw==", "dev": true, "dependencies": { - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "@types/node": "^16.0.0", "ts-dedent": "^2.0.0" }, @@ -5374,29 +5889,27 @@ } }, "node_modules/@storybook/core-webpack/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, "node_modules/@storybook/csf": { - "version": "0.0.2-next.8", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2-next.8.tgz", - "integrity": "sha512-3T6rflW7D9q1iXOR+bidwoNbd9rVUTyjYH/sqsnYjbXhb/aOXsQzGKwNeq9QqZIFVpKfg5BoOF5i7DCMtoGknQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.0.tgz", + "integrity": "sha512-uk+jMXCZ8t38jSTHk2o5btI+aV2Ksbvl6DoOv3r6VaCM1KZqeuMwtwywIQdflkA8/6q/dKT8z8L+g8hC4GC3VQ==", "dev": true, "dependencies": { - "expect-type": "^0.14.2", - "lodash": "^4.17.15", "type-fest": "^2.19.0" } }, "node_modules/@storybook/csf-plugin": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.0.0-beta.30.tgz", - "integrity": "sha512-ny8NCrdJWjSxraCWAGdMjXP1EtHygABCjv6Qcv9OijBexmzET04YwY7HmQlW6B9tq2l86TlFLPyICVtv8wniyA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.0.12.tgz", + "integrity": "sha512-iiH0ynLQV5BYFc0o7RlSJS2S3GT/ffyfbV4rnCnPKdqyo4REEVvmhOuLhwzurtsXsjh+xF6VUYUDN+8/5mbkYw==", "dev": true, "dependencies": { - "@storybook/csf-tools": "7.0.0-beta.30", + "@storybook/csf-tools": "7.0.12", "unplugin": "^0.10.2" }, "funding": { @@ -5405,15 +5918,18 @@ } }, "node_modules/@storybook/csf-tools": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.0.0-beta.30.tgz", - "integrity": "sha512-/CCizDLZSqm3lNO0w+oc1Xqid4/Ix7TikKZxxaOpGipXp4Ehw8iRMjnfHbE+ANq8ZtTdQzOXBxG4LG2noUpHBw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.0.12.tgz", + "integrity": "sha512-EcDzKeENzs4awyjx0VxlONDLibiEtIPDP1XdOCcZGtv3nXXBFtS2WDsYhJHkwyvE37jWTyw2e4xKQmBi0Hjvbw==", "dev": true, "dependencies": { - "@babel/types": "^7.20.2", - "@storybook/csf": "next", - "@storybook/types": "7.0.0-beta.30", - "fs-extra": "^9.0.1", + "@babel/generator": "~7.21.1", + "@babel/parser": "~7.21.2", + "@babel/traverse": "~7.21.2", + "@babel/types": "~7.21.2", + "@storybook/csf": "^0.1.0", + "@storybook/types": "7.0.12", + "fs-extra": "^11.1.0", "recast": "^0.23.1", "ts-dedent": "^2.0.0" }, @@ -5422,34 +5938,22 @@ "url": "https://opencollective.com/storybook" } }, - "node_modules/@storybook/csf/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@storybook/docs-mdx": { - "version": "0.0.1-next.5", - "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.0.1-next.5.tgz", - "integrity": "sha512-EowXFPq4TBZQguKCdU8y7EzpuSv2vSu5gy7pgF/1P5mq7LG9h8YIrerOW9DL4zfp9E0GHIWlSXR5KuFIqqKc/Q==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", + "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", "dev": true }, "node_modules/@storybook/docs-tools": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.0.0-beta.30.tgz", - "integrity": "sha512-pPGI1K0YXWTmRLg8VDy7BiZvUPmRLfdVP05vFEMw+5LpwZNjTI1hn8eQgEIME9eESNOZFj/VhdewPNfyki9M5A==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.0.12.tgz", + "integrity": "sha512-+HykeQLgjyDyF9G7HqY0FHXlX7X5YpQcmNjftJzBrc/GO1EeO0M78d54avcOPyyTfuWOh7oZtSJ0MzjA1qrqaQ==", "dev": true, "dependencies": { "@babel/core": "^7.12.10", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12", "@types/doctrine": "^0.0.3", "doctrine": "^3.0.0", "lodash": "^4.17.21" @@ -5466,17 +5970,16 @@ "dev": true }, "node_modules/@storybook/instrumenter": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.0.0-beta.30.tgz", - "integrity": "sha512-raP9Sq5QmAJ4nf4IRs5hKOBZ3dg5h/GiKtwIlJI6sA5zo3bHzvqApOD308yG4fp2hyeiaBbjFBsDi2Kchrv6uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.0.12.tgz", + "integrity": "sha512-jx4rb4AMT1YIOpE0HCdfyLvpYU+94wPkC9vt7sZGWAp7nnYG+KO/lx3XCJaR9qQPIxVYejJtWkeGn4RID79SoQ==", "dev": true, "dependencies": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30", - "core-js": "^3.8.2" + "@storybook/preview-api": "7.0.12" }, "funding": { "type": "opencollective", @@ -5484,9 +5987,9 @@ } }, "node_modules/@storybook/manager": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.0.0-beta.30.tgz", - "integrity": "sha512-yI9O27g/k/wYGH4/ct/59XytnAy5XU49UxLrOUI3Np1Z+lstOikslqk2g0h3Zp3IFNzXNYZkVgQ2dPWxHeLabA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.0.12.tgz", + "integrity": "sha512-19BsDcwJOYXn6zEarxvNGDdYLUqZyhX92x6GPHSC4cf8BoxHuhmtnz5vOTZHusCxkKIu/C9W0H6wH2Ma47kDCg==", "dev": true, "funding": { "type": "opencollective", @@ -5494,19 +5997,19 @@ } }, "node_modules/@storybook/manager-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.0.0-beta.30.tgz", - "integrity": "sha512-cxEn56WpzI6UMBIaD5rgTeTg67VzREUOLgXIy51W1u7NWSb2T5agHrLzXg3Oaxlh1tL4bronbTibx/qveahtgA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.0.12.tgz", + "integrity": "sha512-3QXARtxpc6Xxqf5pviUw2UuhK53+IsINSljeWhAqdQ1Gzbywl67TpibTd7xVN6NKxhUH5Bzo9bIZTAzMZGqaKw==", "dev": true, "dependencies": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/router": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/router": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", @@ -5524,36 +6027,84 @@ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/@storybook/manager-api/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/manager-api/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/manager-api/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@storybook/mdx2-csf": { - "version": "1.0.0-next.4", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.0.0-next.4.tgz", - "integrity": "sha512-nvRgYdpYvXsvSgCzKc4LQA1JxtJzmv47IsFAsh1rTz5FoHyK8watLU2WqX9T4w52fpFXBHx7RwGEsCRt0XgZlQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", + "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", "dev": true }, "node_modules/@storybook/nextjs": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-7.0.0-beta.30.tgz", - "integrity": "sha512-f8lJ4SFJEc6cp6ktUekiehRd8L9u+WoJCX4QnH630K+4dj5ZoXi+mEP3bSwrW/szkwN9A+P5wobAhTiXi7KTQw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-7.0.12.tgz", + "integrity": "sha512-XFO62uKiS1Cojn2SFQCQXL1RWyylrug1ywKl88OVDmOwBVfJQ/Xm/PMJVp+4dMRFOGQFAIS86uUImNZRHyGsfA==", "dev": true, "dependencies": { - "@next/font": "^13.0.7", - "@storybook/addon-actions": "7.0.0-beta.30", - "@storybook/builder-webpack5": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preset-react-webpack": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/react": "7.0.0-beta.30", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-transform-runtime": "^7.21.0", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@babel/runtime": "^7.21.0", + "@storybook/addon-actions": "7.0.12", + "@storybook/builder-webpack5": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preset-react-webpack": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/react": "7.0.12", "@types/node": "^16.0.0", + "css-loader": "^6.7.3", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "image-size": "^1.0.0", "loader-utils": "^3.2.0", "pnp-webpack-plugin": "^1.7.0", - "postcss-loader": "^6.2.1", + "postcss": "^8.4.21", + "postcss-loader": "^7.0.2", "resolve-url-loader": "^5.0.0", "sass-loader": "^12.4.0", "semver": "^7.3.5", + "style-loader": "^3.3.1", + "styled-jsx": "5.1.1", "ts-dedent": "^2.0.0", "tsconfig-paths": "^4.0.0", "tsconfig-paths-webpack-plugin": "^3.5.2" @@ -5567,6 +6118,7 @@ }, "peerDependencies": { "@babel/core": "^7.11.5", + "@next/font": "^13.0.0", "next": "^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", @@ -5576,38 +6128,235 @@ "@babel/core": { "optional": true }, + "@next/font": { + "optional": true + }, "@storybook/addon-actions": { "optional": true }, "typescript": { "optional": true + }, + "webpack": { + "optional": true } } }, "node_modules/@storybook/nextjs/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, - "node_modules/@storybook/nextjs/node_modules/tsconfig-paths": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", - "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "node_modules/@storybook/nextjs/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/@storybook/nextjs/node_modules/cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" } }, + "node_modules/@storybook/nextjs/node_modules/css-loader": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.4.tgz", + "integrity": "sha512-0Y5uHtK5BswfaGJ+jrO+4pPg1msFBc0pwPIE1VqfpmVn6YbDfYfXMj8rfd7nt+4goAhJueO+H/I40VWJfcP1mQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.1", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@storybook/nextjs/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/nextjs/node_modules/postcss-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.0.tgz", + "integrity": "sha512-qLAFjvR2BFNz1H930P7mj1iuWJFjGey/nVhimfOAAQ1ZyPpcClAxP8+A55Sl8mBvM+K2a9Pjgdj10KpANWrNfw==", + "dev": true, + "dependencies": { + "cosmiconfig": "^8.1.3", + "jiti": "^1.18.2", + "klona": "^2.0.6", + "semver": "^7.3.8" + }, + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/postcss-modules-local-by-default": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.1.tgz", + "integrity": "sha512-Zr/dB+IlXaEqdoslLHhhqecwj73vc3rDmOpsBNBEVk7P2aqAlz+Ijy0fFbU5Ie9PtreDOIgGa9MsLWakVGl+fA==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "dependencies": { + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/nextjs/node_modules/style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "dev": true, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.0.0" + } + }, + "node_modules/@storybook/nextjs/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/@storybook/node-logger": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.0.0-beta.30.tgz", - "integrity": "sha512-mAvPG4smFASwSmb1+nMvR10Zlg/zPmNFeh6IKMttOWS5O0qSVzXGv4/QH63tjBcS0w915W3TGcDLLpKDa0c+lA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.0.12.tgz", + "integrity": "sha512-VL+NXzc9NuOP6/9alg4Sofz9kh8tmlo3p+UtCIYCHH088yCsB3XsNhkG9lF1C5EZVWcuHxc2u6MMF3ezOjvKfQ==", "dev": true, "dependencies": { "@types/npmlog": "^4.1.2", @@ -5673,9 +6422,9 @@ } }, "node_modules/@storybook/postinstall": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.0.0-beta.30.tgz", - "integrity": "sha512-PoM6+UVLd589bM8kg2SNer8ORNMhC3SV894/dfhvgXm7id4weqZ5xnhfZ/T0ZYH2Ts7qSuR+TQmPVAAQNHsrag==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.0.12.tgz", + "integrity": "sha512-RKNvBLgABBTQwvGyF2jX4vP7OMLB3KvEEOQDoeOKjqyWfekDn5smI+eT714mtmKIH0YMcwmvzLgEdZkjmM/XhA==", "dev": true, "funding": { "type": "opencollective", @@ -5683,26 +6432,27 @@ } }, "node_modules/@storybook/preset-react-webpack": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.0.0-beta.30.tgz", - "integrity": "sha512-PF7CAXWv6nS6N5OXnEj3XZKJRIKIFRmIrWwBhdK1L30XCHmQ313/0lA9JV24UHU8EwkUOfyF1IKkikhkKBkTTg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.0.12.tgz", + "integrity": "sha512-EBgP5p8uiwJXPpM5M6mC4SrKCKSeQEJI+oQ36olUIB7PUhysiVFhLB+rOIgkXc3nhX1uRTO/PYefd9PBMwE11A==", "dev": true, "dependencies": { "@babel/preset-flow": "^7.18.6", "@babel/preset-react": "^7.18.6", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5", - "@storybook/core-webpack": "7.0.0-beta.30", - "@storybook/docs-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/react": "7.0.0-beta.30", - "@storybook/react-docgen-typescript-plugin": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", + "@storybook/core-webpack": "7.0.12", + "@storybook/docs-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/react": "7.0.12", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", "@types/node": "^16.0.0", "@types/semver": "^7.3.4", "babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-react-docgen": "^4.2.1", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "react-refresh": "^0.11.0", - "semver": "^7.3.7" + "semver": "^7.3.7", + "webpack": "5" }, "engines": { "node": ">=16.0.0" @@ -5714,8 +6464,7 @@ "peerDependencies": { "@babel/core": "^7.11.5", "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0", - "webpack": "5" + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" }, "peerDependenciesMeta": { "@babel/core": { @@ -5727,15 +6476,48 @@ } }, "node_modules/@storybook/preset-react-webpack/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", + "dev": true + }, + "node_modules/@storybook/preset-react-webpack/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@storybook/preset-react-webpack/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/@storybook/preview": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.0.0-beta.30.tgz", - "integrity": "sha512-mcqs1PB7i/oEx4viFMECA6tI14x29RMGVctPtipkDIo0myo1BAsHSsgALaHRfQCw9mXl5KUiOyiwHQMf0dEkwg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.0.12.tgz", + "integrity": "sha512-za8El/nnkyAo/uqyqAg7PMuP6DSdPoEnDRyIk4LzY7sAGly6i4Uge377cdo1nUBQLS5S4kKIc4xf8TUegb3G1Q==", "dev": true, "funding": { "type": "opencollective", @@ -5743,24 +6525,23 @@ } }, "node_modules/@storybook/preview-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.0.0-beta.30.tgz", - "integrity": "sha512-3klBZJ3gC+B80vJvzvHDh4uHy8+SwNOttcKyOAJOt0IJTNYo2HiAn7rUhaMeHfKzoD/YGiFiRkTrPKJDZJAGUA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.0.12.tgz", + "integrity": "sha512-YI/AfHszIOYt967fsRlc7j6I0zZB+RSsBwD/nMA8y9vszdpQ0MgRhxHgQxFf6cgqbuQcdCsnTIpT0iQ4GHjDXg==", "dev": true, "dependencies": { - "@storybook/channel-postmessage": "7.0.0-beta.30", - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/channel-postmessage": "7.0.12", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/types": "7.0.0-beta.30", + "@storybook/types": "7.0.12", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "slash": "^3.0.0", "synchronous-promise": "^2.0.15", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" @@ -5771,17 +6552,18 @@ } }, "node_modules/@storybook/react": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.0.0-beta.30.tgz", - "integrity": "sha512-tcG+7vkf8/C2Az/Ei23DEfCx7sBqBi/odBEFIKYlZZkDTlkYWdTpcsn1P4fE/QFetwyS6F85aG3Qmluyk7YBQA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.0.12.tgz", + "integrity": "sha512-dKHKc02LSgn3St7U/xj/Rr2DFLbS4dWQka+pS/AOvPPvMAR2gGHVhkmoFuFMf176hUTuE5MCoWBoNJIRMz7ZiQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-client": "7.0.0-beta.30", - "@storybook/docs-tools": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/core-client": "7.0.12", + "@storybook/docs-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/preview-api": "7.0.12", + "@storybook/react-dom-shim": "7.0.12", + "@storybook/types": "7.0.12", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", "@types/node": "^16.0.0", @@ -5815,9 +6597,9 @@ } }, "node_modules/@storybook/react-docgen-typescript-plugin": { - "version": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", - "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0.tgz", - "integrity": "sha512-eVg3BxlOm2P+chijHBTByr90IZVUtgRW56qEOLX7xlww2NBuKrcavBlcmn+HH7GIUktquWkMPtvy6e0W0NgA5w==", + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", "dev": true, "dependencies": { "debug": "^4.1.1", @@ -5825,62 +6607,41 @@ "find-cache-dir": "^3.3.1", "flat-cache": "^3.0.4", "micromatch": "^4.0.2", - "react-docgen-typescript": "^2.1.1", + "react-docgen-typescript": "^2.2.2", "tslib": "^2.0.0" }, "peerDependencies": { - "typescript": ">= 3.x", + "typescript": ">= 4.x", "webpack": ">= 4" } }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@storybook/react-dom-shim": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.0.12.tgz", + "integrity": "sha512-4z9J54TD7uphxPqSuLEzeKTV4oF8Fmv8qFfnT0XZJ2mpYTC2NTbkYoYZQ8N0eYzvNOk6xgfpDqBdmIANf4NaYw==", "dev": true, - "dependencies": { - "ms": "2.1.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, - "node_modules/@storybook/react-docgen-typescript-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@storybook/react/node_modules/@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, - "node_modules/@storybook/react/node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true, - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/@storybook/router": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.0.0-beta.30.tgz", - "integrity": "sha512-hSdVv/IlBA96rf6RpmSCeS2CgxfmvgQOWVR8JR+5M97MjRMtXcIKB3f2ea8JSEPWkOa7i2k8ARunlAAVVmOiPw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.0.12.tgz", + "integrity": "sha512-dOtBiCBGeDem86BCWR7AlTVQjoBk0yw/XZLXS9qcpUfpe+UDjd0Rh21ZdEEMHG1Wfu4d2AhhG5l/JSJ1IE83jQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", "memoizerific": "^1.11.3", "qs": "^6.10.0" }, @@ -5962,13 +6723,13 @@ } }, "node_modules/@storybook/store": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/store/-/store-7.0.0-beta.30.tgz", - "integrity": "sha512-Uzni6jW4cUee2i92jgMshRJh7AcBD79gUJpLz2HmKm7xXypi3TCzpUQi++8OAbfPgRkvk3sGwhcyrfkujJ1KqQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-7.0.12.tgz", + "integrity": "sha512-+gqs6y55fXp9vLrq9VyCGoAHbjfEBMZClkCNksPUBPoLRCY0knxGvhIOoDdcqHkHpm3AQGsfW/ESurbLj/Q76Q==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" }, "funding": { "type": "opencollective", @@ -5976,17 +6737,17 @@ } }, "node_modules/@storybook/telemetry": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.0.0-beta.30.tgz", - "integrity": "sha512-ufmdVxZoAiaIP5VWjbTRrruNTm6OXSvhjCYCpqBJIgMbvEosE5njNJ4ySuyZSjMtLvJy0kdnx7ca+bQQ5ALFuQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.0.12.tgz", + "integrity": "sha512-oxqe15bn5W+1pLpLjXTfj3H+YPZq3jExjdJwTCUHtFrrsNs0k6dyqAUk8qTOUqOTclANHb6vlNBFJDvZ6qbfEQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/core-common": "7.0.12", "chalk": "^4.1.0", "detect-package-manager": "^2.0.1", "fetch-retry": "^5.0.2", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "isomorphic-unfetch": "^3.1.0", "nanoid": "^3.3.1", "read-pkg-up": "^7.0.1" @@ -6062,18 +6823,18 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/addons": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.15.tgz", - "integrity": "sha512-xT31SuSX+kYGyxCNK2nqL7WTxucs3rSmhiCLovJcUjYk+QquV3c2c53Ki7lwwdDbzfXFcNAe0HJ4hoTN4jhn0Q==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.16.tgz", + "integrity": "sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==", "dev": true, "dependencies": { - "@storybook/api": "6.5.15", - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/api": "6.5.16", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", - "@storybook/theming": "6.5.15", + "@storybook/router": "6.5.16", + "@storybook/theming": "6.5.16", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -6089,18 +6850,18 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/api": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.15.tgz", - "integrity": "sha512-BBE0KXKvj1/3jTghbIoWfrcDM0t+xO7EYtWWAXD6XlhGsZVD2Dy82Z52ONyLulMDRpMWl0OYy3h6A1YnFUH25w==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.16.tgz", + "integrity": "sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==", "dev": true, "dependencies": { - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", + "@storybook/router": "6.5.16", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -6122,9 +6883,9 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/channels": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.15.tgz", - "integrity": "sha512-gPpsBgirv2NCXbH4WbYqdkI0JLE96aiVuu7UEWfn9yu071pQ9CLHbhXGD9fSFNrfOkyBBY10ppSE7uCXw3Wexg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.16.tgz", + "integrity": "sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==", "dev": true, "dependencies": { "core-js": "^3.8.2", @@ -6137,9 +6898,9 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/client-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.15.tgz", - "integrity": "sha512-0uyxKvodq+FycGv6aUwC1wUR6suXf2+7ywMFAOlYolI4UvNj8NyU/5AfgKT5XnxYAgPmoCiAjOE700TrfHrosw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.16.tgz", + "integrity": "sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==", "dev": true, "dependencies": { "core-js": "^3.8.2", @@ -6151,9 +6912,9 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/core-events": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.15.tgz", - "integrity": "sha512-B1Ba6l5W7MeNclclqMMTMHgYgfdpB5SIhNCQFnzIz8blynzRhNFMdxvbAl6Je5G0S4xydYYd7Lno2kXQebs7HA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.16.tgz", + "integrity": "sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==", "dev": true, "dependencies": { "core-js": "^3.8.2" @@ -6173,14 +6934,14 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/instrumenter": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.15.tgz", - "integrity": "sha512-93WyH0s63RCv496eHjQ5dWFXoExXg9dlNMe7i4/FVVbWeDdb1pPVIHsLn28WxOiVQahQEAW2EA7Mao3BiBWg+A==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.16.tgz", + "integrity": "sha512-q8/GaBk8PA/cL7m5OW+ec5t63+Zja9YvYSPGXrYtW17koSv7OnNPmk6RvI7tIHHO0mODBYnaHjF4zQfEGoyR5Q==", "dev": true, "dependencies": { - "@storybook/addons": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/addons": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "core-js": "^3.8.2", "global": "^4.4.0" }, @@ -6190,12 +6951,12 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/router": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.15.tgz", - "integrity": "sha512-9t8rI8t7/Krolau29gsdjdbRQ66orONIyP0efp0EukVgv6reNFzb/U14ARrl0uHys6Tl5Xyece9FoakQUdn8Kg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.16.tgz", + "integrity": "sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -6211,12 +6972,12 @@ } }, "node_modules/@storybook/testing-library/node_modules/@storybook/theming": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.15.tgz", - "integrity": "sha512-pgdW0lVZKKXQ4VhIfLHycMmwFSVOY7vLTKnytag4Y8Yz+aXm0bwDN/QxPntFzDH47F1Rcy2ywNnvty8ooDTvuA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.16.tgz", + "integrity": "sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "regenerator-runtime": "^0.13.7" @@ -6247,13 +7008,13 @@ } }, "node_modules/@storybook/theming": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.0.0-beta.30.tgz", - "integrity": "sha512-b3GM3vQfgAbmLvUaMPoAwYVynMAk7iH7H+ig9Dqv5/IJl8KIP7DTD5HAkP+PEzk+WrcOnw7mKDIk6Kt/lD0VWQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.0.12.tgz", + "integrity": "sha512-frBkvH7LF8j23ODaywLK4m4LLscw49oKblkZ+30QZkBAzRf2o3a/QSZW2V1zfBo7ygcXiUJ5bIjh7Y17mMJqbQ==", "dev": true, "dependencies": { "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3" }, @@ -6267,16 +7028,14 @@ } }, "node_modules/@storybook/types": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.0.0-beta.30.tgz", - "integrity": "sha512-udjSzDh8GPxpb0ITZqvooDv+khtyy1z1iNy/5VLOBhWe/vDWXC/mLHKPYlWdNthE9Vm3tJs61n8fTJBuPs2VZg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.0.12.tgz", + "integrity": "sha512-nlvU4MyO2grwPCRQ8alA3AnY1bQxGJ6A4QgJu+1MhtjVenifFlxOQX4H1OiA+YXfjlV096oO5LrxvetJPFAKKQ==", "dev": true, "dependencies": { - "@babel/core": "^7.12.10", - "@storybook/channels": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", "@types/babel__core": "^7.0.0", "@types/express": "^4.7.0", - "express": "^4.17.3", "file-system-cache": "^2.0.0" }, "funding": { @@ -6285,9 +7044,9 @@ } }, "node_modules/@stripe/react-stripe-js": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.16.3.tgz", - "integrity": "sha512-gS6UDGEuM92K50pFB3o//EqqPxmaqpC8IrsBda4P4LxeULoO0pBFSHXJ5Ab6uA7G2lyO2bluvSLereh0OH9GrQ==", + "version": "1.16.5", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.16.5.tgz", + "integrity": "sha512-lVPW3IfwdacyS22pP+nBB6/GNFRRhT/4jfgAK6T2guQmtzPwJV1DogiGGaBNhiKtSY18+yS8KlHSu+PvZNclvQ==", "dependencies": { "prop-types": "^15.7.2" }, @@ -6298,9 +7057,9 @@ } }, "node_modules/@stripe/stripe-js": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.46.0.tgz", - "integrity": "sha512-dkm0zCEoRLu5rTnsIgwDf/QG2DKcalOT2dk1IVgMySOHWTChLyOvQwMYhEduGgLvyYWTwNhAUV4WOLPQvjwLwA==" + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.53.0.tgz", + "integrity": "sha512-qhhAa5WxlgVqh1J41ppyqqQVu6S1T1Q9lDAk2Ho9eI/GjrkMvAHcJpKqhekJRsZ1vjsK4P68PYOcXBXPyNCpnQ==" }, "node_modules/@swc/helpers": { "version": "0.4.11", @@ -6311,9 +7070,9 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", - "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz", + "integrity": "sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==", "dev": true, "dependencies": { "lodash.castarray": "^4.4.0", @@ -6326,20 +7085,20 @@ } }, "node_modules/@tanstack/query-core": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.22.4.tgz", - "integrity": "sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw==", + "version": "4.29.7", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.7.tgz", + "integrity": "sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/react-query": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.23.0.tgz", - "integrity": "sha512-cfQsrecZQjYYueiow4WcK8ItokXJnv+b2OrK8Lf5kF7lM9uCo1ilyygFB8wo4MfxchUBVM6Cs8wq4Ed7fouwkA==", + "version": "4.29.7", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.7.tgz", + "integrity": "sha512-ijBWEzAIo09fB1yd22slRZzprrZ5zMdWYzBnCg5qiXuFbH78uGN1qtGz8+Ed4MuhaPaYSD+hykn+QEKtQviEtg==", "dependencies": { - "@tanstack/query-core": "4.22.4", + "@tanstack/query-core": "4.29.7", "use-sync-external-store": "^1.2.0" }, "funding": { @@ -6459,13 +7218,13 @@ "dev": true }, "node_modules/@types/babel__core": { - "version": "7.1.20", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", - "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", + "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", "dev": true, "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" @@ -6491,9 +7250,9 @@ } }, "node_modules/@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.5.tgz", + "integrity": "sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==", "dev": true, "dependencies": { "@babel/types": "^7.3.0" @@ -6539,9 +7298,9 @@ "dev": true }, "node_modules/@types/ejs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.1.tgz", - "integrity": "sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz", + "integrity": "sha512-ZmiaE3wglXVWBM9fyVC17aGPkLo/UgaOjEiI2FXQfyczrCefORPxIe+2dVmnmk3zkVIbizjrlQzmPGhSYGXG5g==", "dev": true }, "node_modules/@types/escodegen": { @@ -6551,9 +7310,9 @@ "dev": true }, "node_modules/@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", "dev": true, "dependencies": { "@types/estree": "*", @@ -6577,26 +7336,27 @@ "dev": true }, "node_modules/@types/express": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", - "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "dependencies": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.31", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.32", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz", - "integrity": "sha512-aI5h/VOkxOF2Z1saPy0Zsxs5avets/iaiAJYznQFm5By/pamU31xWKL//epiF4OfUA2qTOc9PV6tCUjhO8wlZA==", + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dev": true, "dependencies": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "node_modules/@types/find-cache-dir": { @@ -6605,6 +7365,16 @@ "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", "dev": true }, + "node_modules/@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "dependencies": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "node_modules/@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -6686,33 +7456,28 @@ "dev": true }, "node_modules/@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" }, "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", "dependencies": { "@types/unist": "*" } }, - "node_modules/@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" - }, "node_modules/@types/mdx": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.3.tgz", - "integrity": "sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.5.tgz", + "integrity": "sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==", "dev": true }, "node_modules/@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "node_modules/@types/mime-types": { @@ -6721,6 +7486,12 @@ "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", "dev": true }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "node_modules/@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -6733,9 +7504,9 @@ "dev": true }, "node_modules/@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", "dev": true, "dependencies": { "@types/node": "*", @@ -6803,9 +7574,9 @@ "dev": true }, "node_modules/@types/react": { - "version": "18.0.26", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", - "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "version": "18.2.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz", + "integrity": "sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -6813,9 +7584,9 @@ } }, "node_modules/@types/react-redux": { - "version": "7.1.24", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", - "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", "dependencies": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -6824,20 +7595,30 @@ } }, "node_modules/@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" }, "node_modules/@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "node_modules/@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", "dev": true, "dependencies": { "@types/mime": "*", @@ -6866,9 +7647,9 @@ "dev": true }, "node_modules/@types/yargs": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", - "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "dependencies": { "@types/yargs-parser": "*" @@ -6881,18 +7662,19 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz", - "integrity": "sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.48.1", - "@typescript-eslint/type-utils": "5.48.1", - "@typescript-eslint/utils": "5.48.1", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, @@ -6913,85 +7695,48 @@ } } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", - "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1" + "yallist": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" } }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/@typescript-eslint/eslint-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.0.tgz", - "integrity": "sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.45.0", - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/typescript-estree": "5.45.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "debug": "^4.3.4" }, "engines": { @@ -7010,37 +7755,14 @@ } } }, - "node_modules/@typescript-eslint/parser/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz", - "integrity": "sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/visitor-keys": "5.45.0" + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -7051,13 +7773,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz", - "integrity": "sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.48.1", - "@typescript-eslint/utils": "5.48.1", + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -7077,90 +7799,10 @@ } } }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", - "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/type-utils/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/@typescript-eslint/types": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.0.tgz", - "integrity": "sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -7171,13 +7813,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz", - "integrity": "sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/visitor-keys": "5.45.0", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -7197,42 +7839,52 @@ } } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "yallist": "^4.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">=10" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.1.tgz", - "integrity": "sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", "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.48.1", - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/typescript-estree": "5.48.1", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "engines": { @@ -7246,132 +7898,46 @@ "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", - "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", + "node_modules/@typescript-eslint/utils/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1" + "yallist": "^4.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" + "node": ">=10" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", - "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "node": ">=10" } }, - "node_modules/@typescript-eslint/utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "node_modules/@typescript-eslint/utils/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz", - "integrity": "sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.45.0", + "@typescript-eslint/types": "5.59.6", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -7383,148 +7949,148 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "dependencies": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "dependencies": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -7662,29 +8228,6 @@ "node": ">= 6.0.0" } }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", @@ -7817,9 +8360,9 @@ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "node_modules/anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "dependencies": { "normalize-path": "^3.0.0", @@ -7854,6 +8397,29 @@ "node": ">=10" } }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/are-we-there-yet/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", @@ -7874,23 +8440,14 @@ } }, "node_modules/aria-hidden": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.2.tgz", - "integrity": "sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", "dependencies": { "tslib": "^2.0.0" }, "engines": { "node": ">=10" - }, - "peerDependencies": { - "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", - "react": "^16.9.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } } }, "node_modules/aria-query": { @@ -7902,31 +8459,17 @@ "deep-equal": "^2.0.5" } }, - "node_modules/arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-flatten": { @@ -7963,15 +8506,6 @@ "node": ">=8" } }, - "node_modules/array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -8033,15 +8567,6 @@ "util": "^0.12.0" } }, - "node_modules/assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ast-types": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", @@ -8077,15 +8602,6 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", @@ -8098,9 +8614,9 @@ } }, "node_modules/autoprefixer": { - "version": "10.4.8", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz", - "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==", + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", "dev": true, "funding": [ { @@ -8113,8 +8629,8 @@ } ], "dependencies": { - "browserslist": "^4.21.3", - "caniuse-lite": "^1.0.30001373", + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -8143,9 +8659,9 @@ } }, "node_modules/axe-core": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz", - "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.1.tgz", + "integrity": "sha512-sCXXUhA+cljomZ3ZAwb8i1p3oOlkABzPy08ZDAoGcYuvtBPlQ1Ytde129ArXyHWDhfeewq7rlx9F+cUx2SSlkg==", "dev": true, "engines": { "node": ">=4" @@ -8238,15 +8754,15 @@ "dev": true }, "node_modules/babel-loader/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", + "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 12.13.0" @@ -8312,15 +8828,6 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/babel-plugin-polyfill-corejs3": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.6.0.tgz", @@ -8358,15 +8865,15 @@ } }, "node_modules/babel-plugin-styled-components": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", - "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", + "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.21.4", "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.11", - "picomatch": "^2.3.0" + "lodash": "^4.17.21", + "picomatch": "^2.3.1" }, "peerDependencies": { "styled-components": ">= 2" @@ -8392,45 +8899,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "node_modules/base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "dependencies": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/base/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/base64-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", @@ -8534,6 +9002,27 @@ "readable-stream": "^3.4.0" } }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bl/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/body-parser": { "version": "1.20.1", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", @@ -8558,6 +9047,36 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", @@ -8650,6 +9169,18 @@ "node": ">=8" } }, + "node_modules/boxen/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bplist-parser": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/bplist-parser/-/bplist-parser-0.2.0.tgz", @@ -8690,10 +9221,20 @@ "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", "dev": true }, + "node_modules/browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, + "dependencies": { + "pako": "~0.2.0" + } + }, "node_modules/browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, "funding": [ { "type": "opencollective", @@ -8705,10 +9246,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" }, "bin": { "browserslist": "cli.js" @@ -8774,6 +9315,21 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" }, + "node_modules/bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "dependencies": { + "run-applescript": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -8784,9 +9340,9 @@ } }, "node_modules/c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", + "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", "dev": true, "dependencies": { "@bcoe/v8-coverage": "^0.2.3", @@ -8809,35 +9365,6 @@ "node": ">=10.12.0" } }, - "node_modules/cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "dependencies": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/cache-base/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -8888,14 +9415,17 @@ } }, "node_modules/camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/caniuse-lite": { - "version": "1.0.30001418", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz", - "integrity": "sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==", + "version": "1.0.30001489", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", + "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==", "funding": [ { "type": "opencollective", @@ -8904,6 +9434,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ] }, @@ -8948,6 +9482,14 @@ "node": ">=4" } }, + "node_modules/chalk/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/character-entities": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", @@ -8997,9 +9539,13 @@ } }, "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true, + "engines": { + "node": ">=10" + } }, "node_modules/chrome-trace-event": { "version": "1.0.3", @@ -9011,9 +9557,9 @@ } }, "node_modules/ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true, "funding": [ { @@ -9034,128 +9580,15 @@ "safe-buffer": "^5.0.1" } }, - "node_modules/class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/class-utils/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/class-utils/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, "node_modules/clean-css": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", - "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", "dev": true, "dependencies": { "source-map": "~0.6.0" @@ -9268,19 +9701,6 @@ "node": ">=6" } }, - "node_modules/collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "dependencies": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -9328,9 +9748,9 @@ } }, "node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "node_modules/combined-stream": { @@ -9345,9 +9765,9 @@ } }, "node_modules/comma-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz", - "integrity": "sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -9374,12 +9794,6 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "node_modules/component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "node_modules/compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -9419,6 +9833,21 @@ "node": ">= 0.8" } }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/compression/node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -9452,10 +9881,16 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "node_modules/concat-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "node_modules/concat-stream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "dependencies": { "core-util-is": "~1.0.0", @@ -9507,26 +9942,18 @@ } }, "node_modules/content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "dependencies": { - "safe-buffer": "~5.1.1" - } - }, - "node_modules/convert-source-map/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "node_modules/cookie": { "version": "0.5.0", @@ -9555,19 +9982,11 @@ "node": ">= 0.8" } }, - "node_modules/copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/core-js": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz", - "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==", + "devOptional": true, "hasInstallScript": true, "funding": { "type": "opencollective", @@ -9575,12 +9994,12 @@ } }, "node_modules/core-js-compat": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.1.tgz", - "integrity": "sha512-Dg91JFeCDA17FKnneN7oCMz4BkQ4TcffkgHP4OWwp9yx3pi7ubqMDXXSacfNak1PQqjc95skyt+YBLHQJnkJwA==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.2.tgz", + "integrity": "sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==", "dev": true, "dependencies": { - "browserslist": "^4.21.4" + "browserslist": "^4.21.5" }, "funding": { "type": "opencollective", @@ -9588,9 +10007,9 @@ } }, "node_modules/core-js-pure": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.1.tgz", - "integrity": "sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.30.2.tgz", + "integrity": "sha512-p/npFUJXXBkCCTIlEGBdghofn00jWG6ZOtdoIXSJmAu2QBvN0IqpZXWweOytcwE6cfx8ZvVUy1vw8zxhe4Y2vg==", "dev": true, "hasInstallScript": true, "funding": { @@ -9604,9 +10023,9 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -9638,6 +10057,14 @@ "sha.js": "^2.4.0" } }, + "node_modules/cross-fetch": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", + "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", + "dependencies": { + "node-fetch": "^2.6.11" + } + }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -9687,53 +10114,110 @@ } }, "node_modules/css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", "dev": true, "dependencies": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 8.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" } }, - "node_modules/css-loader/node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "node_modules/css-loader/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/css-loader/node_modules/loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">=4.0.0" + } + }, + "node_modules/css-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/css-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/css-select": { @@ -9753,9 +10237,9 @@ } }, "node_modules/css-to-react-native": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", - "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", "dependencies": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", @@ -9787,9 +10271,9 @@ } }, "node_modules/csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "node_modules/cva": { "name": "class-variance-authority", @@ -9815,11 +10299,19 @@ "dev": true }, "node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "2.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/decode-named-character-reference": { @@ -9863,16 +10355,17 @@ "dev": true }, "node_modules/deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", + "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", + "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", @@ -9880,7 +10373,7 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.0", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", @@ -9890,21 +10383,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/deep-equal/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "node_modules/deep-equal/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -9920,14 +10398,32 @@ "dev": true }, "node_modules/deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true, "engines": { "node": ">=0.10.0" } }, + "node_modules/default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "dependencies": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/default-browser-id": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", @@ -9944,6 +10440,116 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/default-browser/node_modules/execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/default-browser/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/default-browser/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/define-lazy-prop": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", @@ -9954,9 +10560,9 @@ } }, "node_modules/define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "dependencies": { "has-property-descriptors": "^1.0.0", @@ -9969,47 +10575,19 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/define-properties/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/define-property/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/defu": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.1.tgz", - "integrity": "sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz", + "integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==", "dev": true }, "node_modules/del": { @@ -10127,29 +10705,6 @@ "detect-port": "bin/detect-port.js" } }, - "node_modules/detect-port/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/detect-port/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/detective": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz", @@ -10212,9 +10767,9 @@ } }, "node_modules/dom-accessibility-api": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.15.tgz", - "integrity": "sha512-8o+oVqLQZoruQPYy3uAAQtc6YbtSiRq5aPJBhJ82YTJRHvI6ofhYAkC81WmjFTnfUbqg6T3aCglIpU9p/5e7Cw==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, "node_modules/dom-converter": { @@ -10283,9 +10838,9 @@ } }, "node_modules/dompurify": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz", - "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.5.tgz", + "integrity": "sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==", "optional": true }, "node_modules/domutils": { @@ -10313,19 +10868,21 @@ } }, "node_modules/dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true, + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", + "dev": true, + "engines": { + "node": ">=12" + } }, "node_modules/duplexer2": { "version": "0.1.4", @@ -10335,10 +10892,15 @@ "readable-stream": "^2.0.2" } }, + "node_modules/duplexer2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -10362,6 +10924,54 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/duplexify/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/duplexify/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/duplexify/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/duplexify/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10369,9 +10979,9 @@ "dev": true }, "node_modules/ejs": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", - "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, "dependencies": { "jake": "^10.8.5" @@ -10384,9 +10994,10 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "version": "1.4.402", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.402.tgz", + "integrity": "sha512-gWYvJSkohOiBE6ecVYXkrDgNaUjo47QEKK0kQzmWyhkH+yoYiG44bwuicTGNSIQRG3WDMsWVZJLRnJnLNkbWvA==", + "dev": true }, "node_modules/emoji-regex": { "version": "9.2.2", @@ -10432,9 +11043,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", + "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -10475,11 +11086,6 @@ "is-arrayish": "^0.2.1" } }, - "node_modules/error-ex/node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - }, "node_modules/error-stack-parser": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", @@ -10490,35 +11096,45 @@ } }, "node_modules/es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" }, "engines": { "node": ">= 0.4" @@ -10527,15 +11143,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -10556,17 +11163,25 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-get-iterator/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/es-module-lexer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", + "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", "dev": true }, - "node_modules/es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", - "dev": true + "node_modules/es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/es-shim-unscopables": { "version": "1.0.0", @@ -10601,9 +11216,9 @@ "dev": true }, "node_modules/esbuild": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", - "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", "dev": true, "hasInstallScript": true, "bin": { @@ -10613,28 +11228,28 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/android-arm": "0.16.17", - "@esbuild/android-arm64": "0.16.17", - "@esbuild/android-x64": "0.16.17", - "@esbuild/darwin-arm64": "0.16.17", - "@esbuild/darwin-x64": "0.16.17", - "@esbuild/freebsd-arm64": "0.16.17", - "@esbuild/freebsd-x64": "0.16.17", - "@esbuild/linux-arm": "0.16.17", - "@esbuild/linux-arm64": "0.16.17", - "@esbuild/linux-ia32": "0.16.17", - "@esbuild/linux-loong64": "0.16.17", - "@esbuild/linux-mips64el": "0.16.17", - "@esbuild/linux-ppc64": "0.16.17", - "@esbuild/linux-riscv64": "0.16.17", - "@esbuild/linux-s390x": "0.16.17", - "@esbuild/linux-x64": "0.16.17", - "@esbuild/netbsd-x64": "0.16.17", - "@esbuild/openbsd-x64": "0.16.17", - "@esbuild/sunos-x64": "0.16.17", - "@esbuild/win32-arm64": "0.16.17", - "@esbuild/win32-ia32": "0.16.17", - "@esbuild/win32-x64": "0.16.17" + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" } }, "node_modules/esbuild-plugin-alias": { @@ -10655,33 +11270,11 @@ "esbuild": ">=0.12 <1" } }, - "node_modules/esbuild-register/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/esbuild-register/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, "engines": { "node": ">=6" } @@ -10693,11 +11286,14 @@ "dev": true }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escodegen": { @@ -10722,45 +11318,6 @@ "source-map": "~0.6.1" } }, - "node_modules/escodegen/node_modules/levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "dependencies": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/escodegen/node_modules/prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/escodegen/node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -10771,25 +11328,16 @@ "node": ">=0.10.0" } }, - "node_modules/escodegen/node_modules/type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "dependencies": { - "prelude-ls": "~1.1.2" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", - "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { - "@eslint/eslintrc": "^1.4.1", + "@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", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -10799,24 +11347,22 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "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", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -10824,7 +11370,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -10879,15 +11424,6 @@ "eslint-plugin-import": "^2.25.2" } }, - "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-config-airbnb-typescript": { "version": "17.0.0", "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.0.0.tgz", @@ -10904,12 +11440,12 @@ } }, "node_modules/eslint-config-next": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.0.5.tgz", - "integrity": "sha512-lge94W7ME6kNCO96eCykq5GbKbllzmcDNDhh1/llMCRgNPl0+GIQ8dOoM0I7uRQVW56VmTXFybJFXgow11a5pg==", + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.3.tgz", + "integrity": "sha512-1lXwdFi29fKxzeugof/TUE7lpHyJQt5+U4LaUHyvQfHjvsWO77vFNicJv5sX6k0VDVSbnfz0lw+avxI+CinbMg==", "dev": true, "dependencies": { - "@next/eslint-plugin-next": "13.0.5", + "@next/eslint-plugin-next": "13.4.3", "@rushstack/eslint-patch": "^1.1.3", "@typescript-eslint/parser": "^5.42.0", "eslint-import-resolver-node": "^0.3.6", @@ -10930,9 +11466,9 @@ } }, "node_modules/eslint-config-prettier": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", - "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, "bin": { "eslint-config-prettier": "bin/cli.js" @@ -10961,25 +11497,20 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-import-resolver-node/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.2.tgz", - "integrity": "sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", + "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", "dev": true, "dependencies": { "debug": "^4.3.4", - "enhanced-resolve": "^5.10.0", - "get-tsconfig": "^4.2.0", - "globby": "^13.1.2", - "is-core-module": "^2.10.0", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "get-tsconfig": "^4.5.0", + "globby": "^13.1.3", + "is-core-module": "^2.11.0", "is-glob": "^4.0.3", - "synckit": "^0.8.4" + "synckit": "^0.8.5" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -10992,27 +11523,10 @@ "eslint-plugin-import": "*" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/eslint-import-resolver-typescript/node_modules/globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", "dev": true, "dependencies": { "dir-glob": "^3.0.1", @@ -11028,12 +11542,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint-import-resolver-typescript/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/eslint-import-resolver-typescript/node_modules/slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -11047,9 +11555,9 @@ } }, "node_modules/eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "dependencies": { "debug": "^3.2.7" @@ -11072,21 +11580,15 @@ "ms": "^2.1.1" } }, - "node_modules/eslint-module-utils/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, "node_modules/eslint-plugin-import": { - "version": "2.27.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz", - "integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==", + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dev": true, "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.0", + "array.prototype.flatmap": "^1.3.1", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.7", @@ -11128,19 +11630,28 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "node_modules/eslint-plugin-import/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, "bin": { - "semver": "bin/semver.js" + "json5": "lib/cli.js" + } + }, + "node_modules/eslint-plugin-import/node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, "node_modules/eslint-plugin-jsx-a11y": { @@ -11173,15 +11684,6 @@ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" } }, - "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-prettier": { "version": "4.2.1", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", @@ -11204,9 +11706,9 @@ } }, "node_modules/eslint-plugin-react": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.0.tgz", - "integrity": "sha512-vSBi1+SrPiLZCGvxpiZIa28fMEUaMjXtCplrvxcIxGzmFiYdsXQDwInEjuv5/i/2CTTxbkS87tE8lsQ0Qxinbw==", + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dev": true, "dependencies": { "array-includes": "^3.1.6", @@ -11273,15 +11775,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-react/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-plugin-simple-import-sort": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-8.0.0.tgz", @@ -11292,9 +11785,9 @@ } }, "node_modules/eslint-plugin-storybook": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.10.tgz", - "integrity": "sha512-3DKXRey06EhwnTKaG6fgMqGTy4C3z6Ikyv6VVixO5BvaExWQe3yGWIAufrC2Et0OaAMIaMwx9KWjqb/Wq+JxPg==", + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.12.tgz", + "integrity": "sha512-XbIvrq6hNVG6rpdBr+eBw63QhOMLpZneQVSooEDow8aQCWGCk/5vqtap1yxpVydNfSxi3S/3mBBRLQqKUqQRww==", "dev": true, "dependencies": { "@storybook/csf": "^0.0.1", @@ -11319,52 +11812,37 @@ } }, "node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "estraverse": "^4.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=8.0.0" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "engines": { - "node": ">=10" + "node": ">=4.0" } }, "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/ansi-styles": { @@ -11404,39 +11882,26 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/eslint/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "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==", "dev": true, "dependencies": { - "ms": "2.1.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://opencollective.com/eslint" } }, "node_modules/eslint/node_modules/globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -11469,11 +11934,22 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/eslint/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "node_modules/eslint/node_modules/optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } }, "node_modules/eslint/node_modules/supports-color": { "version": "7.2.0", @@ -11487,15 +11963,27 @@ "node": ">=8" } }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -11505,9 +11993,9 @@ } }, "node_modules/espree/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -11529,9 +12017,9 @@ } }, "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "dependencies": { "estraverse": "^5.1.0" @@ -11630,113 +12118,6 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "dependencies": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/expand-brackets/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", @@ -11745,12 +12126,6 @@ "node": ">=6" } }, - "node_modules/expect-type": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-0.14.2.tgz", - "integrity": "sha512-ed3+tr5ujbIYXZ8Pl/VgIphwJQ0q5tBLGGdn7Zvwt1WyPBRX83xjT5pT77P/GkuQbctx0K2ZNSSan7eruJqTCQ==", - "dev": true - }, "node_modules/express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -11793,6 +12168,36 @@ "node": ">= 0.10.0" } }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -11809,37 +12214,6 @@ "node": ">=0.10.0" } }, - "node_modules/extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "dependencies": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extglob/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", @@ -11855,6 +12229,21 @@ "extract-zip": "cli.js" } }, + "node_modules/extract-zip/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/extract-zip/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -11862,9 +12251,9 @@ "dev": true }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "node_modules/fast-glob": { @@ -11914,9 +12303,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -11941,9 +12330,9 @@ } }, "node_modules/fetch-retry": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", - "integrity": "sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", + "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", "dev": true }, "node_modules/fflate": { @@ -11964,27 +12353,13 @@ } }, "node_modules/file-system-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.0.2.tgz", - "integrity": "sha512-lp4BHO4CWqvRyx88Tt3quZic9ZMf4cJyquYq7UI8sH42Bm2ArlBBjKQAalZOo+UfaBassb7X123Lik5qZ/tSAA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", + "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", "dev": true, "dependencies": { - "fs-extra": "^11.1.0", - "ramda": "^0.28.0" - } - }, - "node_modules/file-system-cache/node_modules/fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=14.14" + "fs-extra": "11.1.1", + "ramda": "0.29.0" } }, "node_modules/filelist": { @@ -12055,6 +12430,21 @@ "node": ">= 0.8" } }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", @@ -12177,18 +12567,18 @@ "dev": true }, "node_modules/flow-parser": { - "version": "0.197.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.197.0.tgz", - "integrity": "sha512-yhwkJPxH1JBg0aJunk/jVRy5p3UhVZBGkzL1hq/GK+GaBh6bKr2YKkv6gDuiufaw+i3pKWQgOLtD++1cvrgXLA==", + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", "dev": true, "engines": { "node": ">=0.4.0" } }, "node_modules/follow-redirects": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", "funding": [ { "type": "individual", @@ -12213,15 +12603,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -12323,6 +12704,33 @@ "node": ">=8" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12335,6 +12743,12 @@ "node": ">=8" } }, + "node_modules/fork-ts-checker-webpack-plugin/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -12370,16 +12784,32 @@ "url": "https://www.patreon.com/infusion" } }, - "node_modules/fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, + "node_modules/framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", "dependencies": { - "map-cache": "^0.2.2" + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" }, - "engines": { - "node": ">=0.10.0" + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dependencies": { + "tslib": "^2.1.0" } }, "node_modules/fresh": { @@ -12392,9 +12822,9 @@ } }, "node_modules/fs": { - "version": "0.0.1-security", - "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", - "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha512-YAiVokMCrSIFZiroB1oz51hPiPRVcUtSa4x2U5RYXyhS9VAPdiFigKbPTnOSq7XY8wd3FIVPYmXpo5lMzFmxgg==" }, "node_modules/fs-constants": { "version": "1.0.0", @@ -12402,18 +12832,17 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, "dependencies": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=14.14" } }, "node_modules/fs-minipass": { @@ -12440,6 +12869,12 @@ "node": ">=8" } }, + "node_modules/fs-minipass/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/fs-monkey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.3.tgz", @@ -12522,6 +12957,7 @@ "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, "engines": { "node": ">=6.9.0" } @@ -12536,13 +12972,14 @@ } }, "node_modules/get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dev": true, "dependencies": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" }, "funding": { @@ -12557,6 +12994,15 @@ "node": ">=6" } }, + "node_modules/get-npm-tarball-url": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.0.3.tgz", + "integrity": "sha512-R/PW6RqyaBQNWYaSyfrh54/qtcnOp22FHCCiRhSSZj0FP3KQWCsxxt0DzIdVTbwTqe9CtQfvl/FPD4UIPt4pqw==", + "dev": true, + "engines": { + "node": ">=12.17" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -12607,36 +13053,27 @@ } }, "node_modules/get-tsconfig": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.2.0.tgz", - "integrity": "sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", + "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", "dev": true, "funding": { "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, - "node_modules/get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/giget": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.0.0.tgz", - "integrity": "sha512-KWELZn3Nxq5+0So485poHrFriK9Bn3V/x9y+wgqrHkbmnGbjfLmZ685/SVA/ovW+ewoqW0gVI47pI4yW/VNobQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.1.2.tgz", + "integrity": "sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==", "dev": true, "dependencies": { "colorette": "^2.0.19", - "defu": "^6.1.1", + "defu": "^6.1.2", "https-proxy-agent": "^5.0.1", "mri": "^1.2.0", - "node-fetch-native": "^1.0.1", - "pathe": "^1.0.0", - "tar": "^6.1.12" + "node-fetch-native": "^1.0.2", + "pathe": "^1.1.0", + "tar": "^6.1.13" }, "bin": { "giget": "dist/cli.mjs" @@ -12654,20 +13091,19 @@ "dev": true }, "node_modules/glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -12685,12 +13121,52 @@ "node": ">=10.13.0" } }, + "node_modules/glob-promise": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-6.0.2.tgz", + "integrity": "sha512-Ni2aDyD1ekD6x8/+K4hDriRDbzzfuK4yKpqSymJ4P7IxbtARiOOuU+k40kbHM0sLIlbf1Qh0qdMkAHMZYE6XJQ==", + "dev": true, + "dependencies": { + "@types/glob": "^8.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/ahmadnassri" + }, + "peerDependencies": { + "glob": "^8.0.3" + } + }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true }, + "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==", + "dev": true, + "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==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/global": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", @@ -12709,11 +13185,20 @@ "node": ">=4" } }, - "node_modules/globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/globby": { "version": "11.1.0", @@ -12735,12 +13220,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, "node_modules/gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -12754,9 +13233,9 @@ } }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "node_modules/grapheme-splitter": { @@ -12765,6 +13244,12 @@ "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", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -12779,6 +13264,69 @@ "node": ">=6.0" } }, + "node_modules/gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "dependencies": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "bin": { + "gunzip-maybe": "bin.js" + } + }, + "node_modules/gunzip-maybe/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/gunzip-maybe/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/gunzip-maybe/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/gunzip-maybe/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/gunzip-maybe/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -12849,6 +13397,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -12882,84 +13442,6 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, - "node_modules/has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "dependencies": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-value/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/has-values/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/has-values/node_modules/kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -12973,10 +13455,31 @@ "node": ">=4" } }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, "node_modules/hast-util-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz", - "integrity": "sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==", "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -12991,6 +13494,11 @@ "he": "bin/he" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -12999,6 +13507,11 @@ "react-is": "^16.7.0" } }, + "node_modules/hoist-non-react-statics/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/hosted-git-info": { "version": "2.8.9", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", @@ -13047,9 +13560,9 @@ } }, "node_modules/html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true, "engines": { "node": ">=8" @@ -13073,31 +13586,10 @@ "html-tokenize": "bin/cmd.js" } }, - "node_modules/html-tokenize/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/html-tokenize/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/html-tokenize/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - }, "node_modules/html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.1.tgz", + "integrity": "sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==", "dev": true, "dependencies": { "@types/html-minifier-terser": "^6.0.0", @@ -13200,29 +13692,6 @@ "node": ">= 6" } }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/human-signals": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", @@ -13233,9 +13702,9 @@ } }, "node_modules/i18next": { - "version": "22.4.9", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.4.9.tgz", - "integrity": "sha512-8gWMmUz460KJDQp/ob3MNUX84cVuDRY9PLFPnV8d+Qezz/6dkjxwOaH70xjrCNDO+JrUL25iXfAIN9wUkInNZw==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz", + "integrity": "sha512-sqWuJFj+wJAKQP2qBQ+b7STzxZNUmnSxrehBCCj9vDOW9RDYPfqCaK1Hbh2frNYQuPziz6O2CGoJPwtzY3vAYA==", "funding": [ { "type": "individual", @@ -13254,10 +13723,21 @@ "@babel/runtime": "^7.20.6" } }, - "node_modules/i18next-fs-backend": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.1.1.tgz", - "integrity": "sha512-FTnj+UmNgT3YRml5ruRv0jMZDG7odOL/OP5PF5mOqvXud2vHrPOOs68Zdk6iqzL47cnnM0ZVkK2BAvpFeDJToA==" + "node_modules/i18next-browser-languagedetector": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz", + "integrity": "sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g==", + "dependencies": { + "@babel/runtime": "^7.19.4" + } + }, + "node_modules/i18next-http-backend": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.1.tgz", + "integrity": "sha512-ZXIdn/8NJIBJ0X4hzXfc3STYxKrCKh1fYjji9HPyIpEJfvTvy8/ZlTl8RuTizzCPj2ZcWrfaecyOMKs6bQ7u5A==", + "dependencies": { + "cross-fetch": "3.1.6" + } }, "node_modules/iconv-lite": { "version": "0.4.24", @@ -13272,15 +13752,47 @@ } }, "node_modules/icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/icss-utils/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/icss-utils/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/icss-utils/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.0" } }, "node_modules/ieee754": { @@ -13303,9 +13815,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true, "engines": { "node": ">= 4" @@ -13327,9 +13839,9 @@ } }, "node_modules/immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==", + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -13350,6 +13862,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "engines": { + "node": ">=4" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", @@ -13369,19 +13889,20 @@ } }, "node_modules/infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", + "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", "dependencies": { "axios": "^1.3.3", + "dotenv": "^16.0.3", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" } }, "node_modules/infisical-node/node_modules/axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "dependencies": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -13414,12 +13935,12 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, "node_modules/internal-slot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" }, @@ -13468,18 +13989,6 @@ "node": ">=8" } }, - "node_modules/is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -13497,13 +14006,13 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-typed-array": "^1.1.10" }, "funding": { @@ -13511,9 +14020,9 @@ } }, "node_modules/is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "node_modules/is-bigint": { "version": "1.0.4", @@ -13590,9 +14099,9 @@ } }, "node_modules/is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "dependencies": { "has": "^1.0.3" }, @@ -13600,18 +14109,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -13627,19 +14124,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=0.10.0" - } + "node_modules/is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true }, "node_modules/is-docker": { "version": "2.2.1", @@ -13715,6 +14204,48 @@ "node": ">=0.10.0" } }, + "node_modules/is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -13945,15 +14476,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -13967,9 +14489,10 @@ } }, "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "node_modules/isexe": { "version": "2.0.0", @@ -14021,15 +14544,6 @@ "node": ">=8" } }, - "node_modules/istanbul-lib-instrument/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/istanbul-lib-report": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", @@ -14079,15 +14593,15 @@ } }, "node_modules/jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.6.tgz", + "integrity": "sha512-G43Ub9IYEFfu72sua6rzooi8V8Gz2lkfk48rW20vEWCGizeaEPlKB1Kh8JIA84yQbiAEfqlPmSpGgCKKxH3rDA==", "dev": true, "dependencies": { "async": "^3.2.3", "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "bin": { "jake": "bin/cli.js" @@ -14149,20 +14663,20 @@ } }, "node_modules/jest-haste-map": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", - "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@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.2.0", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" }, @@ -14264,21 +14778,21 @@ } }, "node_modules/jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, "node_modules/jest-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", + "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==", "dev": true, "dependencies": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -14342,13 +14856,13 @@ } }, "node_modules/jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "dependencies": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -14380,14 +14894,13 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", + "node_modules/jiti": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", + "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/js-sdsl" + "bin": { + "jiti": "bin/jiti.js" } }, "node_modules/js-tokens": { @@ -14413,9 +14926,9 @@ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, "node_modules/jscodeshift": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", - "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", "dev": true, "dependencies": { "@babel/core": "^7.13.16", @@ -14431,10 +14944,10 @@ "chalk": "^4.1.2", "flow-parser": "0.*", "graceful-fs": "^4.2.4", - "micromatch": "^3.1.10", + "micromatch": "^4.0.4", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.20.4", + "recast": "^0.21.0", "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, @@ -14460,25 +14973,16 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/jscodeshift/node_modules/braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "node_modules/jscodeshift/node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", "dev": true, "dependencies": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "tslib": "^2.0.1" }, "engines": { - "node": ">=0.10.0" + "node": ">=4" } }, "node_modules/jscodeshift/node_modules/chalk": { @@ -14497,21 +15001,6 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/jscodeshift/node_modules/fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", @@ -14521,113 +15010,13 @@ "node": ">=8" } }, - "node_modules/jscodeshift/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/jscodeshift/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/is-number/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jscodeshift/node_modules/micromatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/recast": { - "version": "0.20.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", - "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", "dev": true, "dependencies": { - "ast-types": "0.14.2", + "ast-types": "0.15.2", "esprima": "~4.0.0", "source-map": "~0.6.1", "tslib": "^2.0.1" @@ -14657,19 +15046,6 @@ "node": ">=8" } }, - "node_modules/jscodeshift/node_modules/to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "dependencies": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/jscodeshift/node_modules/write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", @@ -14713,6 +15089,7 @@ "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, "bin": { "json5": "lib/cli.js" }, @@ -14740,6 +15117,19 @@ "debug": "^2.1.3" } }, + "node_modules/jsonp/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/jsonp/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, "node_modules/jspdf": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.1.tgz", @@ -14780,6 +15170,11 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, "node_modules/keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -14800,9 +15195,10 @@ } }, "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, "engines": { "node": ">=6" } @@ -14832,21 +15228,17 @@ } }, "node_modules/lazy-universal-dotenv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", - "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", + "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", "dev": true, "dependencies": { - "@babel/runtime": "^7.5.0", "app-root-dir": "^1.0.2", - "core-js": "^3.0.4", - "dotenv": "^8.0.0", - "dotenv-expand": "^5.1.0" + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0" }, "engines": { - "node": ">=6.0.0", - "npm": ">=6.0.0", - "yarn": ">=1.0.0" + "node": ">=14.0.0" } }, "node_modules/leven": { @@ -14872,9 +15264,9 @@ } }, "node_modules/lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, "engines": { "node": ">=10" @@ -14976,6 +15368,23 @@ "loose-envify": "cli.js" } }, + "node_modules/lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "dependencies": { + "lottie-web": "^5.10.2" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/lottie-web": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.11.0.tgz", + "integrity": "sha512-9vSt0AtdOH98GKDXwD5LPfFg9Pcmxt5+1BllAbudKM5iqPxpJnJUfuGaP45OyudDrESCOBgsjnntVUTygBNlzw==" + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -14986,20 +15395,18 @@ } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "yallist": "^3.0.2" } }, "node_modules/lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "bin": { "lz-string": "bin/bin.js" @@ -15020,15 +15427,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/make-dir/node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/makeerror": { "version": "1.0.12", "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", @@ -15038,33 +15436,12 @@ "tmpl": "1.0.5" } }, - "node_modules/map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/map-or-similar": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", "dev": true }, - "node_modules/map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "dependencies": { - "object-visit": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/markdown-it": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", @@ -15086,9 +15463,9 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/markdown-to-jsx": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.8.tgz", - "integrity": "sha512-rRSa1aFmFnpDRFAhv5vIkWM4nPaoB9vnzIjuIKa1wGupfn2hdCNeaQHKpu4/muoc8n8J7yowjTP2oncA4/Rbgg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.2.0.tgz", + "integrity": "sha512-3l4/Bigjm4bEqjCR6Xr+d4DtM1X6vvtGsMGSjJYyep8RjjIvcWtrXBS8Wbfe1/P+atKNMccpsraESIaWVplzVg==", "dev": true, "engines": { "node": ">= 10" @@ -15108,13 +15485,51 @@ } }, "node_modules/mdast-util-definitions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz", - "integrity": "sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, + "dependencies": { + "unist-util-visit": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, "dependencies": { - "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/mdast-util-definitions/node_modules/unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "dependencies": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" }, "funding": { "type": "opencollective", @@ -15122,9 +15537,9 @@ } }, "node_modules/mdast-util-from-markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz", - "integrity": "sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", + "integrity": "sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==", "dependencies": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", @@ -15145,18 +15560,15 @@ } }, "node_modules/mdast-util-to-hast": { - "version": "12.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.2.2.tgz", - "integrity": "sha512-lVkUttV9wqmdXFtEBXKcepvU/zfwbhjbkM5rxrquLW55dS1DfOrnAXCk5mg1be1sfY/WfMmayGy1NsbK1GLCYQ==", + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", "dependencies": { "@types/hast": "^2.0.0", "@types/mdast": "^3.0.0", - "@types/mdurl": "^1.0.0", "mdast-util-definitions": "^5.0.0", - "mdurl": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-sanitize-uri": "^1.1.0", "trim-lines": "^3.0.0", - "unist-builder": "^3.0.0", "unist-util-generated": "^2.0.0", "unist-util-position": "^4.0.0", "unist-util-visit": "^4.0.0" @@ -15166,10 +15578,27 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/mdast-util-to-hast/node_modules/mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "dependencies": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, "node_modules/mdast-util-to-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz", - "integrity": "sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "dependencies": { + "@types/mdast": "^3.0.0" + }, "funding": { "type": "opencollective", "url": "https://opencollective.com/unified" @@ -15190,9 +15619,9 @@ } }, "node_modules/memfs": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz", - "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz", + "integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==", "dev": true, "dependencies": { "fs-monkey": "^1.0.3" @@ -15246,9 +15675,9 @@ } }, "node_modules/micromark": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.0.10.tgz", - "integrity": "sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz", + "integrity": "sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==", "funding": [ { "type": "GitHub Sponsors", @@ -15597,9 +16026,9 @@ } }, "node_modules/micromark-util-sanitize-uri": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz", - "integrity": "sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz", + "integrity": "sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==", "funding": [ { "type": "GitHub Sponsors", @@ -15667,27 +16096,6 @@ } ] }, - "node_modules/micromark/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/micromark/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -15783,18 +16191,18 @@ } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/minipass": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", - "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { "node": ">=8" } @@ -15824,51 +16232,11 @@ "node": ">=8" } }, - "node_modules/mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "dependencies": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/mixin-deep/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "node_modules/minizlib/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/mkdirp": { "version": "0.5.6", @@ -15896,9 +16264,9 @@ } }, "node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multipipe": { "version": "1.0.2", @@ -15915,9 +16283,15 @@ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -15925,74 +16299,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "dependencies": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nanomatch/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", @@ -16077,43 +16383,46 @@ } } }, - "node_modules/next-i18next": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-13.0.2.tgz", - "integrity": "sha512-aUHyKT2kztMgEP44zDB5KoW8XZUQawIdOYWXcrMH6lxAcS0kBsKX0uKMzGS5XlgLW88gvOVc3D7NdfCznLgyyg==", + "node_modules/next/node_modules/postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", "funding": [ { - "type": "individual", - "url": "https://locize.com/i18next.html" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" }, { - "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - }, - { - "type": "individual", - "url": "https://locize.com" - }, - { - "type": "individual", - "url": "https://github.com/belgattitude" + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" } ], "dependencies": { - "@babel/runtime": "^7.20.6", - "@types/hoist-non-react-statics": "^3.3.1", - "core-js": "^3", - "hoist-non-react-statics": "^3.3.2", - "i18next-fs-backend": "^2.1.0" + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" }, "engines": { - "node": ">=14" + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/next/node_modules/styled-jsx": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", + "engines": { + "node": ">= 12.0.0" }, "peerDependencies": { - "i18next": "^22.0.6", - "next": ">= 12.0.0", - "react": ">= 17.0.2", - "react-i18next": "^12.1.1" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } } }, "node_modules/no-case": { @@ -16127,9 +16436,9 @@ } }, "node_modules/node-abi": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.30.0.tgz", - "integrity": "sha512-qWO5l3SCqbwQavymOmtTVuCWZE23++S+rxyoHjXqUmPyzRcaoI4lA2gO55/drddGnedAyjA7sk76SfQ5lfUMnw==", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", + "integrity": "sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==", "dependencies": { "semver": "^7.3.5" }, @@ -16137,16 +16446,46 @@ "node": ">=10" } }, + "node_modules/node-abi/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-abi/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, "node_modules/node-addon-api": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz", - "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" }, "node_modules/node-dir": { "version": "0.1.17", @@ -16161,9 +16500,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", - "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -16180,9 +16519,9 @@ } }, "node_modules/node-fetch-native": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz", - "integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.1.1.tgz", + "integrity": "sha512-9VvspTSUp2Sxbl+9vbZTlFGq9lHwE8GDVVekxx6YsNd1YH59sb3Ba8v3Y3cD8PkLNcileGGcA21PFjVl0jzDaw==", "dev": true }, "node_modules/node-int64": { @@ -16192,9 +16531,10 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.11.tgz", + "integrity": "sha512-+M0PwXeU80kRohZ3aT4J/OnR+l9/KD2nVLNNoRgFtnf+umQVFdGBAO2N8+nCnEi0xlh/Wk3zOGC+vNNx+uM79Q==", + "dev": true }, "node_modules/normalize-package-data": { "version": "2.5.0", @@ -16279,97 +16619,6 @@ "node": ">=0.10.0" } }, - "node_modules/object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "dependencies": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/object-copy/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-copy/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", @@ -16380,9 +16629,9 @@ } }, "node_modules/object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -16405,29 +16654,12 @@ } }, "node_modules/object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" - }, - "node_modules/object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "dependencies": { - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-visit/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, "engines": { - "node": ">=0.10.0" + "node": ">= 0.4" } }, "node_modules/object.assign": { @@ -16448,15 +16680,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.assign/node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/object.entries": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.6.tgz", @@ -16501,27 +16724,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object.pick/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/object.values": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", @@ -16590,9 +16792,9 @@ } }, "node_modules/open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "dependencies": { "define-lazy-prop": "^2.0.0", @@ -16607,17 +16809,51 @@ } }, "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/optionator/node_modules/type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "dependencies": { + "prelude-ls": "~1.1.2" }, "engines": { "node": ">= 0.8.0" @@ -16677,6 +16913,12 @@ "node": ">=6" } }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -16734,15 +16976,6 @@ "tslib": "^2.0.3" } }, - "node_modules/pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -16796,11 +17029,74 @@ } }, "node_modules/pathe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", - "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", "dev": true }, + "node_modules/peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + } + }, + "node_modules/peek-stream/node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/peek-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "node_modules/peek-stream/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/peek-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/peek-stream/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/peek-stream/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, "node_modules/pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -16883,19 +17179,22 @@ "node": ">=10" } }, - "node_modules/posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true, - "engines": { - "node": ">=0.10.0" + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" } }, "node_modules/postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -16904,10 +17203,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -16933,9 +17236,9 @@ } }, "node_modules/postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, "dependencies": { "camelcase-css": "^2.0.1" @@ -16948,59 +17251,23 @@ "url": "https://opencollective.com/postcss/" }, "peerDependencies": { - "postcss": "^8.3.3" - } - }, - "node_modules/postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", - "dev": true, - "dependencies": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" - }, - "engines": { - "node": ">= 10" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - "peerDependencies": { - "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" - }, - "peerDependenciesMeta": { - "postcss": { - "optional": true - }, - "ts-node": { - "optional": true - } - } - }, - "node_modules/postcss-load-config/node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", - "dev": true, - "engines": { - "node": ">= 6" + "postcss": "^8.4.21" } }, "node_modules/postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", "dev": true, "dependencies": { "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" }, "engines": { - "node": ">= 12.13.0" + "node": ">= 10.13.0" }, "funding": { "type": "opencollective", @@ -17008,66 +17275,232 @@ }, "peerDependencies": { "postcss": "^7.0.0 || ^8.0.1", - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/postcss-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/postcss-loader/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/postcss-loader/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-extract-imports/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-modules-extract-imports/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-modules-extract-imports/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "engines": { - "node": "^10 || ^12 || >= 14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": ">=0.10.0" } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", "dev": true, "dependencies": { - "icss-utils": "^5.0.0", + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.1.0" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 6" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, - "peerDependencies": { - "postcss": "^8.1.0" + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", "dev": true, "dependencies": { - "postcss-selector-parser": "^6.0.4" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">= 6" + } + }, + "node_modules/postcss-modules-scope/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-modules-scope/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, - "peerDependencies": { - "postcss": "^8.1.0" + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-modules-scope/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "dependencies": { - "icss-utils": "^5.0.0" + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + } + }, + "node_modules/postcss-modules-values/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/postcss-modules-values/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "^10 || ^12 || >= 14" + "node": ">=6.0.0" }, - "peerDependencies": { - "postcss": "^8.1.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-modules-values/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" } }, "node_modules/postcss-nested": { @@ -17108,11 +17541,10 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "node_modules/posthog-js": { - "version": "1.39.4", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.39.4.tgz", - "integrity": "sha512-Elpf1gwyuObueXi89iH+9pP+WhpkiivP8Qwej4RzOLwSTa7Floaa4rgAw7rnCnX1PtRoJ3F0kqb6q9T+aZjRiA==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.58.0.tgz", + "integrity": "sha512-PpH/MwjwV6UHDsv78xFvteEWYgY3O/HTKBnotzmkNCDWgsKzNr978B1AKzgtBU2GzBsnwUfuK+u2O6mxRzFSWw==", "dependencies": { - "@sentry/types": "7.22.0", "fflate": "^0.4.1", "rrweb-snapshot": "^1.1.14" } @@ -17152,9 +17584,9 @@ } }, "node_modules/prettier": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", - "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, "bin": { "prettier": "bin-prettier.js" @@ -17179,15 +17611,15 @@ } }, "node_modules/prettier-plugin-tailwindcss": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz", - "integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.8.tgz", + "integrity": "sha512-KgPcEnJeIijlMjsA6WwYgRs5rh3/q76oInqtMXBA/EMcamrcYJpyhtRhyX1ayT9hnHlHTuO8sIifHF10WuSDKg==", "dev": true, "engines": { "node": ">=12.17.0" }, "peerDependencies": { - "@prettier/plugin-php": "*", + "@ianvs/prettier-plugin-sort-imports": "*", "@prettier/plugin-pug": "*", "@shopify/prettier-plugin-liquid": "*", "@shufo/prettier-plugin-blade": "*", @@ -17204,7 +17636,7 @@ "prettier-plugin-twig-melody": "*" }, "peerDependenciesMeta": { - "@prettier/plugin-php": { + "@ianvs/prettier-plugin-sort-imports": { "optional": true }, "@prettier/plugin-pug": { @@ -17335,15 +17767,6 @@ "node": ">= 6" } }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -17354,15 +17777,20 @@ "react-is": "^16.13.1" } }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "node_modules/property-expr": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz", "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" }, "node_modules/property-information": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.1.1.tgz", - "integrity": "sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", + "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" @@ -17395,10 +17823,31 @@ "once": "^1.3.1" } }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, "node_modules/punycode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz", - "integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==", + "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" @@ -17434,21 +17883,24 @@ "node": ">= 6.0.0" } }, - "node_modules/puppeteer-core/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/puppeteer-core/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": { - "ms": "2.1.2" + "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": ">=6.0" + "node": "*" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/puppeteer-core/node_modules/https-proxy-agent": { @@ -17476,12 +17928,6 @@ "node": ">=4.0.0" } }, - "node_modules/puppeteer-core/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "node_modules/puppeteer-core/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -17504,9 +17950,9 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "dev": true, "dependencies": { "side-channel": "^1.0.4" @@ -17591,9 +18037,9 @@ "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, "node_modules/ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", + "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", "dev": true, "funding": { "type": "opencollective", @@ -17690,9 +18136,9 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "node_modules/react-beautiful-dnd/node_modules/react-redux": { - "version": "7.2.8", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz", - "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==", + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", "dependencies": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -17876,9 +18322,9 @@ } }, "node_modules/react-hook-form": { - "version": "7.43.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.0.tgz", - "integrity": "sha512-/rVEz7T0gLdSFwPqutJ1kn2e0sQNyb9ci/hmwEYr2YG0KF/LSuRLvNrf9QWJM+gj88CjDpDW5Bh/1AD7B2+z9Q==", + "version": "7.43.9", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.9.tgz", + "integrity": "sha512-AUDN3Pz2NSeoxQ7Hs6OhQhDr6gtF9YRuutGDwPQqhSUAHJSgGl2VeY3qN19MG0SucpjgDiuMJ4iC5T5uB+eaNQ==", "engines": { "node": ">=12.22.0" }, @@ -17891,11 +18337,11 @@ } }, "node_modules/react-i18next": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.1.1.tgz", - "integrity": "sha512-mFdieOI0LDy84q3JuZU6Aou1DoWW2fhapcTGeBS8+vWSJuViuoCLQAMYSb0QoHhXS8B0WKUOPpx4cffAP7r/aA==", + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", "dependencies": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.20.6", "html-parse-stringify": "^3.0.1" }, "peerDependencies": { @@ -17921,9 +18367,9 @@ } }, "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "node_modules/react-mailchimp-subscribe": { "version": "2.1.3", @@ -17939,9 +18385,9 @@ } }, "node_modules/react-markdown": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz", - "integrity": "sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A==", + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz", + "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==", "dependencies": { "@types/hast": "^2.0.0", "@types/prop-types": "^15.0.0", @@ -17954,7 +18400,7 @@ "remark-parse": "^10.0.0", "remark-rehype": "^10.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.3.0", + "style-to-object": "^0.4.0", "unified": "^10.0.0", "unist-util-visit": "^4.0.0", "vfile": "^5.0.0" @@ -17968,15 +18414,10 @@ "react": ">=16" } }, - "node_modules/react-markdown/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, "node_modules/react-redux": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz", - "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", "dependencies": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -18011,11 +18452,6 @@ } } }, - "node_modules/react-redux/node_modules/react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -18071,9 +18507,9 @@ } }, "node_modules/react-resizable": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz", - "integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", "dependencies": { "prop-types": "15.x", "react-draggable": "^4.0.3" @@ -18228,18 +18664,21 @@ } }, "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -18253,9 +18692,9 @@ } }, "node_modules/recast": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.1.tgz", - "integrity": "sha512-RokaBcoxSjXUDzz1TXSZmZsSW6ZpLmlA3GGqJ8uuTrQ9hZhEz+4Tpsc+gRvYRJ2BU4H+ZyUlg91eSGDw7bwy7g==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.2.tgz", + "integrity": "sha512-Qv6cPfVZyMOtPszK6PgW70pUgm7gPlFitAPf0Q69rlOA0zLw2XdDcNmPbVGYicFGT9O8I7TZ/0ryJD+6COvIPw==", "dev": true, "dependencies": { "assert": "^2.0.0", @@ -18302,17 +18741,17 @@ } }, "node_modules/redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "dependencies": { "@babel/runtime": "^7.9.2" } }, "node_modules/redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "peerDependencies": { "redux": "^4" } @@ -18349,65 +18788,6 @@ "@babel/runtime": "^7.8.4" } }, - "node_modules/regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/regex-not/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/regex-parser": { "version": "2.2.11", "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", @@ -18415,14 +18795,14 @@ "dev": true }, "node_modules/regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -18431,27 +18811,15 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, "node_modules/regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, "dependencies": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" @@ -18460,12 +18828,6 @@ "node": ">=4" } }, - "node_modules/regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, "node_modules/regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", @@ -18513,19 +18875,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/remark-external-links/node_modules/mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "dependencies": { - "unist-util-visit": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/remark-external-links/node_modules/space-separated-tokens": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", @@ -18576,9 +18925,9 @@ } }, "node_modules/remark-parse": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", - "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", "dependencies": { "@types/mdast": "^3.0.0", "mdast-util-from-markdown": "^1.0.0", @@ -18681,24 +19030,6 @@ "strip-ansi": "^6.0.1" } }, - "node_modules/repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true, - "engines": { - "node": ">=0.10" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -18732,16 +19063,16 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "node_modules/reselect": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz", - "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==" + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, @@ -18753,20 +19084,14 @@ } }, "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", - "deprecated": "https://github.com/lydell/resolve-url#deprecated", - "dev": true - }, "node_modules/resolve-url-loader": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz", @@ -18806,15 +19131,6 @@ "node": ">=0.10.0" } }, - "node_modules/ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "engines": { - "node": ">=0.12" - } - }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -18849,6 +19165,26 @@ "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==", + "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/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -18863,6 +19199,21 @@ "resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-1.1.14.tgz", "integrity": "sha512-eP5pirNjP5+GewQfcOQY4uBiDnpqxNRc65yKPW0eSoU1XamDfc4M8oqpXGMyUyvLyxFDB0q0+DChuxxiU2FXBQ==" }, + "node_modules/run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "dependencies": { + "execa": "^5.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -18916,15 +19267,6 @@ } ] }, - "node_modules/safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "dependencies": { - "ret": "~0.1.10" - } - }, "node_modules/safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -18993,9 +19335,9 @@ } }, "node_modules/schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.8", @@ -19023,17 +19365,12 @@ } }, "node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/send": { @@ -19060,6 +19397,21 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -19125,45 +19477,9 @@ "dev": true }, "node_modules/set-cookie-parser": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", - "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==" - }, - "node_modules/set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "dependencies": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/set-value/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" }, "node_modules/setprototypeof": { "version": "1.2.0", @@ -19201,16 +19517,16 @@ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "node_modules/sharp": { - "version": "0.31.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.31.2.tgz", - "integrity": "sha512-DUdNVEXgS5A97cTagSLIIp8dUZ/lZtk78iNVZgHdHbx1qnQR7JAHY0BnXnwwH39Iw+VKhO08CTYhIg0p98vQ5Q==", + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz", + "integrity": "sha512-kQTFtj7ldpUqSe8kDxoGLZc1rnMFU0AO2pqbX6pLy3b7Oj8ivJIdoKNwxHVQG2HN6XpHPJqCSM2nsma2gOXvOg==", "hasInstallScript": true, "dependencies": { "color": "^4.2.3", "detect-libc": "^2.0.1", - "node-addon-api": "^5.0.0", + "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", - "semver": "^7.3.8", + "semver": "^7.5.0", "simple-get": "^4.0.1", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" @@ -19222,6 +19538,36 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/sharp/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp/node_modules/semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/sharp/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -19260,6 +19606,26 @@ "node": ">=4" } }, + "node_modules/shelljs/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/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -19331,6 +19697,11 @@ "is-arrayish": "^0.3.1" } }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/simple-update-notifier": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", @@ -19367,179 +19738,6 @@ "node": ">=8" } }, - "node_modules/snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "dependencies": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "dependencies": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "dependencies": { - "is-descriptor": "^1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-node/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "dependencies": { - "kind-of": "^3.2.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon-util/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon-util/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/snapdragon/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/snapdragon/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -19556,20 +19754,6 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated", - "dev": true, - "dependencies": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -19595,26 +19779,19 @@ "node": ">=0.10.0" } }, - "node_modules/source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "deprecated": "See https://github.com/lydell/source-map-url#deprecated", - "dev": true - }, "node_modules/space-separated-tokens": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz", - "integrity": "sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", "funding": { "type": "github", "url": "https://github.com/sponsors/wooorm" } }, "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "dependencies": { "spdx-expression-parse": "^3.0.0", @@ -19638,9 +19815,9 @@ } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "node_modules/split-on-first": { @@ -19651,64 +19828,6 @@ "node": ">=6" } }, - "node_modules/split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "dependencies": { - "extend-shallow": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split-string/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -19729,108 +19848,6 @@ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true }, - "node_modules/static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dev": true, - "dependencies": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "dependencies": { - "is-descriptor": "^0.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/static-extend/node_modules/is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "dependencies": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/static-extend/node_modules/kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -19859,12 +19876,12 @@ "dev": true }, "node_modules/storybook": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.0.0-beta.30.tgz", - "integrity": "sha512-hfOtpvNnQ/rXLfojznCs2WdOFbojKx0Gf1W1Ra6DzOBrmUdXzWwRL8X1RUkI6jwUfYuaE97D8gQpfNRlvoqv4A==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.0.12.tgz", + "integrity": "sha512-HKi7NQQTZhBGEU3KUFxTNGtIZcG8+hokiO5TwcIr7s7smAVKdvj9vY5YGsVkiWF39o+5UtafW1B/i9D8lBFsYg==", "dev": true, "dependencies": { - "@storybook/cli": "7.0.0-beta.30" + "@storybook/cli": "7.0.12" }, "bin": { "sb": "index.js", @@ -19876,18 +19893,18 @@ } }, "node_modules/storybook-dark-mode": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-2.0.5.tgz", - "integrity": "sha512-egOMu2tgGttGAMtFZcDLZobs1xc7LzFOh+pRVqaW59AVp05ABdQ3Hj6IX2Pz7tYGmF9AmaK+nBv0hDFxPe7Hfg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-2.1.1.tgz", + "integrity": "sha512-Ops6u/htODxIUXnAYASttqcbd2PRN723o0uIKpoYQn1+so2g6gYalpAhuysxnRhCG8yHsm6NJuX5drzzI+uFvQ==", "dev": true, "dependencies": { "@storybook/addons": "^6.5.14", "@storybook/api": "^6.5.14", "@storybook/components": "^6.5.14", "@storybook/core-events": "^6.5.14", + "@storybook/global": "^5.0.0", "@storybook/theming": "^6.5.14", "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", "memoizerific": "^1.11.3" }, "peerDependencies": { @@ -19904,18 +19921,18 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/addons": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.15.tgz", - "integrity": "sha512-xT31SuSX+kYGyxCNK2nqL7WTxucs3rSmhiCLovJcUjYk+QquV3c2c53Ki7lwwdDbzfXFcNAe0HJ4hoTN4jhn0Q==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.16.tgz", + "integrity": "sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==", "dev": true, "dependencies": { - "@storybook/api": "6.5.15", - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/api": "6.5.16", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", - "@storybook/theming": "6.5.15", + "@storybook/router": "6.5.16", + "@storybook/theming": "6.5.16", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -19931,18 +19948,18 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/api": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.15.tgz", - "integrity": "sha512-BBE0KXKvj1/3jTghbIoWfrcDM0t+xO7EYtWWAXD6XlhGsZVD2Dy82Z52ONyLulMDRpMWl0OYy3h6A1YnFUH25w==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.16.tgz", + "integrity": "sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==", "dev": true, "dependencies": { - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", + "@storybook/router": "6.5.16", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -19964,9 +19981,9 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/channels": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.15.tgz", - "integrity": "sha512-gPpsBgirv2NCXbH4WbYqdkI0JLE96aiVuu7UEWfn9yu071pQ9CLHbhXGD9fSFNrfOkyBBY10ppSE7uCXw3Wexg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.16.tgz", + "integrity": "sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==", "dev": true, "dependencies": { "core-js": "^3.8.2", @@ -19979,9 +19996,9 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/client-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.15.tgz", - "integrity": "sha512-0uyxKvodq+FycGv6aUwC1wUR6suXf2+7ywMFAOlYolI4UvNj8NyU/5AfgKT5XnxYAgPmoCiAjOE700TrfHrosw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.16.tgz", + "integrity": "sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==", "dev": true, "dependencies": { "core-js": "^3.8.2", @@ -19993,14 +20010,14 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/components": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.15.tgz", - "integrity": "sha512-bHTT0Oa3s4g+MBMaLBbX9ofMtb1AW59AzIUNGrfqW1XqJMGuUHMiJ7TSo+i5dRSFpbFygnwMEG9LfHxpR2Z0Dw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.16.tgz", + "integrity": "sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA==", "dev": true, "dependencies": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -20017,9 +20034,9 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/core-events": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.15.tgz", - "integrity": "sha512-B1Ba6l5W7MeNclclqMMTMHgYgfdpB5SIhNCQFnzIz8blynzRhNFMdxvbAl6Je5G0S4xydYYd7Lno2kXQebs7HA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.16.tgz", + "integrity": "sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==", "dev": true, "dependencies": { "core-js": "^3.8.2" @@ -20039,12 +20056,12 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/router": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.15.tgz", - "integrity": "sha512-9t8rI8t7/Krolau29gsdjdbRQ66orONIyP0efp0EukVgv6reNFzb/U14ARrl0uHys6Tl5Xyece9FoakQUdn8Kg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.16.tgz", + "integrity": "sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -20060,12 +20077,12 @@ } }, "node_modules/storybook-dark-mode/node_modules/@storybook/theming": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.15.tgz", - "integrity": "sha512-pgdW0lVZKKXQ4VhIfLHycMmwFSVOY7vLTKnytag4Y8Yz+aXm0bwDN/QxPntFzDH47F1Rcy2ywNnvty8ooDTvuA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.16.tgz", + "integrity": "sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==", "dev": true, "dependencies": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "regenerator-runtime": "^0.13.7" @@ -20095,6 +20112,12 @@ "memoizerific": "^1.11.3" } }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "node_modules/strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", @@ -20104,12 +20127,9 @@ } }, "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "node_modules/string-width": { "version": "4.2.3", @@ -20150,6 +20170,23 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -20241,33 +20278,78 @@ } }, "node_modules/style-loader": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", - "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", "dev": true, + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, "engines": { - "node": ">= 12.13.0" + "node": ">= 8.9.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "webpack": "^5.0.0" + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/style-loader/node_modules/loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + }, + "engines": { + "node": ">=8.9.0" + } + }, + "node_modules/style-loader/node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, "node_modules/style-to-object": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", - "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", + "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", "dependencies": { "inline-style-parser": "0.1.1" } }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, "node_modules/styled-components": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.7.tgz", - "integrity": "sha512-JL1b4A79OGqav4TxkrNsuuQfy6ZnrpyQx6hBDQ3Hd3JyuR2IQuVNBpF+FCEWFNZpN5hj+fhkaEVWteVJ18f0tw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.10.tgz", + "integrity": "sha512-3kSzSBN0TiCnGJM04UwO1HklIQQSXW7rCARUk+VyMR7clz8XVlA3jijtf5ypqoDIdNMKx3la4VvaPFR855SFcg==", "dependencies": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -20293,10 +20375,27 @@ "react-is": ">= 16.8.0" } }, + "node_modules/styled-components/node_modules/@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "dependencies": { + "@emotion/memoize": "^0.8.1" + } + }, + "node_modules/styled-components/node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "node_modules/styled-jsx": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dev": true, + "dependencies": { + "client-only": "0.0.1" + }, "engines": { "node": ">= 12.0.0" }, @@ -20313,9 +20412,9 @@ } }, "node_modules/stylis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", - "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "node_modules/supports-color": { "version": "5.5.0", @@ -20349,19 +20448,19 @@ } }, "node_modules/synchronous-promise": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.16.tgz", - "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", + "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", "dev": true }, "node_modules/synckit": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.4.tgz", - "integrity": "sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", "dev": true, "dependencies": { "@pkgr/utils": "^2.3.1", - "tslib": "^2.4.0" + "tslib": "^2.5.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -20371,14 +20470,18 @@ } }, "node_modules/tailwind-merge": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.8.1.tgz", - "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.12.0.tgz", + "integrity": "sha512-Y17eDp7FtN1+JJ4OY0Bqv9OA41O+MS8c1Iyr3T6JFLnOgLg3EvcyMKZAnQ8AGyvB5Nxm3t9Xb5Mhe139m8QT/g==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } }, "node_modules/tailwindcss": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", - "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", + "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", "dev": true, "dependencies": { "arg": "^5.0.2", @@ -20395,12 +20498,12 @@ "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.18", + "postcss": "^8.0.9", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.10", + "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.1" @@ -20416,28 +20519,55 @@ "postcss": "^8.0.9" } }, - "node_modules/tailwindcss/node_modules/postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - } - ], "dependencies": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" }, "engines": { - "node": "^10 || ^12 || >=14" + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" } }, "node_modules/tapable": { @@ -20450,14 +20580,14 @@ } }, "node_modules/tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" @@ -20477,6 +20607,11 @@ "tar-stream": "^2.1.4" } }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, "node_modules/tar-stream": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", @@ -20492,13 +20627,25 @@ "node": ">=6" } }, - "node_modules/tar/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, "engines": { - "node": ">=10" + "node": ">= 6" + } + }, + "node_modules/tar-stream/node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dependencies": { + "safe-buffer": "~5.2.0" } }, "node_modules/tar/node_modules/mkdirp": { @@ -20513,10 +20660,16 @@ "node": ">=10" } }, + "node_modules/tar/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/telejson": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.0.4.tgz", - "integrity": "sha512-J4QEuCnYGXAI9KSN7RXK0a0cOW2ONpjc4IQbInGZ6c3stvplLAYyZjTnScrRd8deXVjNCFV1wXcLC7SObDuQYA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.1.0.tgz", + "integrity": "sha512-jFJO4P5gPebZAERPkJsqMAQ0IMA1Hi0AoSfxpnUaV6j6R2SZqlpkbS20U6dEUtA3RUYt2Ak/mTlkQzHH9Rv/hA==", "dev": true, "dependencies": { "memoizerific": "^1.11.3" @@ -20543,6 +20696,26 @@ "node": ">=8" } }, + "node_modules/temp/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/temp/node_modules/rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -20587,9 +20760,9 @@ } }, "node_modules/terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.17.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.5.tgz", + "integrity": "sha512-NqFkzBX34WExkCbk3K5urmNCpEWqMPZnwGI1pMHwqvJ/zDlXC75u3NI7BrzoR8/pryy8Abx2e1i8ChrWkhH1Hg==", "dev": true, "dependencies": { "@jridgewell/source-map": "^0.3.2", @@ -20605,16 +20778,16 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "dependencies": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "engines": { "node": ">= 10.13.0" @@ -20677,9 +20850,9 @@ } }, "node_modules/terser/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -20708,6 +20881,26 @@ "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-segmentation": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/text-segmentation/-/text-segmentation-1.0.3.tgz", @@ -20737,26 +20930,10 @@ "xtend": "~2.1.1" } }, - "node_modules/through2/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "node_modules/through2/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/through2/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + "node_modules/through2/node_modules/object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" }, "node_modules/through2/node_modules/xtend": { "version": "2.1.2", @@ -20769,20 +20946,22 @@ "node": ">=0.4" } }, - "node_modules/tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "dependencies": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, "node_modules/tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "node_modules/titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/tmpl": { "version": "1.0.5", @@ -20798,55 +20977,10 @@ "node": ">=4" } }, - "node_modules/to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dev": true, - "dependencies": { - "kind-of": "^3.0.2" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-object-path/node_modules/is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "node_modules/to-object-path/node_modules/kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "dependencies": { - "is-buffer": "^1.1.5" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/to-querystring": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-querystring/-/to-querystring-1.1.1.tgz", - "integrity": "sha512-ZgIacl9TXAoT7sGXUYjQiy0MW7Tf/7CJQLt757hYHfXXc8JBzOVBMx4DckqKUO4hi36J72/m8UcH/GCHK+n97g==" - }, - "node_modules/to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "dependencies": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/to-querystring/-/to-querystring-1.2.0.tgz", + "integrity": "sha512-V4qvlRNOltdNxvWGuDS71sNMH6FtFNx3GP967WT8gb6xzi4thJTUfogIln9hvz1ZmWcm9hY35LklMexo0YVHdg==" }, "node_modules/to-regex-range": { "version": "5.0.1", @@ -20860,52 +20994,6 @@ "node": ">=8.0" } }, - "node_modules/to-regex/node_modules/extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "dependencies": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/to-regex/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -20967,15 +21055,17 @@ } }, "node_modules/tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "dependencies": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" } }, "node_modules/tsconfig-paths-webpack-plugin": { @@ -21029,6 +21119,18 @@ "node": ">=8" } }, + "node_modules/tsconfig-paths-webpack-plugin/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tsconfig-paths-webpack-plugin/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -21041,22 +21143,22 @@ "node": ">=8" } }, - "node_modules/tsconfig-paths/node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "node_modules/tsconfig-paths-webpack-plugin/node_modules/tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", "dev": true, "dependencies": { - "minimist": "^1.2.0" - }, - "bin": { - "json5": "lib/cli.js" + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" } }, "node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "node_modules/tsscmp": { "version": "1.0.6", @@ -21121,12 +21223,12 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true, "engines": { - "node": ">=10" + "node": ">=12.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -21145,6 +21247,20 @@ "node": ">= 0.6" } }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -21152,9 +21268,9 @@ "dev": true }, "node_modules/typescript": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "devOptional": true, "bin": { "tsc": "bin/tsc", @@ -21261,21 +21377,6 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "dependencies": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -21288,10 +21389,19 @@ "node": ">=8" } }, - "node_modules/unist-builder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz", - "integrity": "sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==", + "node_modules/unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + } + }, + "node_modules/unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", "dependencies": { "@types/unist": "^2.0.0" }, @@ -21300,28 +21410,10 @@ "url": "https://opencollective.com/unified" } }, - "node_modules/unist-util-generated": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz", - "integrity": "sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz", - "integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, "node_modules/unist-util-position": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.3.tgz", - "integrity": "sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", "dependencies": { "@types/unist": "^2.0.0" }, @@ -21331,9 +21423,9 @@ } }, "node_modules/unist-util-stringify-position": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz", - "integrity": "sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", "dependencies": { "@types/unist": "^2.0.0" }, @@ -21343,9 +21435,9 @@ } }, "node_modules/unist-util-visit": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.1.tgz", - "integrity": "sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", @@ -21357,9 +21449,9 @@ } }, "node_modules/unist-util-visit-parents": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz", - "integrity": "sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", "dependencies": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" @@ -21405,9 +21497,9 @@ } }, "node_modules/unplugin/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -21416,63 +21508,6 @@ "node": ">=0.4.0" } }, - "node_modules/unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, - "dependencies": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "dependencies": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "dependencies": { - "isarray": "1.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/unset-value/node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/untildify": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", @@ -21483,9 +21518,10 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -21494,6 +21530,10 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { @@ -21501,7 +21541,7 @@ "picocolors": "^1.0.0" }, "bin": { - "browserslist-lint": "cli.js" + "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" @@ -21516,22 +21556,6 @@ "punycode": "^2.1.0" } }, - "node_modules/urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "deprecated": "Please see https://github.com/lydell/urix#deprecated", - "dev": true - }, - "node_modules/use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/use-callback-ref": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", @@ -21573,6 +21597,19 @@ "react": "^16.8.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "dev": true, + "dependencies": { + "@juggle/resize-observer": "^3.3.1" + }, + "peerDependencies": { + "react": "16.8.0 - 18", + "react-dom": "16.8.0 - 18" + } + }, "node_modules/use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", @@ -21652,12 +21689,6 @@ "uuid": "dist/bin/uuid" } }, - "node_modules/uuid-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", - "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", - "dev": true - }, "node_modules/uuidv4": { "version": "6.2.13", "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", @@ -21684,10 +21715,18 @@ "node": ">=8" } }, + "node_modules/uvu/node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "engines": { + "node": ">=6" + } + }, "node_modules/v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.12", @@ -21718,9 +21757,9 @@ } }, "node_modules/vfile": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.5.tgz", - "integrity": "sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", "dependencies": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", @@ -21733,9 +21772,9 @@ } }, "node_modules/vfile-message": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", - "integrity": "sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", "dependencies": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" @@ -21781,22 +21820,22 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "node_modules/webpack": { - "version": "5.76.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", - "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.1.tgz", + "integrity": "sha512-TNsG9jDScbNuB+Lb/3+vYolPplCS3bbEaJf+Bj0Gw4DhP3ioAflBb1flcRt9zsWITyvOhM96wMQNRWlSX52DgA==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.14.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -21805,9 +21844,9 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.1.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, @@ -21885,15 +21924,15 @@ "dev": true }, "node_modules/webpack-dev-middleware/node_modules/schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", + "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" }, "engines": { "node": ">= 12.13.0" @@ -21929,10 +21968,16 @@ "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==", "dev": true }, + "node_modules/webpack/node_modules/@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, "node_modules/webpack/node_modules/acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -21942,36 +21987,14 @@ } }, "node_modules/webpack/node_modules/acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, "peerDependencies": { "acorn": "^8" } }, - "node_modules/webpack/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/webpack/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -22134,9 +22157,9 @@ } }, "node_modules/ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "dev": true, "engines": { "node": ">=10.0.0" @@ -22173,14 +22196,15 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "node_modules/yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==", "engines": { "node": ">= 14" } @@ -22254,23 +22278,13 @@ }, "dependencies": { "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", - "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" - } - } } }, "@aw-web-design/x-default-browser": { @@ -22283,67 +22297,50 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz", + "integrity": "sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==", "requires": { "@babel/highlight": "^7.18.6" } }, "@babel/compat-data": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", - "integrity": "sha512-KZXo2t10+/jxmkhNXc7pZTqRvSOIvVv/+lJwHS+B2rErwOyjuVRh60yVpb7liQ1U5t7lLJ1bz+t8tSypUZdm0g==" + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.21.9.tgz", + "integrity": "sha512-FUGed8kfhyWvbYug/Un/VPJD41rDIgoVVcR+FuzhzOYyRz5uED+Gd3SLZml0Uw2l2aHFb7ZgdW5mGA3G2cCCnQ==", + "dev": true }, "@babel/core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.20.5.tgz", - "integrity": "sha512-UdOWmk4pNWTm/4DlPUl/Pt4Gz4rcEMb7CY0Y3eJl5Yz1vI8ZJGmHWaVE55LoxRjdpx0z259GE9U5STA9atUinQ==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.21.8.tgz", + "integrity": "sha512-YeM22Sondbo523Sz0+CirSPnbj9bG3P0CdHcBZdqUuaeOaYEFbOLoGU7lebvGP6P5J/WE9wOn7u7C4J9HvS1xQ==", + "dev": true, "requires": { - "@ampproject/remapping": "^2.1.0", - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-module-transforms": "^7.20.2", - "@babel/helpers": "^7.20.5", - "@babel/parser": "^7.20.5", - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5", + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helpers": "^7.21.5", + "@babel/parser": "^7.21.8", + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5", "convert-source-map": "^1.7.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", - "json5": "^2.2.1", + "json5": "^2.2.2", "semver": "^6.3.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - } } }, "@babel/generator": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.7.tgz", - "integrity": "sha512-7wqMOJq8doJMZmP4ApXTzLxSr7+oO2jroJURrVEp6XShrQUObV8Tq/D0NCcoYg2uHqUrjzO0zwBjoYzelxK+sw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.21.9.tgz", + "integrity": "sha512-F3fZga2uv09wFdEjEQIJxXALXfz0+JaOb7SabvVMmjHxeVTuGW8wgE8Vp1Hd7O+zMTYtcfEISGRzPkeiaPPsvg==", "requires": { - "@babel/types": "^7.20.7", + "@babel/types": "^7.21.5", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" } }, @@ -22356,71 +22353,53 @@ } }, "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.18.9.tgz", - "integrity": "sha512-yFQ0YCHoIqarl8BCRwBL8ulYUaZpz3bNsA7oFepAzee+8/+ImtADXNOmO5vJvsPff3qi+hvpkY/NYBTrBQgdNw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.21.5.tgz", + "integrity": "sha512-uNrjKztPLkUk7bpCNC0jEKDJzzkvel/W+HguzbN8krA+LPfC1CEobJEvAvGka2A/M+ViOqXdcRL0GqPUJSjx9g==", "dev": true, "requires": { - "@babel/helper-explode-assignable-expression": "^7.18.6", - "@babel/types": "^7.18.9" + "@babel/types": "^7.21.5" } }, "@babel/helper-compilation-targets": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.20.7.tgz", - "integrity": "sha512-4tGORmfQcrc+bvrjb5y3dG9Mx1IOZjsHqQVUz7XCNHO+iTmqxWnVg3KRygjGmpRLJGdQSKuvFinbIb0CnZwHAQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.21.5.tgz", + "integrity": "sha512-1RkbFGUKex4lvsB9yhIfWltJM5cZKUftB2eNajaDv3dCMEp49iBG0K14uH8NnX9IPux2+mK7JGEOB0jn48/J6w==", + "dev": true, "requires": { - "@babel/compat-data": "^7.20.5", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "browserslist": "^4.21.3", "lru-cache": "^5.1.1", "semver": "^6.3.0" - }, - "dependencies": { - "lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "requires": { - "yallist": "^3.0.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" - }, - "yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" - } } }, "@babel/helper-create-class-features-plugin": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.20.12.tgz", - "integrity": "sha512-9OunRkbT0JQcednL0UFvbfXpAsUXiGjUk0a7sN8fUXX7Mue79cUSMjHGDRRi/Vz9vYlpIhLV5fMD5dKoMhhsNQ==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.21.8.tgz", + "integrity": "sha512-+THiN8MqiH2AczyuZrnrKL6cAxFRRQDKW9h1YkBvbgKmAm6mwiacig1qT73DHIWMGo40GRnsEfN3LA+E6NtmSw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-function-name": "^7.21.0", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", - "@babel/helper-replace-supers": "^7.20.7", + "@babel/helper-replace-supers": "^7.21.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", - "@babel/helper-split-export-declaration": "^7.18.6" + "@babel/helper-split-export-declaration": "^7.18.6", + "semver": "^6.3.0" } }, "@babel/helper-create-regexp-features-plugin": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.20.5.tgz", - "integrity": "sha512-m68B1lkg3XDGX5yCvGO0kPx3v9WIYLnzjKfPcQiwntEQa5ZeRkPmo2X/ISJc8qxWGfwUr+kvZAeEzAwLec2r2w==", + "version": "7.21.8", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.21.8.tgz", + "integrity": "sha512-zGuSdedkFtsFHGbexAvNuipg1hbtitDLo2XE8/uf6Y9sOQV1xsYX/2pNbtedp/X0eU1pIt+kGvaqHCowkRbS5g==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "regexpu-core": "^5.2.1" + "regexpu-core": "^5.3.1", + "semver": "^6.3.0" } }, "@babel/helper-define-polyfill-provider": { @@ -22435,52 +22414,20 @@ "lodash.debounce": "^4.0.8", "resolve": "^1.14.2", "semver": "^6.1.2" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==" - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.18.6.tgz", - "integrity": "sha512-eyAYAsQmB80jNfg4baAtLeWAQHfHFiR483rzFK+BhETlGZaQC9bsfrugfXDCbRHLQbIA7U5NxhhOxN7p/dWIcg==", - "dev": true, - "requires": { - "@babel/types": "^7.18.6" - } + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.21.5.tgz", + "integrity": "sha512-IYl4gZ3ETsWocUWgsFZLM5i1BYx9SoemminVEXadgLBa9TdeorzgLKm8wWLA6J1N/kT3Kch8XIk1laNzYoHKvQ==" }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "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==", "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.20.7", + "@babel/types": "^7.21.0" } }, "@babel/helper-hoist-variables": { @@ -22492,35 +22439,36 @@ } }, "@babel/helper-member-expression-to-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.20.7.tgz", - "integrity": "sha512-9J0CxJLq315fEdi4s7xK5TQaNYjZw+nDVpVqr1axNGKzdrdwYBD5b4uKv3n75aABG0rCCTK8Im8Ww7eYfMrZgw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.21.5.tgz", + "integrity": "sha512-nIcGfgwpH2u4n9GG1HpStW5Ogx7x7ekiFHbjjFRKXbn5zUvqO9ZgotCO4x1aNbKn/x/xOUaXEhyNHCwtFCpxWg==", "dev": true, "requires": { - "@babel/types": "^7.20.7" + "@babel/types": "^7.21.5" } }, "@babel/helper-module-imports": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.18.6.tgz", - "integrity": "sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==", + "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==", "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.21.4" } }, "@babel/helper-module-transforms": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.20.11.tgz", - "integrity": "sha512-uRy78kN4psmji1s2QtbtcCSaj/LILFDp0f/ymhpQH5QY3nljUZCaNWz9X1dEj/8MBdBEFECs7yRhKn8i7NjZgg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.21.5.tgz", + "integrity": "sha512-bI2Z9zBGY2q5yMHoBvJ2a9iX3ZOAzJPm7Q8Yz6YeoUjU/Cvhmi2G4QyTNyPBqqXSgTjUxRg3L0xV45HvkNWWBw==", + "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-simple-access": "^7.20.2", + "@babel/helper-environment-visitor": "^7.21.5", + "@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.20.7", - "@babel/traverse": "^7.20.10", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" } }, "@babel/helper-optimise-call-expression": { @@ -22533,9 +22481,10 @@ } }, "@babel/helper-plugin-utils": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.20.2.tgz", - "integrity": "sha512-8RvlJG2mj4huQ4pZ+rU9lqKi9ZKiRmuvGuM2HlWmkmgOhbs6zEAw6IEiJ5cQqGbDzGZOhwuOQNtZMi/ENLjZoQ==" + "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==", + "dev": true }, "@babel/helper-remap-async-to-generator": { "version": "7.18.9", @@ -22550,25 +22499,26 @@ } }, "@babel/helper-replace-supers": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.20.7.tgz", - "integrity": "sha512-vujDMtB6LVfNW13jhlCrp48QNslK6JXi7lQG736HVbHz/mbf4Dc7tIRh1Xf5C0rF7BP8iiSxGMCmY6Ci1ven3A==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.21.5.tgz", + "integrity": "sha512-/y7vBgsr9Idu4M6MprbOVUfH3vs7tsIfnVWv/Ml2xgwvyH6LTngdfbf5AdsKwkJy4zgy1X/kuNrEKvhhK28Yrg==", "dev": true, "requires": { - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-member-expression-to-functions": "^7.20.7", + "@babel/helper-environment-visitor": "^7.21.5", + "@babel/helper-member-expression-to-functions": "^7.21.5", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/template": "^7.20.7", - "@babel/traverse": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" } }, "@babel/helper-simple-access": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.20.2.tgz", - "integrity": "sha512-+0woI/WPq59IrqDYbVGfshjT5Dmk/nnbdpcF8SnMhhXObpTq2KNBdLFRFrkVdbDOyUmHBCxzm5FHV1rACIkIbA==", + "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==", + "dev": true, "requires": { - "@babel/types": "^7.20.2" + "@babel/types": "^7.21.5" } }, "@babel/helper-skip-transparent-expression-wrappers": { @@ -22589,9 +22539,9 @@ } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==" + "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==" }, "@babel/helper-validator-identifier": { "version": "7.19.1", @@ -22599,9 +22549,10 @@ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==" }, "@babel/helper-validator-option": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.18.6.tgz", - "integrity": "sha512-XO7gESt5ouv/LRJdrVjkShckw6STTaB7l9BrpBaAHDeF5YZT+01PCwmR0SJHnkW6i8OwW/EVWRShfi4j2x+KQw==" + "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==", + "dev": true }, "@babel/helper-wrap-function": { "version": "7.20.5", @@ -22616,13 +22567,14 @@ } }, "@babel/helpers": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.20.6.tgz", - "integrity": "sha512-Pf/OjgfgFRW5bApskEz5pvidpim7tEDPlFtKcNRXWmfHGn9IEI2W2flqRQXTFb7gIPTyK++N6rVHuwKut4XK6w==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.21.5.tgz", + "integrity": "sha512-BSY+JSlHxOmGsPTydUkPf1MdMQ3M81x5xGCOVgWM3G8XH77sJ292Y2oqcp0CbbgxhqBuI46iUz1tT7hqP7EfgA==", + "dev": true, "requires": { - "@babel/template": "^7.18.10", - "@babel/traverse": "^7.20.5", - "@babel/types": "^7.20.5" + "@babel/template": "^7.20.7", + "@babel/traverse": "^7.21.5", + "@babel/types": "^7.21.5" } }, "@babel/highlight": { @@ -22636,9 +22588,9 @@ } }, "@babel/parser": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.7.tgz", - "integrity": "sha512-T3Z9oHybU+0vZlY9CiDSJQTD5ZapcW18ZctFMi0MOAl/4BjFF4ul7NVSARLdbGO5vDqy9eQiGTV0LtKfvCYvcg==" + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.9.tgz", + "integrity": "sha512-q5PNg/Bi1OpGgx5jYlvWZwAorZepEudDMCLtj967aeS7WMont7dUZI46M2XwcIQqvUlMxWfdLFu4S/qSxeUu5g==" }, "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.18.6", @@ -22683,12 +22635,12 @@ } }, "@babel/plugin-proposal-class-static-block": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.20.7.tgz", - "integrity": "sha512-AveGOoi9DAjUYYuUAG//Ig69GlazLnoyzMw68VCDux+c1tsnnH/OkYcpz/5xzMkEFC6UxjR5Gw1c+iY2wOGVeQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.21.0.tgz", + "integrity": "sha512-XP5G9MWNUskFuP30IfFSEFB0Z6HzLIUcjYM4bYOPHXl7eiJ9HFv8tWj6TXTN5QODiEhDZAeI4hLok2iHFFV4hw==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-class-static-block": "^7.14.5" } @@ -22777,9 +22729,9 @@ } }, "@babel/plugin-proposal-optional-chaining": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.20.7.tgz", - "integrity": "sha512-T+A7b1kfjtRM51ssoOfS1+wbyCVqorfyZhT99TvxxLMirPShD8CzKMRepMlCBGM5RpHMbn8s+5MMHnPstJH6mQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.20.2", @@ -22798,13 +22750,13 @@ } }, "@babel/plugin-proposal-private-property-in-object": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.20.5.tgz", - "integrity": "sha512-Vq7b9dUA12ByzB4EjQTPo25sFhY+08pQDBSZRtUAkj7lb7jahaHR5igera16QZ+3my1nYR4dKsNdYj5IjPHilQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz", + "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-create-class-features-plugin": "^7.20.5", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-private-property-in-object": "^7.14.5" } @@ -22828,6 +22780,15 @@ "@babel/helper-plugin-utils": "^7.8.0" } }, + "@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, "@babel/plugin-syntax-class-properties": { "version": "7.12.13", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", @@ -22865,12 +22826,12 @@ } }, "@babel/plugin-syntax-flow": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.18.6.tgz", - "integrity": "sha512-LUbR+KNTBWCUAqRG9ex5Gnzu2IOkt8jRJbHHXFT9q+L9zm7M/QQbEqXyw1n1pohYvOyWC8CjeyjrSaIwiYjK7A==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.21.4.tgz", + "integrity": "sha512-l9xd3N+XG4fZRxEP3vXdK6RW7vN1Uf5dxzRC/09wV86wqZ/YYQooBIGNsiRdfNR3/q2/5pPzV4B54J/9ctX5jw==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-syntax-import-assertions": { @@ -22882,6 +22843,15 @@ "@babel/helper-plugin-utils": "^7.19.0" } }, + "@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, "@babel/plugin-syntax-json-strings": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", @@ -22892,11 +22862,12 @@ } }, "@babel/plugin-syntax-jsx": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.18.6.tgz", - "integrity": "sha512-6mmljtAedFGTWu2p/8WIORGwy+61PLgOMPOdazc7YoJ9ZCWUyFy3A6CpPkRKLKD1ToAesxX8KGEViAiLo9N+7Q==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.21.4.tgz", + "integrity": "sha512-5hewiLct5OKyh6PLKEYaFclcqtIgCb6bmELouxjF6up5q3Sov7rOayW4RwhbaBL0dit8rA80GNfY+UuDp2mBbQ==", + "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-syntax-logical-assignment-operators": { @@ -22972,23 +22943,23 @@ } }, "@babel/plugin-syntax-typescript": { - "version": "7.20.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.20.0.tgz", - "integrity": "sha512-rd9TkG+u1CExzS4SM1BlMEhMXwFLKVjOAFFCDx9PbX5ycJWDoWMcwdJH9RhkPu1dOgn5TrxLot/Gx6lWFuAUNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.19.0" - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.20.7.tgz", - "integrity": "sha512-3poA5E7dzDomxj9WXWwuD6A5F3kc7VXwIJO+E+J8qtDtS+pXPAhrgEyh+9GBwBgPq1Z+bB+/JD60lp5jsN7JPQ==", + "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==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.20.2" } }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.21.5.tgz", + "integrity": "sha512-wb1mhwGOCaXHDTcsRYMKF9e5bbMgqwxtqa2Y1ifH96dXJPwbuLX9qHy3clhrxVqgMz7nyNXs8VkxdH8UBcjKqA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.21.5" + } + }, "@babel/plugin-transform-async-to-generator": { "version": "7.20.7", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.20.7.tgz", @@ -23010,24 +22981,24 @@ } }, "@babel/plugin-transform-block-scoping": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.20.11.tgz", - "integrity": "sha512-tA4N427a7fjf1P0/2I4ScsHGc5jcHPbb30xMbaTke2gxDuWpUfXDuX1FEymJwKk4tuGUvGcejAR6HdZVqmmPyw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.21.0.tgz", + "integrity": "sha512-Mdrbunoh9SxwFZapeHVrwFmri16+oYotcZysSzhNIVDwIAb1UV+kvnxULSYq9J3/q5MDG+4X6w8QVgD1zhBXNQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.20.2" } }, "@babel/plugin-transform-classes": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.20.7.tgz", - "integrity": "sha512-LWYbsiXTPKl+oBlXUGlwNlJZetXD5Am+CyBdqhPsDVjM9Jc8jwBJFrKhHf900Kfk2eZG1y9MAG3UNajol7A4VQ==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.21.0.tgz", + "integrity": "sha512-RZhbYTCEUAe6ntPehC4hlslPWosNHDox+vAs4On/mCLRLfoDVHf6hVEd7kuxr1RnHwJmxFfUM3cZiZRmPxJPXQ==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", "@babel/helper-compilation-targets": "^7.20.7", "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/helper-function-name": "^7.21.0", "@babel/helper-optimise-call-expression": "^7.18.6", "@babel/helper-plugin-utils": "^7.20.2", "@babel/helper-replace-supers": "^7.20.7", @@ -23036,19 +23007,19 @@ } }, "@babel/plugin-transform-computed-properties": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.20.7.tgz", - "integrity": "sha512-Lz7MvBK6DTjElHAmfu6bfANzKcxpyNPeYBGEafyA6E5HtRpjpZwU+u7Qrgz/2OR0z+5TvKYbPdphfSaAcZBrYQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.21.5.tgz", + "integrity": "sha512-TR653Ki3pAwxBxUe8srfF3e4Pe3FTA46uaNHYyQwIoM4oWKSoOZiDNyHJ0oIoDIUPSRQbQG7jzgVBX3FPVne1Q==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "@babel/template": "^7.20.7" } }, "@babel/plugin-transform-destructuring": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.20.7.tgz", - "integrity": "sha512-Xwg403sRrZb81IVB79ZPqNQME23yhugYVqgTxAhT99h485F4f+GMELFhhOsscDUB7HCswepKeCKLn/GZvUKoBA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.21.3.tgz", + "integrity": "sha512-bp6hwMFzuiE4HqYEyoGJ/V2LeIWn+hLVKc4pnj++E5XQptwhtcGmSayM029d/j2X1bPKGTlsyPwAubuU22KhMA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.20.2" @@ -23084,22 +23055,22 @@ } }, "@babel/plugin-transform-flow-strip-types": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.19.0.tgz", - "integrity": "sha512-sgeMlNaQVbCSpgLSKP4ZZKfsJVnFnNQlUSk6gPYzR/q7tzCgQF2t8RBKAP6cKJeZdveei7Q7Jm527xepI8lNLg==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.21.0.tgz", + "integrity": "sha512-FlFA2Mj87a6sDkW4gfGrQQqwY/dLlBAyJa2dJEZ+FHXUVHBflO2wyKvg+OOEzXfrKYIa4HWl0mgmbCzt0cMb7w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.19.0", + "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-flow": "^7.18.6" } }, "@babel/plugin-transform-for-of": { - "version": "7.18.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.18.8.tgz", - "integrity": "sha512-yEfTRnjuskWYo0k1mHUqrVWaZwrdq8AYbfrpqULOJOaucGSp4mNMVps+YtA8byoevxS/urwU75vyhQIxcCgiBQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.21.5.tgz", + "integrity": "sha512-nYWpjKW/7j/I/mZkGVgHJXh4bA1sfdFnJoOXwJuj4m3Q2EraO/8ZyrkCau9P5tbHQk01RMSt6KYLCsW7730SXQ==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6" + "@babel/helper-plugin-utils": "^7.21.5" } }, "@babel/plugin-transform-function-name": { @@ -23142,14 +23113,14 @@ } }, "@babel/plugin-transform-modules-commonjs": { - "version": "7.20.11", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.20.11.tgz", - "integrity": "sha512-S8e1f7WQ7cimJQ51JkAaDrEtohVEitXjgCGAS2N8S31Y42E+kWwfSz83LYz57QdBm7q9diARVqanIaH2oVgQnw==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.21.5.tgz", + "integrity": "sha512-OVryBEgKUbtqMoB7eG2rs6UFexJi6Zj6FDXx+esBLPTCxCNxAY9o+8Di7IsUGJ+AVhp5ncK0fxWUBd0/1gPhrQ==", "dev": true, "requires": { - "@babel/helper-module-transforms": "^7.20.11", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-simple-access": "^7.20.2" + "@babel/helper-module-transforms": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-simple-access": "^7.21.5" } }, "@babel/plugin-transform-modules-systemjs": { @@ -23204,9 +23175,9 @@ } }, "@babel/plugin-transform-parameters": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.20.7.tgz", - "integrity": "sha512-WiWBIkeHKVOSYPO0pWkxGPfKeWrCJyD3NJ53+Lrp/QMSZbsVPovrVl2aWZ19D/LTVnaDv5Ap7GJ/B2CTOZdrfA==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.21.3.tgz", + "integrity": "sha512-Wxc+TvppQG9xWFYatvCGPvZ6+SIUxQ2ZdiBP+PHYMIjnPXD+uThCshaz4NZOnODAtBjjcVQQ/3OKs9LW28purQ==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.20.2" @@ -23231,16 +23202,16 @@ } }, "@babel/plugin-transform-react-jsx": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.20.7.tgz", - "integrity": "sha512-Tfq7qqD+tRj3EoDhY00nn2uP2hsRxgYGi5mLQ5TimKav0a9Lrpd4deE+fcLXU8zFYRjlKPHZhpCvfEA6qnBxqQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.21.5.tgz", + "integrity": "sha512-ELdlq61FpoEkHO6gFRpfj0kUgSwQTGoaEU8eMRoS8Dv3v6e7BjEAj5WMtIBRdHUeAioMhKP5HyxNzNnP+heKbA==", "dev": true, "requires": { "@babel/helper-annotate-as-pure": "^7.18.6", - "@babel/helper-module-imports": "^7.18.6", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/plugin-syntax-jsx": "^7.18.6", - "@babel/types": "^7.20.7" + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/types": "^7.21.5" } }, "@babel/plugin-transform-react-jsx-development": { @@ -23263,12 +23234,12 @@ } }, "@babel/plugin-transform-regenerator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.20.5.tgz", - "integrity": "sha512-kW/oO7HPBtntbsahzQ0qSE3tFvkFwnbozz3NWFhLGqH75vLEg+sCGngLlhVkePlCs3Jv0dBBHDzCHxNiFAQKCQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.21.5.tgz", + "integrity": "sha512-ZoYBKDb6LyMi5yCsByQ5jmXsHAQDDYeexT1Szvlmui+lADvfSecr5Dxd/PkrTC3pAD182Fcju1VQkB4oCp9M+w==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-plugin-utils": "^7.21.5", "regenerator-transform": "^0.15.1" } }, @@ -23281,6 +23252,20 @@ "@babel/helper-plugin-utils": "^7.18.6" } }, + "@babel/plugin-transform-runtime": { + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.21.4.tgz", + "integrity": "sha512-1J4dhrw1h1PqnNNpzwxQ2UBymJUF8KuPjAAnlLwZcGhHAIqUigFW7cdK6GHoB64ubY4qXQNYknoUeks4Wz7CUA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.21.4", + "@babel/helper-plugin-utils": "^7.20.2", + "babel-plugin-polyfill-corejs2": "^0.3.3", + "babel-plugin-polyfill-corejs3": "^0.6.0", + "babel-plugin-polyfill-regenerator": "^0.4.1", + "semver": "^6.3.0" + } + }, "@babel/plugin-transform-shorthand-properties": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.18.6.tgz", @@ -23328,23 +23313,24 @@ } }, "@babel/plugin-transform-typescript": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.20.7.tgz", - "integrity": "sha512-m3wVKEvf6SoszD8pu4NZz3PvfKRCMgk6D6d0Qi9hNnlM5M6CFS92EgF4EiHVLKbU0r/r7ty1hg7NPZwE7WRbYw==", + "version": "7.21.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.21.3.tgz", + "integrity": "sha512-RQxPz6Iqt8T0uw/WsJNReuBpWpBqs/n7mNo18sKLoTbMp+UrEekhH+pKSVC7gWz+DNjo9gryfV8YzCiT45RgMw==", "dev": true, "requires": { - "@babel/helper-create-class-features-plugin": "^7.20.7", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", "@babel/helper-plugin-utils": "^7.20.2", "@babel/plugin-syntax-typescript": "^7.20.0" } }, "@babel/plugin-transform-unicode-escapes": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.18.10.tgz", - "integrity": "sha512-kKAdAI+YzPgGY/ftStBFXTI1LZFju38rYThnfMykS+IXy8BVx+res7s2fxf1l8I35DV2T97ezo6+SGrXz6B3iQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.21.5.tgz", + "integrity": "sha512-LYm/gTOwZqsYohlvFUe/8Tujz75LqqVC2w+2qPHLR+WyWHGCZPN1KBpJCJn+4Bk4gOkQy/IXKIge6az5MqwlOg==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.9" + "@babel/helper-plugin-utils": "^7.21.5" } }, "@babel/plugin-transform-unicode-regex": { @@ -23358,31 +23344,31 @@ } }, "@babel/preset-env": { - "version": "7.20.2", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.20.2.tgz", - "integrity": "sha512-1G0efQEWR1EHkKvKHqbG+IN/QdgwfByUpM5V5QroDzGV2t3S/WXNQd693cHiHTlCFMpr9B6FkPFXDA2lQcKoDg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.21.5.tgz", + "integrity": "sha512-wH00QnTTldTbf/IefEVyChtRdw5RJvODT/Vb4Vcxq1AZvtXj6T0YeX0cAcXhI6/BdGuiP3GcNIL4OQbI2DVNxg==", "dev": true, "requires": { - "@babel/compat-data": "^7.20.1", - "@babel/helper-compilation-targets": "^7.20.0", - "@babel/helper-plugin-utils": "^7.20.2", - "@babel/helper-validator-option": "^7.18.6", + "@babel/compat-data": "^7.21.5", + "@babel/helper-compilation-targets": "^7.21.5", + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.18.6", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.18.9", - "@babel/plugin-proposal-async-generator-functions": "^7.20.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.20.7", + "@babel/plugin-proposal-async-generator-functions": "^7.20.7", "@babel/plugin-proposal-class-properties": "^7.18.6", - "@babel/plugin-proposal-class-static-block": "^7.18.6", + "@babel/plugin-proposal-class-static-block": "^7.21.0", "@babel/plugin-proposal-dynamic-import": "^7.18.6", "@babel/plugin-proposal-export-namespace-from": "^7.18.9", "@babel/plugin-proposal-json-strings": "^7.18.6", - "@babel/plugin-proposal-logical-assignment-operators": "^7.18.9", + "@babel/plugin-proposal-logical-assignment-operators": "^7.20.7", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.6", "@babel/plugin-proposal-numeric-separator": "^7.18.6", - "@babel/plugin-proposal-object-rest-spread": "^7.20.2", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", "@babel/plugin-proposal-optional-catch-binding": "^7.18.6", - "@babel/plugin-proposal-optional-chaining": "^7.18.9", + "@babel/plugin-proposal-optional-chaining": "^7.21.0", "@babel/plugin-proposal-private-methods": "^7.18.6", - "@babel/plugin-proposal-private-property-in-object": "^7.18.6", + "@babel/plugin-proposal-private-property-in-object": "^7.21.0", "@babel/plugin-proposal-unicode-property-regex": "^7.18.6", "@babel/plugin-syntax-async-generators": "^7.8.4", "@babel/plugin-syntax-class-properties": "^7.12.13", @@ -23390,6 +23376,7 @@ "@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-export-namespace-from": "^7.8.3", "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-syntax-import-meta": "^7.10.4", "@babel/plugin-syntax-json-strings": "^7.8.3", "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", @@ -23399,64 +23386,56 @@ "@babel/plugin-syntax-optional-chaining": "^7.8.3", "@babel/plugin-syntax-private-property-in-object": "^7.14.5", "@babel/plugin-syntax-top-level-await": "^7.14.5", - "@babel/plugin-transform-arrow-functions": "^7.18.6", - "@babel/plugin-transform-async-to-generator": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.21.5", + "@babel/plugin-transform-async-to-generator": "^7.20.7", "@babel/plugin-transform-block-scoped-functions": "^7.18.6", - "@babel/plugin-transform-block-scoping": "^7.20.2", - "@babel/plugin-transform-classes": "^7.20.2", - "@babel/plugin-transform-computed-properties": "^7.18.9", - "@babel/plugin-transform-destructuring": "^7.20.2", + "@babel/plugin-transform-block-scoping": "^7.21.0", + "@babel/plugin-transform-classes": "^7.21.0", + "@babel/plugin-transform-computed-properties": "^7.21.5", + "@babel/plugin-transform-destructuring": "^7.21.3", "@babel/plugin-transform-dotall-regex": "^7.18.6", "@babel/plugin-transform-duplicate-keys": "^7.18.9", "@babel/plugin-transform-exponentiation-operator": "^7.18.6", - "@babel/plugin-transform-for-of": "^7.18.8", + "@babel/plugin-transform-for-of": "^7.21.5", "@babel/plugin-transform-function-name": "^7.18.9", "@babel/plugin-transform-literals": "^7.18.9", "@babel/plugin-transform-member-expression-literals": "^7.18.6", - "@babel/plugin-transform-modules-amd": "^7.19.6", - "@babel/plugin-transform-modules-commonjs": "^7.19.6", - "@babel/plugin-transform-modules-systemjs": "^7.19.6", + "@babel/plugin-transform-modules-amd": "^7.20.11", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", + "@babel/plugin-transform-modules-systemjs": "^7.20.11", "@babel/plugin-transform-modules-umd": "^7.18.6", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.19.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.20.5", "@babel/plugin-transform-new-target": "^7.18.6", "@babel/plugin-transform-object-super": "^7.18.6", - "@babel/plugin-transform-parameters": "^7.20.1", + "@babel/plugin-transform-parameters": "^7.21.3", "@babel/plugin-transform-property-literals": "^7.18.6", - "@babel/plugin-transform-regenerator": "^7.18.6", + "@babel/plugin-transform-regenerator": "^7.21.5", "@babel/plugin-transform-reserved-words": "^7.18.6", "@babel/plugin-transform-shorthand-properties": "^7.18.6", - "@babel/plugin-transform-spread": "^7.19.0", + "@babel/plugin-transform-spread": "^7.20.7", "@babel/plugin-transform-sticky-regex": "^7.18.6", "@babel/plugin-transform-template-literals": "^7.18.9", "@babel/plugin-transform-typeof-symbol": "^7.18.9", - "@babel/plugin-transform-unicode-escapes": "^7.18.10", + "@babel/plugin-transform-unicode-escapes": "^7.21.5", "@babel/plugin-transform-unicode-regex": "^7.18.6", "@babel/preset-modules": "^0.1.5", - "@babel/types": "^7.20.2", + "@babel/types": "^7.21.5", "babel-plugin-polyfill-corejs2": "^0.3.3", "babel-plugin-polyfill-corejs3": "^0.6.0", "babel-plugin-polyfill-regenerator": "^0.4.1", "core-js-compat": "^3.25.1", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "@babel/preset-flow": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.18.6.tgz", - "integrity": "sha512-E7BDhL64W6OUqpuyHnSroLnqyRTcG6ZdOBl1OKI/QK/HJfplqK/S3sq1Cckx7oTodJ5yOXyfw7rEADJ6UjoQDQ==", + "version": "7.21.4", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.21.4.tgz", + "integrity": "sha512-F24cSq4DIBmhq4OzK3dE63NHagb27OPE3eWR+HLekt4Z3Y5MzIIUGF3LlLgV0gN8vzbDViSY7HnrReNVCJXTeA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-flow-strip-types": "^7.18.6" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-transform-flow-strip-types": "^7.21.0" } }, "@babel/preset-modules": { @@ -23487,20 +23466,22 @@ } }, "@babel/preset-typescript": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.18.6.tgz", - "integrity": "sha512-s9ik86kXBAnD760aybBucdpnLsAt0jK1xqJn2juOn9lkOvSHV60os5hxoVJsPzMQxvnUJFAlkont2DvvaYEBtQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.21.5.tgz", + "integrity": "sha512-iqe3sETat5EOrORXiQ6rWfoOg2y68Cs75B9wNxdPW4kixJxh7aXQE1KPdWLDniC24T/6dSnguF33W9j/ZZQcmA==", "dev": true, "requires": { - "@babel/helper-plugin-utils": "^7.18.6", - "@babel/helper-validator-option": "^7.18.6", - "@babel/plugin-transform-typescript": "^7.18.6" + "@babel/helper-plugin-utils": "^7.21.5", + "@babel/helper-validator-option": "^7.21.0", + "@babel/plugin-syntax-jsx": "^7.21.4", + "@babel/plugin-transform-modules-commonjs": "^7.21.5", + "@babel/plugin-transform-typescript": "^7.21.3" } }, "@babel/register": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.18.9.tgz", - "integrity": "sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw==", + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.21.0.tgz", + "integrity": "sha512-9nKsPmYDi5DidAqJaQooxIhsLJiNMkGr8ypQ8Uic7cIox7UCDsM7HuUGxdGT7mSDTYbqzIdsOWzfBton/YJrMw==", "dev": true, "requires": { "clone-deep": "^4.0.1", @@ -23597,62 +23578,53 @@ } } }, + "@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "dev": true + }, "@babel/runtime": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", - "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz", + "integrity": "sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==", "requires": { "regenerator-runtime": "^0.13.11" } }, "@babel/template": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", - "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", + "version": "7.21.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.21.9.tgz", + "integrity": "sha512-MK0X5k8NKOuWRamiEfc3KEJiHMTkGZNUjzMipqCGDDc6ijRl/B7RGSKVGncu4Ro/HdyzzY6cmoXuKI2Gffk7vQ==", "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7" + "@babel/code-frame": "^7.21.4", + "@babel/parser": "^7.21.9", + "@babel/types": "^7.21.5" } }, "@babel/traverse": { - "version": "7.20.12", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.12.tgz", - "integrity": "sha512-MsIbFN0u+raeja38qboyF8TIT7K0BFzz/Yd/77ta4MsUsmP2RAnidIlwq7d5HFQrH/OZJecGV6B71C4zAgpoSQ==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.21.5.tgz", + "integrity": "sha512-AhQoI3YjWi6u/y/ntv7k48mcrCXmus0t79J9qPNlk/lAsFlCiJ047RmbfMOawySTHtywXhbXgpx/8nXMYd+oFw==", "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.7", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", + "@babel/code-frame": "^7.21.4", + "@babel/generator": "^7.21.5", + "@babel/helper-environment-visitor": "^7.21.5", + "@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.20.7", - "@babel/types": "^7.20.7", + "@babel/parser": "^7.21.5", + "@babel/types": "^7.21.5", "debug": "^4.1.0", "globals": "^11.1.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "@babel/types": { - "version": "7.20.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", - "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", + "version": "7.21.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.21.5.tgz", + "integrity": "sha512-m4AfNvVF2mVC/F7fDEdH2El3HzUg9It/XsCxZiOTTA3m3qYfcSVSbTfM6Q9xG+hYDniZssYhlXKKUMD5m8tF4Q==", "requires": { - "@babel/helper-string-parser": "^7.19.4", + "@babel/helper-string-parser": "^7.21.5", "@babel/helper-validator-identifier": "^7.19.1", "to-fast-properties": "^2.0.0" } @@ -23683,124 +23655,101 @@ "dev": true }, "@emotion/babel-plugin": { - "version": "11.10.2", - "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.10.2.tgz", - "integrity": "sha512-xNQ57njWTFVfPAc3cjfuaPdsgLp5QOSuRsj9MA6ndEhH/AzuZM86qIQzt6rq+aGBwj3n5/TkLmU5lhAfdRmogA==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.11.0.tgz", + "integrity": "sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==", "requires": { "@babel/helper-module-imports": "^7.16.7", - "@babel/plugin-syntax-jsx": "^7.17.12", "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/serialize": "^1.1.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/serialize": "^1.1.2", "babel-plugin-macros": "^3.1.0", "convert-source-map": "^1.5.0", "escape-string-regexp": "^4.0.0", "find-root": "^1.1.0", "source-map": "^0.5.7", - "stylis": "4.0.13" - }, - "dependencies": { - "@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - } + "stylis": "4.2.0" } }, "@emotion/cache": { - "version": "11.10.3", - "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.10.3.tgz", - "integrity": "sha512-Psmp/7ovAa8appWh3g51goxu/z3iVms7JXOreq136D8Bbn6dYraPnmL6mdM8GThEx9vwSn92Fz+mGSjBzN8UPQ==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.11.0.tgz", + "integrity": "sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==", "requires": { - "@emotion/memoize": "^0.8.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0", - "@emotion/weak-memoize": "^0.3.0", - "stylis": "4.0.13" - }, - "dependencies": { - "@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - } + "@emotion/memoize": "^0.8.1", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1", + "@emotion/weak-memoize": "^0.3.1", + "stylis": "4.2.0" } }, "@emotion/css": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.10.0.tgz", - "integrity": "sha512-dH9f+kSCucc8ilMg0MUA1AemabcyzYpe5EKX24F528PJjD7HyIY/VBNJHxfUdc8l400h2ncAjR6yEDu+DBj2cg==", + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/css/-/css-11.11.0.tgz", + "integrity": "sha512-m4g6nKzZyiKyJ3WOfdwrBdcujVcpaScIWHAnyNKPm/A/xJKwfXPfQAbEVi1kgexWTDakmg+r2aDj0KvnMTo4oQ==", "requires": { - "@emotion/babel-plugin": "^11.10.0", - "@emotion/cache": "^11.10.0", - "@emotion/serialize": "^1.1.0", - "@emotion/sheet": "^1.2.0", - "@emotion/utils": "^1.2.0" + "@emotion/babel-plugin": "^11.11.0", + "@emotion/cache": "^11.11.0", + "@emotion/serialize": "^1.1.2", + "@emotion/sheet": "^1.2.2", + "@emotion/utils": "^1.2.1" } }, "@emotion/hash": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.0.tgz", - "integrity": "sha512-14FtKiHhy2QoPIzdTcvh//8OyBlknNs2nXRwIhG904opCby3l+9Xaf/wuPvICBF0rc1ZCNBd3nKe9cd2mecVkQ==" + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.1.tgz", + "integrity": "sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==" }, "@emotion/is-prop-valid": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.1.3.tgz", - "integrity": "sha512-RFg04p6C+1uO19uG8N+vqanzKqiM9eeV1LDOG3bmkYmuOj7NbKNlFC/4EZq5gnwAIlcC/jOT24f8Td0iax2SXA==", + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, "requires": { - "@emotion/memoize": "^0.7.4" - } - }, - "@emotion/memoize": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.5.tgz", - "integrity": "sha512-igX9a37DR2ZPGYtV6suZ6whr8pTFtyHL3K/oLUotxpSVO2ASaprmAe2Dkq7tBo7CRY7MMDrAa9nuQP9/YG8FxQ==" - }, - "@emotion/serialize": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.0.tgz", - "integrity": "sha512-F1ZZZW51T/fx+wKbVlwsfchr5q97iW8brAnXmsskz4d0hVB4O3M/SiA3SaeH06x02lSNzkkQv+n3AX3kCXKSFA==", - "requires": { - "@emotion/hash": "^0.9.0", - "@emotion/memoize": "^0.8.0", - "@emotion/unitless": "^0.8.0", - "@emotion/utils": "^1.2.0", - "csstype": "^3.0.2" + "@emotion/memoize": "0.7.4" }, "dependencies": { "@emotion/memoize": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.0.tgz", - "integrity": "sha512-G/YwXTkv7Den9mXDO7AhLWkE3q+I92B+VqAE+dYG4NGPaHZGvt3G8Q0p9vmE+sq7rTGphUbAvmQ9YpbfMQGGlA==" - }, - "@emotion/unitless": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz", - "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==" + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true } } }, - "@emotion/server": { - "version": "11.10.0", - "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.10.0.tgz", - "integrity": "sha512-MTvJ21JPo9aS02GdjFW4nhdwOi2tNNpMmAM/YED0pkxzjDNi5WbiTwXqaCnvLc2Lr8NFtjhT0az1vTJyLIHYcw==", + "@emotion/memoize": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz", + "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==" + }, + "@emotion/serialize": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz", + "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==", "requires": { - "@emotion/utils": "^1.2.0", + "@emotion/hash": "^0.9.1", + "@emotion/memoize": "^0.8.1", + "@emotion/unitless": "^0.8.1", + "@emotion/utils": "^1.2.1", + "csstype": "^3.0.2" + } + }, + "@emotion/server": { + "version": "11.11.0", + "resolved": "https://registry.npmjs.org/@emotion/server/-/server-11.11.0.tgz", + "integrity": "sha512-6q89fj2z8VBTx9w93kJ5n51hsmtYuFPtZgnc1L8VzRx9ti4EU6EyvF6Nn1H1x3vcCQCF7u2dB2lY4AYJwUW4PA==", + "requires": { + "@emotion/utils": "^1.2.1", "html-tokenize": "^2.0.0", "multipipe": "^1.0.2", "through": "^2.3.8" } }, "@emotion/sheet": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.0.tgz", - "integrity": "sha512-OiTkRgpxescko+M51tZsMq7Puu/KP55wMT8BgpcXVG2hqXc0Vo0mfymJ/Uj24Hp0i083ji/o0aLddh08UEjq8w==" + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.2.2.tgz", + "integrity": "sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==" }, "@emotion/stylis": { "version": "0.8.5", @@ -23808,43 +23757,205 @@ "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" }, "@emotion/unitless": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", - "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==" }, "@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.0.tgz", - "integrity": "sha512-1eEgUGmkaljiBnRMTdksDV1W4kUnmwgp7X9G8B++9GYwl1lUdqSndSriIrTJ0N7LQaoauY9JJ2yhiOYK5+NI4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz", + "integrity": "sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==", "dev": true, "requires": {} }, "@emotion/utils": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.0.tgz", - "integrity": "sha512-sn3WH53Kzpw8oQ5mgMmIzzyAaH2ZqFEbozVVBSYp538E06OSE6ytOp7pRAjNQR+Q/orwqdQYJSe2m3hCOeznkw==" + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.2.1.tgz", + "integrity": "sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==" }, "@emotion/weak-memoize": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.0.tgz", - "integrity": "sha512-AHPmaAx+RYfZz0eYu6Gviiagpmiyw98ySSlQvCUhVGDRtDFe4DBS0x1bSjdF3gqUDYOczB+yYvBTtEylYSdRhg==" + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz", + "integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==" }, - "@esbuild/darwin-arm64": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.16.17.tgz", - "integrity": "sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==", + "@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", "dev": true, "optional": true }, + "@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.5.1.tgz", + "integrity": "sha512-Z5ba73P98O1KUYCCJTUeVpja9RcGoMdncZ6T49FCUl2lN38JtCJ+3WgIDBv0AuY4WChU5PmtJmOCTlN6FZTFKQ==", + "dev": true + }, "@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.4.0", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -23859,19 +23970,10 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, "globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -23886,14 +23988,20 @@ "argparse": "^2.0.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true } } }, + "@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==", + "dev": true + }, "@fal-works/esbuild-plugin-global-externals": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz", @@ -23928,62 +24036,62 @@ "integrity": "sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==" }, "@fortawesome/fontawesome-common-types": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.1.2.tgz", - "integrity": "sha512-wBaAPGz1Awxg05e0PBRkDRuTsy4B3dpBm+zreTTyd9TH4uUM27cAL4xWyWR0rLJCrRwzVsQ4hF3FvM6rqydKPA==" + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", + "integrity": "sha512-HNii132xfomg5QVZw0HwXXpN22s7VBHQBv9CeOu9tfJnhsWQNd2lmTNi8CSrnw5B+5YOmzu1UoPAyxaXsJ6RgQ==" }, "@fortawesome/fontawesome-svg-core": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.1.2.tgz", - "integrity": "sha512-853G/Htp0BOdXnPoeCPTjFrVwyrJHpe8MhjB/DYE9XjwhnNDfuBCd3aKc2YUYbEfHEcBws4UAA0kA9dymZKGjA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.4.0.tgz", + "integrity": "sha512-Bertv8xOiVELz5raB2FlXDPKt+m94MQ3JgDfsVbrqNpLU9+UE2E18GKjLKw+d3XbeYPqg1pzyQKGsrzbw+pPaw==", "requires": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" } }, "@fortawesome/free-brands-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.1.2.tgz", - "integrity": "sha512-b2eMfXQBsSxh52pcPtYchURQs6BWNh3zVTG8XH8Lv6V4kDhEg7D0kHN+K1SZniDiPb/e5tBlaygsinMUvetITA==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.4.0.tgz", + "integrity": "sha512-qvxTCo0FQ5k2N+VCXb/PZQ+QMhqRVM4OORiO6MXdG6bKolIojGU/srQ1ptvKk0JTbRgaJOfL2qMqGvBEZG7Z6g==", "requires": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" } }, "@fortawesome/free-regular-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.1.2.tgz", - "integrity": "sha512-xR4hA+tAwsaTHGfb+25H1gVU/aJ0Rzu+xIUfnyrhaL13yNQ7TWiI2RvzniAaB+VGHDU2a+Pk96Ve+pkN3/+TTQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-6.4.0.tgz", + "integrity": "sha512-ZfycI7D0KWPZtf7wtMFnQxs8qjBXArRzczABuMQqecA/nXohquJ5J/RCR77PmY5qGWkxAZDxpnUFVXKwtY/jPw==", "requires": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" } }, "@fortawesome/free-solid-svg-icons": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.1.2.tgz", - "integrity": "sha512-lTgZz+cMpzjkHmCwOG3E1ilUZrnINYdqMmrkv30EC3XbRsGlbIOL8H9LaNp5SV4g0pNJDfQ4EdTWWaMvdwyLiQ==", + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.4.0.tgz", + "integrity": "sha512-kutPeRGWm8V5dltFP1zGjQOEAzaLZj4StdQhWVZnfGFCvAPVvHh8qk5bRrU4KXnRRRNni5tKQI9PBAdI6MP8nQ==", "requires": { - "@fortawesome/fontawesome-common-types": "6.1.2" + "@fortawesome/fontawesome-common-types": "6.4.0" } }, "@fortawesome/react-fontawesome": { - "version": "0.1.19", - "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.1.19.tgz", - "integrity": "sha512-Hyb+lB8T18cvLNX0S3llz7PcSOAJMLwiVKBuuzwM/nI5uoBw+gQjnf9il0fR1C3DKOI5Kc79pkJ4/xB0Uw9aFQ==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@fortawesome/react-fontawesome/-/react-fontawesome-0.2.0.tgz", + "integrity": "sha512-uHg75Rb/XORTtVt7OS9WoK8uM276Ufi7gCzshVWkUJbHhh3svsUUeqXerrM96Wm7fRiDzfKRwSoahhMIkGAYHw==", "requires": { "prop-types": "^15.8.1" } }, "@headlessui/react": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.7.tgz", - "integrity": "sha512-BqDOd/tB9u2tA0T3Z0fn18ktw+KbVwMnkxxsGPIH2hzssrQhKB5n/6StZOyvLYP/FsYtvuXfi9I0YowKPv2c1w==", + "version": "1.7.14", + "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.14.tgz", + "integrity": "sha512-znzdq9PG8rkwcu9oQ2FwIy0ZFtP9Z7ycS+BAqJ3R5EIqC/0bJGvhT7193rFf+45i9nnPsYvCQVW4V/bB9Xc+gA==", "requires": { "client-only": "^0.0.1" } }, "@hookform/resolvers": { - "version": "2.9.10", - "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.9.10.tgz", - "integrity": "sha512-JIL1DgJIlH9yuxcNGtyhsWX/PgNltz+5Gr6+8SX9fhXc/hPbEIk6wPI82nhgvp3uUb6ZfAM5mqg/x7KR7NAb+A==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.9.11.tgz", + "integrity": "sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ==", "requires": {} }, "@humanwhocodes/config-array": { @@ -23995,23 +24103,6 @@ "@humanwhocodes/object-schema": "^1.2.1", "debug": "^4.1.1", "minimatch": "^3.0.5" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "@humanwhocodes/module-importer": { @@ -24075,12 +24166,6 @@ "requires": { "p-limit": "^2.2.0" } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true } } }, @@ -24091,35 +24176,35 @@ "dev": true }, "@jest/schemas": { - "version": "29.0.0", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz", - "integrity": "sha512-3Ab5HgYIIAnS0HjqJHQYZS+zXc4tUmTmBH3z83ajI6afXp8X3ZtdLX+nXx+I7LNkJD7uN9LAVhgnjDgZa2z0kA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", "dev": true, "requires": { - "@sinclair/typebox": "^0.24.1" + "@sinclair/typebox": "^0.25.16" } }, "@jest/transform": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.3.1.tgz", - "integrity": "sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.5.0.tgz", + "integrity": "sha512-8vbeZWqLJOvHaDfeMuoHITGKSz5qWc9u04lnWrQE3VyuSw604PzQM824ZeX9XSjUCeDiE3GuxZe5UKa8J61NQw==", "dev": true, "requires": { "@babel/core": "^7.11.6", - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@jridgewell/trace-mapping": "^0.3.15", "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.3.1", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", + "jest-haste-map": "^29.5.0", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", "micromatch": "^4.0.4", "pirates": "^4.0.4", "slash": "^3.0.0", - "write-file-atomic": "^4.0.1" + "write-file-atomic": "^4.0.2" }, "dependencies": { "ansi-styles": { @@ -24165,12 +24250,12 @@ } }, "@jest/types": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.3.1.tgz", - "integrity": "sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.5.0.tgz", + "integrity": "sha512-qbu7kN6czmVRc3xWFQcAN03RAUamgppVUdXrvl1Wr3jlNF93o9mJbGcDWrwGB6ht44u7efB1qCFgVQmca24Uog==", "dev": true, "requires": { - "@jest/schemas": "^29.0.0", + "@jest/schemas": "^29.4.3", "@types/istanbul-lib-coverage": "^2.0.0", "@types/istanbul-reports": "^3.0.0", "@types/node": "*", @@ -24215,9 +24300,9 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "requires": { "@jridgewell/set-array": "^1.0.1", "@jridgewell/sourcemap-codec": "^1.4.10", @@ -24235,9 +24320,9 @@ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==" }, "@jridgewell/source-map": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", - "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.3.tgz", + "integrity": "sha512-b+fsZXeLYi9fEULmfBrhxn4IrPlINf8fiNarzTof004v3lFdntdwa9PF7vFJqm3mg7s+ScJMxXaE3Acp1irZcg==", "dev": true, "requires": { "@jridgewell/gen-mapping": "^0.3.0", @@ -24245,48 +24330,152 @@ } }, "@jridgewell/sourcemap-codec": { - "version": "1.4.14", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", - "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "@jridgewell/trace-mapping": { - "version": "0.3.17", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", - "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", + "version": "0.3.18", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz", + "integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==", "requires": { "@jridgewell/resolve-uri": "3.1.0", "@jridgewell/sourcemap-codec": "1.4.14" + }, + "dependencies": { + "@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", + "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" + } } }, + "@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "dev": true + }, "@mdx-js/react": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.2.1.tgz", - "integrity": "sha512-YdXcMcEnqZhzql98RNrqYo9cEhTTesBiCclEtoiQUbJwx87q9453GTapYU6kJ8ZZ2ek1Vp25SiAXEFy5O/eAPw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-2.3.0.tgz", + "integrity": "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g==", "dev": true, "requires": { "@types/mdx": "^2.0.0", "@types/react": ">=16" } }, + "@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "requires": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "requires": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "requires": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "requires": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "requires": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "@ndelangen/get-tarball": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/@ndelangen/get-tarball/-/get-tarball-3.0.7.tgz", + "integrity": "sha512-NqGfTZIZpRFef1GoVaShSSRwDC3vde3ThtTeqFdcYd6ipKqnfEVhjK2hUeHjCQUcptyZr2TONqcloFXM+5QBrQ==", + "dev": true, + "requires": { + "gunzip-maybe": "^1.4.2", + "pump": "^3.0.0", + "tar-fs": "^2.1.1" + } + }, "@next/env": { "version": "12.3.4", "resolved": "https://registry.npmjs.org/@next/env/-/env-12.3.4.tgz", "integrity": "sha512-H/69Lc5Q02dq3o+dxxy5O/oNxFsZpdL6WREtOOtOM1B/weonIwDXkekr1KV5DPVPr12IHFPrMrcJQ6bgPMfn7A==" }, "@next/eslint-plugin-next": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.0.5.tgz", - "integrity": "sha512-H9U9B1dFnCDmylDZ6/dYt95Ie1Iu+SLBMcO6rkIGIDcj5UK+DNyMiWm83xWBZ1gREM8cfp5Srv1g6wqf8pM4lw==", + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-13.4.3.tgz", + "integrity": "sha512-5B0uOnh7wyUY9vNNdIA6NUvWozhrZaTMZOzdirYAefqD0ZBK5C/h3+KMYdCKrR7JrXGvVpWnHtv54b3dCzwICA==", "dev": true, "requires": { "glob": "7.1.7" + }, + "dependencies": { + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + } } }, - "@next/font": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/@next/font/-/font-13.1.2.tgz", - "integrity": "sha512-NXGXGFGiOKEnvBIHq9cdFTKbHO2/4B3Zd9K27M7j1DioIQVar7oVRqZMYs0h3XMVEZLwjjkdAtqRPCzzd3RtXg==", - "dev": true + "@next/swc-android-arm-eabi": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.3.4.tgz", + "integrity": "sha512-cM42Cw6V4Bz/2+j/xIzO8nK/Q3Ly+VSlZJTa1vHzsocJRYz8KT6MrreXaci2++SIZCF1rVRCDgAg5PpqRibdIA==", + "optional": true + }, + "@next/swc-android-arm64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-android-arm64/-/swc-android-arm64-12.3.4.tgz", + "integrity": "sha512-5jf0dTBjL+rabWjGj3eghpLUxCukRhBcEJgwLedewEA/LJk2HyqCvGIwj5rH+iwmq1llCWbOky2dO3pVljrapg==", + "optional": true }, "@next/swc-darwin-arm64": { "version": "12.3.4", @@ -24294,6 +24483,66 @@ "integrity": "sha512-DqsSTd3FRjQUR6ao0E1e2OlOcrF5br+uegcEGPVonKYJpcr0MJrtYmPxd4v5T6UCJZ+XzydF7eQo5wdGvSZAyA==", "optional": true }, + "@next/swc-darwin-x64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-12.3.4.tgz", + "integrity": "sha512-PPF7tbWD4k0dJ2EcUSnOsaOJ5rhT3rlEt/3LhZUGiYNL8KvoqczFrETlUx0cUYaXe11dRA3F80Hpt727QIwByQ==", + "optional": true + }, + "@next/swc-freebsd-x64": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.3.4.tgz", + "integrity": "sha512-KM9JXRXi/U2PUM928z7l4tnfQ9u8bTco/jb939pdFUHqc28V43Ohd31MmZD1QzEK4aFlMRaIBQOWQZh4D/E5lQ==", + "optional": true + }, + "@next/swc-linux-arm-gnueabihf": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.3.4.tgz", + "integrity": "sha512-3zqD3pO+z5CZyxtKDTnOJ2XgFFRUBciOox6EWkoZvJfc9zcidNAQxuwonUeNts6Xbm8Wtm5YGIRC0x+12YH7kw==", + "optional": true + }, + "@next/swc-linux-arm64-gnu": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.3.4.tgz", + "integrity": "sha512-kiX0vgJGMZVv+oo1QuObaYulXNvdH/IINmvdZnVzMO/jic/B8EEIGlZ8Bgvw8LCjH3zNVPO3mGrdMvnEEPEhKA==", + "optional": true + }, + "@next/swc-linux-arm64-musl": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.3.4.tgz", + "integrity": "sha512-EETZPa1juczrKLWk5okoW2hv7D7WvonU+Cf2CgsSoxgsYbUCZ1voOpL4JZTOb6IbKMDo6ja+SbY0vzXZBUMvkQ==", + "optional": true + }, + "@next/swc-linux-x64-gnu": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.3.4.tgz", + "integrity": "sha512-4csPbRbfZbuWOk3ATyWcvVFdD9/Rsdq5YHKvRuEni68OCLkfy4f+4I9OBpyK1SKJ00Cih16NJbHE+k+ljPPpag==", + "optional": true + }, + "@next/swc-linux-x64-musl": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.3.4.tgz", + "integrity": "sha512-YeBmI+63Ro75SUiL/QXEVXQ19T++58aI/IINOyhpsRL1LKdyfK/35iilraZEFz9bLQrwy1LYAR5lK200A9Gjbg==", + "optional": true + }, + "@next/swc-win32-arm64-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.3.4.tgz", + "integrity": "sha512-Sd0qFUJv8Tj0PukAYbCCDbmXcMkbIuhnTeHm9m4ZGjCf6kt7E/RMs55Pd3R5ePjOkN7dJEuxYBehawTR/aPDSQ==", + "optional": true + }, + "@next/swc-win32-ia32-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.3.4.tgz", + "integrity": "sha512-rt/vv/vg/ZGGkrkKcuJ0LyliRdbskQU+91bje+PgoYmxTZf/tYs6IfbmgudBJk6gH3QnjHWbkphDdRQrseRefQ==", + "optional": true + }, + "@next/swc-win32-x64-msvc": { + "version": "12.3.4", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.3.4.tgz", + "integrity": "sha512-DQ20JEfTBZAgF8QCjYfJhv2/279M6onxFjdG/+5B0Cyj00/EdBxiWb2eGGFgQhrBbNv/lsvzFbbi0Ptf8Vw/bg==", + "optional": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -24329,9 +24578,9 @@ } }, "@octokit/core": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.0.tgz", - "integrity": "sha512-AgvDRUg3COpR82P7PBdGZF/NNqGmtMq2NiPqeSsDIeCfYFOZ9gddqWNQHnFdEUf+YwOj4aZYmJnlPp7OXmDIDg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-4.2.1.tgz", + "integrity": "sha512-tEDxFx8E38zF3gT7sSMDrT1tGumDgsw5yPG6BBh/X+5ClIQfMH/Yqocxz1PnHx6CHyF6pxmovUTOfZAUvQ0Lvw==", "requires": { "@octokit/auth-token": "^3.0.0", "@octokit/graphql": "^5.0.0", @@ -24353,9 +24602,9 @@ } }, "@octokit/graphql": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.5.tgz", - "integrity": "sha512-Qwfvh3xdqKtIznjX9lz2D458r7dJPP8l6r4GQkIdWQouZwHQK0mVT88uwiU2bdTU2OtT1uOlKpRciUWldpG0yQ==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-5.0.6.tgz", + "integrity": "sha512-Fxyxdy/JH0MnIB5h+UQ3yCoh1FG4kWXfFKkpWqjZHw/p+Kc8Y44Hu/kCgNBT6nU1shNumEchmW/sUO1JuQnPcw==", "requires": { "@octokit/request": "^6.0.0", "@octokit/types": "^9.0.0", @@ -24363,16 +24612,17 @@ } }, "@octokit/openapi-types": { - "version": "16.0.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-16.0.0.tgz", - "integrity": "sha512-JbFWOqTJVLHZSUUoF4FzAZKYtqdxWu9Z5m2QQnOyEa04fOFljvyh7D3GYKbfuaSWisqehImiVIMG4eyJeP5VEA==" + "version": "17.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-17.2.0.tgz", + "integrity": "sha512-MazrFNx4plbLsGl+LFesMo96eIXkFgEtaKbnNpdh4aQ0VM10aoylFsTYP1AEjkeoRNZiiPe3T6Gl2Hr8dJWdlQ==" }, "@octokit/plugin-paginate-rest": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.0.0.tgz", - "integrity": "sha512-Sq5VU1PfT6/JyuXPyt04KZNVsFOSBaYOAq2QRZUwzVlI10KFvcbUo8lR258AAQL1Et60b0WuVik+zOWKLuDZxw==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-6.1.2.tgz", + "integrity": "sha512-qhrmtQeHU/IivxucOV1bbI/xZyC/iOBhclokv7Sut5vnejAIAEXVcGQeRpQlU39E0WwK9lNvJHphHri/DB6lbQ==", "requires": { - "@octokit/types": "^9.0.0" + "@octokit/tsconfig": "^1.0.2", + "@octokit/types": "^9.2.3" } }, "@octokit/plugin-request-log": { @@ -24382,18 +24632,18 @@ "requires": {} }, "@octokit/plugin-rest-endpoint-methods": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-7.0.1.tgz", - "integrity": "sha512-pnCaLwZBudK5xCdrR823xHGNgqOzRnJ/mpC/76YPpNP7DybdsJtP7mdOwh+wYZxK5jqeQuhu59ogMI4NRlBUvA==", + "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==", "requires": { - "@octokit/types": "^9.0.0", + "@octokit/types": "^9.2.3", "deprecation": "^2.3.1" } }, "@octokit/request": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.3.tgz", - "integrity": "sha512-TNAodj5yNzrrZ/VxP+H5HiYaZep0H3GU0O7PaF+fhDrt8FPrnkei9Aal/txsN/1P7V3CPiThG0tIvpPDYUsyAA==", + "version": "6.2.5", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-6.2.5.tgz", + "integrity": "sha512-z83E8UIlPNaJUsXpjD8E0V5o/5f+vJJNbNcBwVZsX3/vC650U41cOkTLjq4PKk9BYonQGOnx7N17gvLyNjgGcQ==", "requires": { "@octokit/endpoint": "^7.0.0", "@octokit/request-error": "^3.0.0", @@ -24414,36 +24664,61 @@ } }, "@octokit/rest": { - "version": "19.0.7", - "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.7.tgz", - "integrity": "sha512-HRtSfjrWmWVNp2uAkEpQnuGMJsu/+dBr47dRc5QVgsCbnIc1+GFEaoKBWkYG+zjrsHpSqcAElMio+n10c0b5JA==", + "version": "19.0.11", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-19.0.11.tgz", + "integrity": "sha512-m2a9VhaP5/tUw8FwfnW2ICXlXpLPIqxtg3XcAiGMLj/Xhw3RSBfZ8le/466ktO1Gcjr8oXudGnHhxV1TXJgFxw==", "requires": { - "@octokit/core": "^4.1.0", - "@octokit/plugin-paginate-rest": "^6.0.0", + "@octokit/core": "^4.2.1", + "@octokit/plugin-paginate-rest": "^6.1.2", "@octokit/plugin-request-log": "^1.0.4", - "@octokit/plugin-rest-endpoint-methods": "^7.0.0" + "@octokit/plugin-rest-endpoint-methods": "^7.1.2" } }, + "@octokit/tsconfig": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@octokit/tsconfig/-/tsconfig-1.0.2.tgz", + "integrity": "sha512-I0vDR0rdtP8p2lGMzvsJzbhdOWy405HcGovrspJ8RRibHnyRgggUSNO5AIox5LmqiwmatHKYsvj6VGFHkqS7lA==" + }, "@octokit/types": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.0.0.tgz", - "integrity": "sha512-LUewfj94xCMH2rbD5YJ+6AQ4AVjFYTgpp6rboWM5T7N3IsIF65SBEOVcYMGAEzO/kKNiNaW4LoWtoThOhH06gw==", + "version": "9.2.3", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-9.2.3.tgz", + "integrity": "sha512-MMeLdHyFIALioycq+LFcA71v0S2xpQUX2cw6pPbHQjaibcHYwLnmK/kMZaWuGfGfjBJZ3wRUq+dOaWsvrPJVvA==", "requires": { - "@octokit/openapi-types": "^16.0.0" + "@octokit/openapi-types": "^17.2.0" } }, "@pkgr/utils": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.3.1.tgz", - "integrity": "sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.0.tgz", + "integrity": "sha512-2OCURAmRtdlL8iUDTypMrrxfwe8frXTeXaxGsVOaYtc/wrUyk8Z/0OBetM7cdlsy7ZFWlMX72VogKeh+A4Xcjw==", "dev": true, "requires": { "cross-spawn": "^7.0.3", + "fast-glob": "^3.2.12", "is-glob": "^4.0.3", - "open": "^8.4.0", + "open": "^9.1.0", "picocolors": "^1.0.0", - "tiny-glob": "^0.2.9", - "tslib": "^2.4.0" + "tslib": "^2.5.0" + }, + "dependencies": { + "define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true + }, + "open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "requires": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + } + } } }, "@pmmmwh/react-refresh-webpack-plugin": { @@ -24499,65 +24774,65 @@ } }, "@radix-ui/react-accordion": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.0.tgz", - "integrity": "sha512-CNN9ZBgCK4i4SX7gFk5s8095j55DUWi85vwRNfkfBLs0QdAG5Tb4ku6sBeugCAiLvsmxw481GyNl+C3stoJVBQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-accordion/-/react-accordion-1.1.1.tgz", + "integrity": "sha512-TQtyyRubYe8DD6DYCovNLTjd2D+TFrNCpr99T5M3cYUbR7BsRxWsxfInjbQ1nHsdy2uPTcnJS5npyXPVfP0piw==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collapsible": "1.0.1", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collapsible": "1.0.2", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" } }, "@radix-ui/react-alert-dialog": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.2.tgz", - "integrity": "sha512-0MtxV53FaEEBOKRgyLnEqHZKKDS5BldQ9oUBsKVXWI5FHbl2jp35qs+0aJET+K5hJDsc40kQUzP7g+wC7tqrqA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-alert-dialog/-/react-alert-dialog-1.0.3.tgz", + "integrity": "sha512-QXFy7+bhGi0u+paF2QbJeSCHZs4gLMJIPm6sajUamyW0fro6g1CaSGc5zmc4QmK2NlSGUrq8m+UsUqJYtzvXow==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dialog": "1.0.2", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-dialog": "1.0.3", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1" } }, "@radix-ui/react-arrow": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz", - "integrity": "sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.0.2.tgz", + "integrity": "sha512-fqYwhhI9IarZ0ll2cUSfKuXHlJK0qE4AfnRrPBbRwEH/4mGQn04/QFGomLi8TXWIdv9WJk//KgGm+aDxVIr1wA==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" } }, "@radix-ui/react-checkbox": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.1.tgz", - "integrity": "sha512-TisH0B8hWmYP3ONRduYCyN04rR9yLPIw/Rwyn1RoC1suSoGCa8Wn+YPdSSSarSszeIbcg3p2lBkDp2XXit4sZw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.0.3.tgz", + "integrity": "sha512-55B8/vKzTuzxllH5sGJO4zaBf9gYpJuJRRzaOKm+0oAefRnMvbf+Kgww7IOANVN0w3z7agFJgtnXaZl8Uj95AA==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", "@radix-ui/react-use-size": "1.0.0" } }, "@radix-ui/react-collapsible": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.1.tgz", - "integrity": "sha512-0maX4q91iYa4gjt3PsNf7dq/yqSR+HGAE8I5p54dQ6gnveS+ETWlMoijxrhmgV1k8svxpm34mQAtqIrJt4XZmA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.0.2.tgz", + "integrity": "sha512-QNiDT6Au8jUU0K1WV+HEd4loH7C5CKQjeXxskwqyiyAkyCmW7qlQM5vSSJCIoQC+OVPyhgafSmGudRP8Qm1/gA==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", @@ -24565,20 +24840,20 @@ "@radix-ui/react-context": "1.0.0", "@radix-ui/react-id": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0" } }, "@radix-ui/react-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.1.tgz", - "integrity": "sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.0.2.tgz", + "integrity": "sha512-s8WdQQ6wNXpaxdZ308KSr8fEWGrg4un8i4r/w7fhiS4ElRNjk5rRcl0/C6TANG2LvLOGIxtzo/jAg6Qf73TEBw==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1" } }, @@ -24599,21 +24874,21 @@ } }, "@radix-ui/react-dialog": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.2.tgz", - "integrity": "sha512-EKxxp2WNSmUPkx4trtWNmZ4/vAYEg7JkAfa1HKBUnaubw9eHzf1Orr9B472lJYaYz327RHDrd4R95fsw7VR8DA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.0.3.tgz", + "integrity": "sha512-owNhq36kNPqC2/a+zJRioPg6HHnTn5B/sh/NjTY8r4W9g1L5VJlrzZIVcBr7R9Mg8iLjVmh6MGgMlfoVf/WO/A==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-controllable-state": "1.0.0", "aria-hidden": "^1.1.1", @@ -24629,30 +24904,30 @@ } }, "@radix-ui/react-dismissable-layer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz", - "integrity": "sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.3.tgz", + "integrity": "sha512-nXZOvFjOuHS1ovumntGV7NNoLaEp9JEvTht3MBjP44NSW5hUKj/8OnfN3+8WmB+CEhN44XaGhpHoSsUIEl5P7Q==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-escape-keydown": "1.0.2" } }, "@radix-ui/react-dropdown-menu": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.2.tgz", - "integrity": "sha512-r0kN0fstrSi+uAdK2GkLxnnbhqVBy/9Q4o4PvGOYipW0BldQlYBMSmZprvCNj2i2mAATx16kvzIn12GnaGjbMw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.4.tgz", + "integrity": "sha512-y6AT9+MydyXcByivdK1+QpjWoKaC7MLjkS/cH1Q3keEyMvDkiY85m8o2Bi6+Z1PPUlCsMULopxagQOSfN0wahg==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-menu": "2.0.2", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-menu": "2.0.4", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" } }, @@ -24665,30 +24940,30 @@ } }, "@radix-ui/react-focus-scope": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz", - "integrity": "sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.2.tgz", + "integrity": "sha512-spwXlNTfeIprt+kaEWE/qYuYT3ZAqJiAGjN/JgdvgVDTu8yc+HuX+WOWXrKliKnLnwck0F6JDkqIERncnih+4A==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-compose-refs": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0" } }, "@radix-ui/react-hover-card": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.3.tgz", - "integrity": "sha512-rr2+DxPlMhR57IPcNvZ85X8chytdfj7kyVToyR5Ge0r4IJEFiyPs0Cs8/K8oe5zt+yo0F8f29vtC8tNNK+ZIkA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.0.5.tgz", + "integrity": "sha512-jXRuZEkxSWdHZbVyL0J46cm7pQjmOMpwJEFKY+VqAJnV+FxS+zIZExI1OCeIiDwCBzUy6If1FfouOsfqBxr86g==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0" } }, @@ -24702,34 +24977,34 @@ } }, "@radix-ui/react-label": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.0.tgz", - "integrity": "sha512-7qCcZ3j2VQspWjy+gKR4W+V/z0XueQjeiZnlPOtsyiP9HaS8bfSU7ECoI3bvvdYntQj7NElW7OAYsYRW4MQvCg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.1.tgz", + "integrity": "sha512-qcfbS3B8hTYmEO44RNcXB6pegkxRsJIbdxTMu0PEX0Luv5O2DvTIwwVYxQfUwLpM88EL84QRPLOLgwUSApMsLQ==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" } }, "@radix-ui/react-menu": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.2.tgz", - "integrity": "sha512-H5dtBi/k3tc45IMd2Pu+Q2PyONFlsYJ5sWUlflSs8BQRghh5GhJHLRuB1yb88VOywuzzvGkaR/HUJJ65Jf2POA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.0.4.tgz", + "integrity": "sha512-mzKR47tZ1t193trEqlQoJvzY4u9vYfVH16ryBrVrCAGZzkgyWnMQYEZdUkM7y8ak9mrkKtJiqB47TlEnubeOFQ==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", - "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-roving-focus": "1.0.3", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "aria-hidden": "^1.1.1", @@ -24737,22 +25012,22 @@ } }, "@radix-ui/react-popover": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.3.tgz", - "integrity": "sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.0.5.tgz", + "integrity": "sha512-GRHZ8yD12MrN2NLobHPE8Rb5uHTxd9x372DE9PPNnBjpczAQHcZ5ne0KXG4xpf+RDdXSzdLv9ym6mYJCDTaUZg==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-controllable-state": "1.0.0", "aria-hidden": "^1.1.1", @@ -24760,16 +25035,16 @@ } }, "@radix-ui/react-popper": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.0.tgz", - "integrity": "sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.1.tgz", + "integrity": "sha512-keYDcdMPNMjSC8zTsZ8wezUMiWM9Yj14wtF3s0PTIs9srnEPC9Kt2Gny1T3T81mmSeyDjZxsD9N5WCwNNb712w==", "requires": { "@babel/runtime": "^7.13.10", "@floating-ui/react-dom": "0.7.2", - "@radix-ui/react-arrow": "1.0.1", + "@radix-ui/react-arrow": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", "@radix-ui/react-use-rect": "1.0.0", @@ -24778,12 +25053,12 @@ } }, "@radix-ui/react-portal": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.1.tgz", - "integrity": "sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.0.2.tgz", + "integrity": "sha512-swu32idoCW7KA2VEiUZGBSu9nB6qwGdV6k6HYhUoOo3M1FFpD+VgLzUqtt3mwL1ssz7r2x8MggpLSQach2Xy/Q==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" } }, "@radix-ui/react-presence": { @@ -24797,66 +25072,66 @@ } }, "@radix-ui/react-primitive": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz", - "integrity": "sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-1.0.2.tgz", + "integrity": "sha512-zY6G5Qq4R8diFPNwtyoLRZBxzu1Z+SXMlfYpChN7Dv8gvmx9X3qhDqiLWvKseKVJMuedFeU/Sa0Sy/Ia+t06Dw==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-slot": "1.0.1" } }, "@radix-ui/react-progress": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.0.1.tgz", - "integrity": "sha512-QbDf9eguM5QtkvGcGHe/nUgloM9yfRGpJTB/Te5cn4WmVHvcbhHyHw39/rbCZxNX4E+GEPp5Vs6+mEoyIotUbg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.0.2.tgz", + "integrity": "sha512-c16RVM43ct2koRcMmPw4b47JWFNs89qe5p4Um9dwoPs0yi+d7It1MJ35EpsX+93o31Mqdwe4vQyu0SrHrygdCg==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" } }, "@radix-ui/react-roving-focus": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz", - "integrity": "sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.3.tgz", + "integrity": "sha512-stjCkIoMe6h+1fWtXlA6cRfikdBzCLp3SnVk7c48cv/uy3DTGoXhN76YaOYUJuy3aEDvDIKwKR5KSmvrtPvQPQ==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0" } }, "@radix-ui/react-select": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.0.tgz", - "integrity": "sha512-MmXKsIBrG9GKxt8JKIn75LEPiX/zejBmj/Z36Hxtm9cdmCFzTo78QJ0Q3buLGzr0c3lzXdfgeKntmgCzaGxgkw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-select/-/react-select-1.2.1.tgz", + "integrity": "sha512-GULRMITaOHNj79BZvQs3iZO0+f2IgI8g5HDhMi7Bnc13t7IlG86NFtOCfTLme4PNZdEtU+no+oGgcl6IFiphpQ==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/number": "1.0.0", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", "@radix-ui/react-direction": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", + "@radix-ui/react-dismissable-layer": "1.0.3", "@radix-ui/react-focus-guards": "1.0.0", - "@radix-ui/react-focus-scope": "1.0.1", + "@radix-ui/react-focus-scope": "1.0.2", "@radix-ui/react-id": "1.0.0", - "@radix-ui/react-popper": "1.1.0", - "@radix-ui/react-portal": "1.0.1", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-slot": "1.0.1", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", - "@radix-ui/react-visually-hidden": "1.0.1", + "@radix-ui/react-visually-hidden": "1.0.2", "aria-hidden": "^1.1.1", "react-remove-scroll": "2.5.5" } @@ -24871,24 +25146,24 @@ } }, "@radix-ui/react-switch": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.1.tgz", - "integrity": "sha512-tTxGluMtwrc5ffgAiOSMrYIx0r3vSTcgM4Vl8rqfpXcHt6ryB9B0OlFKUOiDpKASXlhvzfHf4Y0AYKJdpzjL8w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.2.tgz", + "integrity": "sha512-BcG/LKehxt36NXG0wPnoCitIfSMtU9Xo7BmythYA1PAMLtsMvW7kALfBzmduQoHTWcKr0AVcFyh0gChBUp9TiQ==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-previous": "1.0.0", "@radix-ui/react-use-size": "1.0.0" } }, "@radix-ui/react-tabs": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz", - "integrity": "sha512-gOUwh+HbjCuL0UCo8kZ+kdUEG8QtpdO4sMQduJ34ZEz0r4922g9REOBM+vIsfwtGxSug4Yb1msJMJYN2Bk8TpQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tabs/-/react-tabs-1.0.3.tgz", + "integrity": "sha512-4CkF/Rx1GcrusI/JZ1Rvyx4okGUs6wEenWA0RG/N+CwkRhTy7t54y7BLsWUXrAz/GRbBfHQg/Odfs/RoW0CiRA==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", @@ -24896,29 +25171,49 @@ "@radix-ui/react-direction": "1.0.0", "@radix-ui/react-id": "1.0.0", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", - "@radix-ui/react-roving-focus": "1.0.2", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-roving-focus": "1.0.3", "@radix-ui/react-use-controllable-state": "1.0.0" } }, "@radix-ui/react-toast": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.2.tgz", - "integrity": "sha512-Kpr4BBYoP0O5A1UeDBmao87UnCMNdAKGNioQH5JzEm6OYTUVGhuDRbOwoZxPwOZ6vsjJHeIpdUrwbiHEB65CCw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toast/-/react-toast-1.1.3.tgz", + "integrity": "sha512-yHFgpxi9wjbfPvpSPdYAzivCqw48eA1ofT8m/WqYOVTxKPdmQMuVKRYPlMmj4C1d6tJdFj/LBa1J4iY3fL4OwQ==", "requires": { "@babel/runtime": "^7.13.10", "@radix-ui/primitive": "1.0.0", - "@radix-ui/react-collection": "1.0.1", + "@radix-ui/react-collection": "1.0.2", "@radix-ui/react-compose-refs": "1.0.0", "@radix-ui/react-context": "1.0.0", - "@radix-ui/react-dismissable-layer": "1.0.2", - "@radix-ui/react-portal": "1.0.1", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-portal": "1.0.2", "@radix-ui/react-presence": "1.0.0", - "@radix-ui/react-primitive": "1.0.1", + "@radix-ui/react-primitive": "1.0.2", "@radix-ui/react-use-callback-ref": "1.0.0", "@radix-ui/react-use-controllable-state": "1.0.0", "@radix-ui/react-use-layout-effect": "1.0.0", - "@radix-ui/react-visually-hidden": "1.0.1" + "@radix-ui/react-visually-hidden": "1.0.2" + } + }, + "@radix-ui/react-tooltip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.0.5.tgz", + "integrity": "sha512-cDKVcfzyO6PpckZekODJZDe5ZxZ2fCZlzKzTmPhe4mX9qTHRfLcKgqb0OKf22xLwDequ2tVleim+ZYx3rabD5w==", + "requires": { + "@babel/runtime": "^7.13.10", + "@radix-ui/primitive": "1.0.0", + "@radix-ui/react-compose-refs": "1.0.0", + "@radix-ui/react-context": "1.0.0", + "@radix-ui/react-dismissable-layer": "1.0.3", + "@radix-ui/react-id": "1.0.0", + "@radix-ui/react-popper": "1.1.1", + "@radix-ui/react-portal": "1.0.2", + "@radix-ui/react-presence": "1.0.0", + "@radix-ui/react-primitive": "1.0.2", + "@radix-ui/react-slot": "1.0.1", + "@radix-ui/react-use-controllable-state": "1.0.0", + "@radix-ui/react-visually-hidden": "1.0.2" } }, "@radix-ui/react-use-callback-ref": { @@ -24982,12 +25277,12 @@ } }, "@radix-ui/react-visually-hidden": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.1.tgz", - "integrity": "sha512-K1hJcCMfWfiYUibRqf3V8r5Drpyf7rh44jnrwAbdvI5iCCijilBBeyQv9SKidYNZIopMdCyR9FnIjkHxHN0FcQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.2.tgz", + "integrity": "sha512-qirnJxtYn73HEk1rXL12/mXnu2rwsNHDID10th2JGtdK25T9wX+mxRmGt7iPSahw512GbZOc0syZX1nLQGoEOg==", "requires": { "@babel/runtime": "^7.13.10", - "@radix-ui/react-primitive": "1.0.1" + "@radix-ui/react-primitive": "1.0.2" } }, "@radix-ui/rect": { @@ -24999,47 +25294,42 @@ } }, "@reduxjs/toolkit": { - "version": "1.8.3", - "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.8.3.tgz", - "integrity": "sha512-lU/LDIfORmjBbyDLaqFN2JB9YmAT1BElET9y0ZszwhSBa5Ef3t6o5CrHupw5J1iOXwd+o92QfQZ8OJpwXvsssg==", + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.5.tgz", + "integrity": "sha512-Rt97jHmfTeaxL4swLRNPD/zV4OxTes4la07Xc4hetpUW/vc75t5m1ANyxG6ymnEQ2FsLQsoMlYB2vV1sO3m8tQ==", "requires": { - "immer": "^9.0.7", - "redux": "^4.1.2", - "redux-thunk": "^2.4.1", - "reselect": "^4.1.5" + "immer": "^9.0.21", + "redux": "^4.2.1", + "redux-thunk": "^2.4.2", + "reselect": "^4.1.8" } }, "@rushstack/eslint-patch": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.2.0.tgz", - "integrity": "sha512-sXo/qW2/pAcmT43VoRKOJbDOfV3cYpq3szSVfIThQXNt+E4DfKj361vaAt3c88U5tPUxzEswam7GW48PJqtKAg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.3.0.tgz", + "integrity": "sha512-IthPJsJR85GhOkp3Hvp8zFOPK5ynKn6STyHa/WZpioK7E1aYDiBzpqQPrngc14DszIUkIrdd3k9Iu0XSzlP/1w==", "dev": true }, - "@sentry/types": { - "version": "7.22.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.22.0.tgz", - "integrity": "sha512-LhCL+wb1Jch+OesB2CIt6xpfO1Ab6CRvoNYRRzVumWPLns1T3ZJkarYfhbLaOEIb38EIbPgREdxn2AJT560U4Q==" - }, "@sinclair/typebox": { - "version": "0.24.51", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.24.51.tgz", - "integrity": "sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==", + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", "dev": true }, "@storybook/addon-actions": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.0.0-beta.30.tgz", - "integrity": "sha512-hk7e0B6kSPD/m5+pU6lKS3CzBBYf3n74m33cFjTRyhk8vO8x5QC5tni8nZdzmqREthoIOIf+1zHxYDO8SLE5zg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-7.0.12.tgz", + "integrity": "sha512-f07Mc3qwcG9heGsuUUTIJbWF2nw/Ite3mvyIZY2VbgwhMUMVHj4knY4fh/LojwcUmmmc7CNZu3sJN/wIqpaHCQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "dequal": "^2.0.2", "lodash": "^4.17.21", "polished": "^4.2.2", @@ -25047,174 +25337,183 @@ "react-inspector": "^6.0.0", "telejson": "^7.0.3", "ts-dedent": "^2.0.0", - "uuid-browser": "^3.1.0" + "uuid": "^9.0.0" + }, + "dependencies": { + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "dev": true + } } }, "@storybook/addon-backgrounds": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.0.0-beta.30.tgz", - "integrity": "sha512-UDPWQEwreK1TXjBjAmZN40uu5+7hC5dobdZhZr+i/4W+xswFMgprT4PtvfcoVyFTdOjRIsIDd0doLurvB5c1ng==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-7.0.12.tgz", + "integrity": "sha512-sAZSxsbj3CcabowALKTafpdnqXMBZB8C42s4Uxv11FCP50GqrP8jp2TqsIiDZxUbeXwI094W/gHnw41MSphG8Q==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "memoizerific": "^1.11.3", "ts-dedent": "^2.0.0" } }, "@storybook/addon-controls": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.0.0-beta.30.tgz", - "integrity": "sha512-5ybbmFH+gcrBRfJnRTdSgNbCYMJMHQY2QTNqukUHO0CjAPEZMpPCFkiQNdIBLslsju9+bunVo1S/MBfwH3Ku7Q==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-7.0.12.tgz", + "integrity": "sha512-/+yBhswN1N7ttR1NGN94HE/25VELm4YuBtrkh+LJeKP/eQ5CZpLjexASN2GZcfmdnkwIYZAEH0X/AImLaCJAWA==", "dev": true, "requires": { - "@storybook/blocks": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/blocks": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "lodash": "^4.17.21", "ts-dedent": "^2.0.0" } }, "@storybook/addon-docs": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.0.0-beta.30.tgz", - "integrity": "sha512-++SN8wmtiKE+bKbhscO8656GPZOFIEv31a3qYgId3W8wg/9YmTKUmXrejjUi3SZmO3xKVZ0bskJUw16oBWddug==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-7.0.12.tgz", + "integrity": "sha512-zgg4sq34Zz8TN74+kSogxRHsIZ5gsIazJpa0osZp91nJQvsKUEfldjBtQWbBWzjVCrWmzOhW5/RLCnmCNm9y/w==", "dev": true, "requires": { "@babel/core": "^7.20.2", "@babel/plugin-transform-react-jsx": "^7.19.0", "@jest/transform": "^29.3.1", "@mdx-js/react": "^2.1.5", - "@storybook/blocks": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/csf-plugin": "7.0.0-beta.30", - "@storybook/csf-tools": "7.0.0-beta.30", + "@storybook/blocks": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/csf-plugin": "7.0.12", + "@storybook/csf-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/mdx2-csf": "next", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/postinstall": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", - "fs-extra": "^9.0.1", + "@storybook/mdx2-csf": "^1.0.0", + "@storybook/node-logger": "7.0.12", + "@storybook/postinstall": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/react-dom-shim": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", + "fs-extra": "^11.1.0", "remark-external-links": "^8.0.0", "remark-slug": "^6.0.0", "ts-dedent": "^2.0.0" } }, "@storybook/addon-essentials": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.0.0-beta.30.tgz", - "integrity": "sha512-3X4WMrf4TCSN9iDrGAQlIM7bj8r+aov4O1Q/fM73n3B6puOG25uMzhT2V8MB4aJdGOXeYvvjAh5rMBdHxfQjPQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-7.0.12.tgz", + "integrity": "sha512-Js2cxvauAf8fkA5D0QrqPPe/FvpY1DbJp61VNGh82Xu0zZrczCGYP3jkWG79vl0zllJNs7hnkV8W6xY1JWgLoA==", "dev": true, "requires": { - "@storybook/addon-actions": "7.0.0-beta.30", - "@storybook/addon-backgrounds": "7.0.0-beta.30", - "@storybook/addon-controls": "7.0.0-beta.30", - "@storybook/addon-docs": "7.0.0-beta.30", - "@storybook/addon-highlight": "7.0.0-beta.30", - "@storybook/addon-measure": "7.0.0-beta.30", - "@storybook/addon-outline": "7.0.0-beta.30", - "@storybook/addon-toolbars": "7.0.0-beta.30", - "@storybook/addon-viewport": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", + "@storybook/addon-actions": "7.0.12", + "@storybook/addon-backgrounds": "7.0.12", + "@storybook/addon-controls": "7.0.12", + "@storybook/addon-docs": "7.0.12", + "@storybook/addon-highlight": "7.0.12", + "@storybook/addon-measure": "7.0.12", + "@storybook/addon-outline": "7.0.12", + "@storybook/addon-toolbars": "7.0.12", + "@storybook/addon-viewport": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", "ts-dedent": "^2.0.0" } }, "@storybook/addon-highlight": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.0.0-beta.30.tgz", - "integrity": "sha512-wyOl7mHGBB6u9I4uqn8PMlAGbZEfa0LeeDLqzzxZWzGFrFUVqjthQ+BAIbb8C+wOs9eb0CTGEecJQhurbV+UuA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-7.0.12.tgz", + "integrity": "sha512-ccIsBVjUlZ7cM1adSSFTqqWXiELPdDqfZLz4dWfDbiLyG3InC953ugtvoUWCIZpC2OOnjVLpF7Rbshq2O/QoMw==", "dev": true, "requires": { - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/preview-api": "7.0.12" } }, "@storybook/addon-interactions": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.0.0-beta.30.tgz", - "integrity": "sha512-mulmrEmDr9vynVVjmJ0OLiHd8NhGvrnTSrN6eMYLKp/VpOEOV0KgE28z+lqkeuAgRdcFG65ddV9AE8h1+rYxyg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-7.0.12.tgz", + "integrity": "sha512-Rb1mv1RQrTd3sA/WwNTdv00rW+7APfvZEeZks6+8+kS1C4EFMDmLnVBZlPllFdo1BOnTCyer4GZZ5ncVkWNLyQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/instrumenter": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/instrumenter": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "jest-mock": "^27.0.6", "polished": "^4.2.2", "ts-dedent": "^2.2.0" } }, "@storybook/addon-links": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.0.0-beta.30.tgz", - "integrity": "sha512-Uyj/WwUOGOTmDvYygM24vP0Zfj28ebYxtd07CYAlhvJ6P7yOb6H9v2cM/a2cJc1h7VmH9eohPNuTFDbv1P+QMQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-7.0.12.tgz", + "integrity": "sha512-6kGClsIpX9dRKc5bUAPNcp/4wlgPIxMrieUV+6k1dTsRQqbaEfxih/Fq259D5+yVBDNi3YAnvRjMiIibl8fa5A==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/router": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/router": "7.0.12", + "@storybook/types": "7.0.12", "prop-types": "^15.7.2", "ts-dedent": "^2.0.0" } }, "@storybook/addon-measure": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.0.0-beta.30.tgz", - "integrity": "sha512-tlY+CcZleoxMV5F50LLY/GFcWU8X5g9Td5K/pYqVw25jZFeqBZCZs+k0eqct1HeWKY64uutAYmljzrrwgpsUmw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-7.0.12.tgz", + "integrity": "sha512-Uq9cj9QmN7WKBQ6wqeneFmTqo1UQKXIc4CpGBEtJtfsYNLsERrVzOs/tRUf66Zl3lWgfFZxs1B5Ij6RDsYEjRw==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30" + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12" } }, "@storybook/addon-outline": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.0.0-beta.30.tgz", - "integrity": "sha512-qvJh05sc40NfF9RZ5KCVRHh3hRb0XCdxXP95qg7P0QF/BCRIrLTP8/94rT56IwhaMKDTttoU1x2PST0FDxQZaQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-7.0.12.tgz", + "integrity": "sha512-eZPkm3mECdqx1EDJ0S6DAzZ9WZLPIsZH7fRy6vdJJuAgvnOSzkt7AEpA0hlgiNyXcFpE1Cav6/g12FUf4Zo82g==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12", "ts-dedent": "^2.0.0" } }, @@ -25232,9 +25531,9 @@ }, "dependencies": { "@storybook/node-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.15.tgz", - "integrity": "sha512-LQjjbfMuUXm7wZTBKb+iGeCNnej4r1Jb2NxG3Svu2bVhaoB6u33jHAcbmhXpXW1jghzW3kQwOU7BoLuJiRRFIw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-6.5.16.tgz", + "integrity": "sha512-YjhBKrclQtjhqFNSO+BZK+RXOx6EQypAELJKoLFaawg331e8VUfvUuRCNB3fcEWp8G9oH13PQQte0OTjLyyOYg==", "dev": true, "requires": { "@types/npmlog": "^4.1.2", @@ -25263,81 +25562,12 @@ "supports-color": "^7.1.0" } }, - "css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" - }, - "dependencies": { - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "icss-utils": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", - "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", - "dev": true, - "requires": { - "postcss": "^7.0.14" - } - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "loader-utils": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", - "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^1.0.1" - } - }, "picocolors": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", @@ -25354,125 +25584,12 @@ "source-map": "^0.6.1" } }, - "postcss-loader": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", - "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", - "dev": true, - "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.4", - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0", - "semver": "^7.3.4" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", - "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", - "dev": true, - "requires": { - "postcss": "^7.0.5" - } - }, - "postcss-modules-local-by-default": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", - "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", - "dev": true, - "requires": { - "icss-utils": "^4.1.1", - "postcss": "^7.0.32", - "postcss-selector-parser": "^6.0.2", - "postcss-value-parser": "^4.1.0" - } - }, - "postcss-modules-scope": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", - "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", - "dev": true, - "requires": { - "postcss": "^7.0.6", - "postcss-selector-parser": "^6.0.0" - } - }, - "postcss-modules-values": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", - "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", - "dev": true, - "requires": { - "icss-utils": "^4.0.0", - "postcss": "^7.0.6" - } - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true }, - "style-loader": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", - "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", - "dev": true, - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^2.7.0" - }, - "dependencies": { - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dev": true, - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "schema-utils": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", - "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.5", - "ajv": "^6.12.4", - "ajv-keywords": "^3.5.2" - } - } - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -25485,136 +25602,136 @@ } }, "@storybook/addon-toolbars": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.0.0-beta.30.tgz", - "integrity": "sha512-b+aOu6lT9OR8WhqXDJwzV/u3DFvB3/Cl31UD1W6BrnqkoMJ7WbZy74stsNx0Kb2g6WqGzqHuErRtS2YMpCMUZA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-7.0.12.tgz", + "integrity": "sha512-7xRxk+999NVdEwzn2z1O9Tg5iuUSEXQ5jo+hiyK934VvuyqUsZnflKbSvwVEHb2W+DroaaXu8bdHWxGSH+6moQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12" } }, "@storybook/addon-viewport": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.0.0-beta.30.tgz", - "integrity": "sha512-ugk44rt07zyj4kUNt8aNHGxMFbrqjygGk+MznASrOd4F4G4LzM09O+a/YqGGKSJQlb90gadW7Xj1iy4HP28NtA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-7.0.12.tgz", + "integrity": "sha512-pMgqtDQF8e9AErnRKbbSK9m1lcKn1dFSOkk0PgSBwIIjmha6q+GeT45EHQrQGtkLdtWT0iTktC8ivzIiGKmHkg==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", "memoizerific": "^1.11.3", "prop-types": "^15.7.2" } }, "@storybook/addons": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.0.0-beta.30.tgz", - "integrity": "sha512-J0/tiaEPXNVbjUAgSNuLirfRfhUwQ5PC4LvNLYO//OKpRn/pvsh5jlFWKVoXG5Km711atS6P7aOt7vTTAH8Akg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-7.0.12.tgz", + "integrity": "sha512-yVADbWCFdb12cSpspeb+/6lfTNarPtZZLql49Bhu6E7PxECw/Q3kfHu0LXBLcSnU7f4QqQvQjp88ultt01ABBQ==", "dev": true, "requires": { - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30" + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12" } }, "@storybook/api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.0.0-beta.30.tgz", - "integrity": "sha512-D7ggwRM6yDrHBDI8IXoRA6XVWrrqNL0E1m+M2uBK9RoKfgVJr9TMapFl3u46LTIC76EsFigJCFdNnlPmnIwlhQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-7.0.12.tgz", + "integrity": "sha512-wki9B7ZXOGwUq/FowDgEnkkX92oNpSg/6ES5Rh19NF3wV0ObLlgXMZ8cZKOLM6G0m/8lkKHGeNBunaLUnX7Yhw==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/manager-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/manager-api": "7.0.12" } }, "@storybook/blocks": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.0.0-beta.30.tgz", - "integrity": "sha512-kwH9Xlr8GeGvJPjbuvlC4aGkZq/1Xz5S5Cnapfs3vnDSD76/30XvFj+QUV+clf3aPAbbKI1QJIXy2lCzUME46w==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-7.0.12.tgz", + "integrity": "sha512-MbJKjuTJ7xVbkUVwkEwb6vTYGrkRk4+Xtx1UGo+512o91ubqFs8hXwCHP+x/49RCIIQs5zl93Ig8fTtm+MejWw==", "dev": true, "requires": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", - "@storybook/docs-tools": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", + "@storybook/docs-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "@types/lodash": "^4.14.167", "color-convert": "^2.0.1", "dequal": "^2.0.2", "lodash": "^4.17.21", - "markdown-to-jsx": "^7.1.3", + "markdown-to-jsx": "^7.1.8", "memoizerific": "^1.11.3", "polished": "^4.2.2", "react-colorful": "^5.1.2", + "telejson": "^7.0.3", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" } }, "@storybook/builder-manager": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.0.0-beta.30.tgz", - "integrity": "sha512-hBiF7LE4Ojsgh7E9LRPgwHATQuV/izY8F/tFKCbWO3g5yzElEHcspEDJmbxh9HnAhNcYFvshCwFBBC1CTc8sTQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/builder-manager/-/builder-manager-7.0.12.tgz", + "integrity": "sha512-bkZPSDH38/dUSsO087oQ8+goyaEDP/xD0/O61QcQ8EbaVeT6s6Qt7mMhqsLrtmEZHvPMQwKeIXhOJlRNNXB+SA==", "dev": true, "requires": { "@fal-works/esbuild-plugin-global-externals": "^2.1.2", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/manager": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/manager": "7.0.12", + "@storybook/node-logger": "7.0.12", "@types/ejs": "^3.1.1", "@types/find-cache-dir": "^3.2.1", "@yarnpkg/esbuild-plugin-pnp": "^3.0.0-rc.10", "browser-assert": "^1.2.1", "ejs": "^3.1.8", - "esbuild": "^0.16.4", + "esbuild": "^0.17.0", "esbuild-plugin-alias": "^0.2.1", "express": "^4.17.3", "find-cache-dir": "^3.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "process": "^0.11.10", - "slash": "^3.0.0", "util": "^0.12.4" } }, "@storybook/builder-webpack5": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.0.0-beta.30.tgz", - "integrity": "sha512-7SS+F9tyIL9N2iUNapCFy0aSxrXRI2byXuKM/xCXgYnMq04z3MbPuG6ymaYUoRZQ2zMYoHkMA8iaLthHsIoRAQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/builder-webpack5/-/builder-webpack5-7.0.12.tgz", + "integrity": "sha512-msrDWgNFu0kkQ8AOuOCqO+Z+b6iB2kNMhpTyreFbZfUwnEv35aXdULeSa/2mCD0/PFUUFZu+cVYflMyENZxe5w==", "dev": true, "requires": { "@babel/core": "^7.12.10", - "@storybook/addons": "7.0.0-beta.30", - "@storybook/api": "7.0.0-beta.30", - "@storybook/channel-postmessage": "7.0.0-beta.30", - "@storybook/channel-websocket": "7.0.0-beta.30", - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-api": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/components": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/core-webpack": "7.0.0-beta.30", + "@storybook/addons": "7.0.12", + "@storybook/api": "7.0.12", + "@storybook/channel-postmessage": "7.0.12", + "@storybook/channel-websocket": "7.0.12", + "@storybook/channels": "7.0.12", + "@storybook/client-api": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/components": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/core-webpack": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/manager-api": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/router": "7.0.0-beta.30", - "@storybook/store": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", + "@storybook/manager-api": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/router": "7.0.12", + "@storybook/store": "7.0.12", + "@storybook/theming": "7.0.12", "@types/node": "^16.0.0", "@types/semver": "^7.3.4", "babel-loader": "^9.0.0", @@ -25624,12 +25741,11 @@ "css-loader": "^6.7.1", "express": "^4.17.3", "fork-ts-checker-webpack-plugin": "^7.2.8", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "html-webpack-plugin": "^5.5.0", "path-browserify": "^1.0.1", "process": "^0.11.10", "semver": "^7.3.7", - "slash": "^3.0.0", "style-loader": "^3.3.1", "terser-webpack-plugin": "^5.3.1", "ts-dedent": "^2.0.0", @@ -25642,60 +25758,151 @@ }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", + "dev": true + }, + "css-loader": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.4.tgz", + "integrity": "sha512-0Y5uHtK5BswfaGJ+jrO+4pPg1msFBc0pwPIE1VqfpmVn6YbDfYfXMj8rfd7nt+4goAhJueO+H/I40VWJfcP1mQ==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.1", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.1.tgz", + "integrity": "sha512-Zr/dB+IlXaEqdoslLHhhqecwj73vc3rDmOpsBNBEVk7P2aqAlz+Ijy0fFbU5Ie9PtreDOIgGa9MsLWakVGl+fA==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "dev": true, + "requires": {} + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "@storybook/channel-postmessage": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-7.0.0-beta.30.tgz", - "integrity": "sha512-szCRSlMZr0ii/j+kIHKim1kCpmVblhvLl8vW25sbUkW0lSJ7F0VQ1mQSNjXDWhZHEMb9/1ZYCbN7HOsXp9oCRg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channel-postmessage/-/channel-postmessage-7.0.12.tgz", + "integrity": "sha512-Tc7kQZ5yxlZ44Nmmzec92JaDJ6UZ3Ze4cBfiHik4XcnM1PtN8hr8VFoC6a2AIm1ybfIRenfT5w9TH5yriiPIhw==", "dev": true, "requires": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", "qs": "^6.10.0", "telejson": "^7.0.3" } }, "@storybook/channel-websocket": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-7.0.0-beta.30.tgz", - "integrity": "sha512-Q+bShSf8ueKw5H3vN76lgAqzl+bG7rqjQhgG7ALYUPDgNGFf+7dFoe2/g5byjhZAZGomObhmIRjpPkCmUzx4Uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channel-websocket/-/channel-websocket-7.0.12.tgz", + "integrity": "sha512-UV6b9gX2mQLtXlKaFKCHcy+6MaK2od6BYqSJfainnBjDsMIXyhcf7fJaj0XQkJrbNnRBwGhw+6s8JxL98xp7Ew==", "dev": true, "requires": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", "@storybook/global": "^5.0.0", "telejson": "^7.0.3" } }, "@storybook/channels": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.0.0-beta.30.tgz", - "integrity": "sha512-XIlFxLKy0MGpWIGondLHf92Aku57SpIxZXmjLbM2iAeG0UljzdL+d8BoMp5Yo0CVMmMBGGZEoM7INrhf6p2WKw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-7.0.12.tgz", + "integrity": "sha512-KDdDmDs8kxAJU+vndTqTNazjLO+XoIPiTRlfP7mk7cgHiQXSjMYy3JSCQ7W0of0Q+9VSl/ve9CNbnGbcQF7rNQ==", "dev": true }, "@storybook/cli": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.0.0-beta.30.tgz", - "integrity": "sha512-nwgHQysnL67VZ/fP99BR16E9WRH634pg2hbRqzC1DCzEWAfAcnlZPbnOUmbVhpL6MdJw6i5nyVdk4ugUcFI8pA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/cli/-/cli-7.0.12.tgz", + "integrity": "sha512-OABCRIujxsszIJ0CCpKg8Uj4C1UlAwBpBQhv2aMX3lA/pur6Od524syv2ypWu6J2FyvK/ooeyMbjoP7330cIuA==", "dev": true, "requires": { "@babel/core": "^7.20.2", "@babel/preset-env": "^7.20.2", - "@storybook/codemod": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-server": "7.0.0-beta.30", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/telemetry": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@ndelangen/get-tarball": "^3.0.7", + "@storybook/codemod": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-server": "7.0.12", + "@storybook/csf-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/telemetry": "7.0.12", + "@storybook/types": "7.0.12", "@types/semver": "^7.3.4", "boxen": "^5.1.2", "chalk": "^4.1.0", @@ -25706,12 +25913,14 @@ "execa": "^5.0.0", "express": "^4.17.3", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", + "get-npm-tarball-url": "^2.0.3", "get-port": "^5.1.1", "giget": "^1.0.0", "globby": "^11.0.2", - "jscodeshift": "^0.13.1", + "jscodeshift": "^0.14.0", "leven": "^3.1.0", + "prettier": "^2.8.0", "prompts": "^2.4.0", "puppeteer-core": "^2.1.1", "read-pkg-up": "^7.0.1", @@ -25755,6 +25964,24 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -25763,110 +25990,112 @@ "requires": { "has-flag": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, "@storybook/client-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.0-beta.30.tgz", - "integrity": "sha512-FPRmBmRRzsA9ZNXBwoOVEMze8dp/U1DxA0OKw9y24v/ijgg+P6GAqpX3WFrx3eQWn3I3oMg/8kJwANvOv38ZDw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/client-api/-/client-api-7.0.12.tgz", + "integrity": "sha512-kcB0wX9+pL9NW8+xFVABFZJeChsql9i2A69yUQQ8OCaJhB7LS3gl1Ri4zJhVHSuTTWBlbNUSPbu1yEkFiAWt/g==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" } }, "@storybook/client-logger": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.0.0-beta.30.tgz", - "integrity": "sha512-50JKxy0E2jUfGcfHwBp+NnlVLqaELSTjB5CjxckUExLfsU/u3dzTPrMmxevBw3ojqaCtyGKZE0yY0ndn/QbeuA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-7.0.12.tgz", + "integrity": "sha512-MQMtIgGEgdixvxnBvZ2m8hhc0DGJWeCpHtxg7oqBLBEBmCYFueTqDZHl4Z6SoCrK0a2YS5X/BIXOcEtP1ulMKw==", "dev": true, "requires": { "@storybook/global": "^5.0.0" } }, "@storybook/codemod": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.0.0-beta.30.tgz", - "integrity": "sha512-kJmzhLVavUB5wTkL1RfnZZml6uSMtwTExMAAoMl1q8ie1KVIXEjO7vrQYz8xRFsQJ/y36TeJWY8w45kjBie0Aw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/codemod/-/codemod-7.0.12.tgz", + "integrity": "sha512-eGbGZSglvbnY1omzRyEC4XP0FbpuCFKgjXmdHn9faGQUU5EJHwcGYYrRW8JZL3nEVIvNDuRAKzM3p0BVo1xeSQ==", "dev": true, "requires": { - "@babel/core": "^7.20.2", - "@babel/preset-env": "^7.20.2", - "@babel/types": "^7.20.7", - "@storybook/csf": "next", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@babel/core": "~7.21.0", + "@babel/preset-env": "~7.21.0", + "@babel/types": "~7.21.2", + "@storybook/csf": "^0.1.0", + "@storybook/csf-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "cross-spawn": "^7.0.3", "globby": "^11.0.2", - "jscodeshift": "^0.13.1", + "jscodeshift": "^0.14.0", "lodash": "^4.17.21", "prettier": "^2.8.0", - "recast": "^0.23.1", - "util": "^0.12.4" + "recast": "^0.23.1" } }, "@storybook/components": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.0.0-beta.30.tgz", - "integrity": "sha512-CrGZY97t0lcjM/kevTVUYrZ35Civnpyyn4Q5uPbHv9cilmSGxbGg3r1yH8s6+FfbSobb77ZiCCbZXCWrSCiwnQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-7.0.12.tgz", + "integrity": "sha512-6TxByzYS4+LxwZRioGpP6Zh9If5ctjQs5OnR2UmQvP6HDjmMWYTntoHKIbDwAL9C6MrnQYpPOGCPkqrtODQ4/w==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/client-logger": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "memoizerific": "^1.11.3", + "use-resize-observer": "^9.1.0", "util-deprecate": "^1.0.2" } }, "@storybook/core-client": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.0.0-beta.30.tgz", - "integrity": "sha512-4F2TMNjV8YpEJoCUGa9yfD+3zv60/pG1xjt6NP5uoMKsvqjfDOXCXXQGcUd6lnidGu/xoYvhR8r0KsRmsIzRYQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-client/-/core-client-7.0.12.tgz", + "integrity": "sha512-m0r+Vl3LfU8cJl8UqIwzh0sEN9I//nMaT8UIIm481AINhQTNihQcnYi9jRw7USjfz2fv5CYkg8cEr4KhI8QlRA==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" } }, "@storybook/core-common": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.0.0-beta.30.tgz", - "integrity": "sha512-46U4cHOgKQBxFBZO19lx0eR7F/fJgzBr4Nhx4Ws6vhdW5492aa8NPjHM+59jXOMpU8ZM3zHvhObaL/VMwnTJWg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-common/-/core-common-7.0.12.tgz", + "integrity": "sha512-PFVjYXHUxDQO1oqfqwQe7S3XoLNO0aZYEr9Zl0LiexlxxnU1v+TQjEfNd/H3T0xxpXlsgzhtEcagdzJeAKyh2g==", "dev": true, "requires": { - "@babel/core": "^7.20.2", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", - "@types/babel__core": "^7.1.20", - "@types/express": "^4.7.0", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "@types/node": "^16.0.0", "@types/pretty-hrtime": "^1.0.0", "chalk": "^4.1.0", - "esbuild": "^0.16.4", - "esbuild-register": "^3.3.3", - "express": "^4.17.3", + "esbuild": "^0.17.0", + "esbuild-register": "^3.4.0", "file-system-cache": "^2.0.0", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", - "glob": "^7.1.6", + "fs-extra": "^11.1.0", + "glob": "^8.1.0", + "glob-promise": "^6.0.2", "handlebars": "^4.7.7", - "lazy-universal-dotenv": "^3.0.1", + "lazy-universal-dotenv": "^4.0.0", "picomatch": "^2.3.0", "pkg-dir": "^5.0.0", "pretty-hrtime": "^1.0.3", "resolve-from": "^5.0.0", - "slash": "^3.0.0", "ts-dedent": "^2.0.0" }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, "ansi-styles": { @@ -25894,12 +26123,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -25912,30 +26135,31 @@ } }, "@storybook/core-events": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.0-beta.30.tgz", - "integrity": "sha512-Q+psogB1KJFU6m+Zz4QqJBDVsTsR9vceVaUDceGogGbZEjBXpIAKwAJzVVi62pJKeFHclcCI4JbquYoOu2vK9w==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-7.0.12.tgz", + "integrity": "sha512-VTmb/zjbz3o1bg+bATzLigVXMVDC/S1FP8CqIrz4mkiys52139FGzMandL2Y2AecPZPGss7ZRdfma28HKVYTRg==", "dev": true }, "@storybook/core-server": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.0.0-beta.30.tgz", - "integrity": "sha512-GfOg7P53OMR/Qa/DAz9IdRpu0sUJlZdrKv53otu4TnI8OxW+Wcom6Ef16aiwaONivQG78zKPzB5w+0+1f2N5uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-server/-/core-server-7.0.12.tgz", + "integrity": "sha512-X35Kmg7y35Ph4J+gCDJrnVgBwlz4/DzOQofUS6rAbi4KvrPWDJXeM2OzOgx6B0abKl4CeMmjuc0tjbg4vbUFuA==", "dev": true, "requires": { "@aw-web-design/x-default-browser": "1.4.88", "@discoveryjs/json-ext": "^0.5.3", - "@storybook/builder-manager": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", - "@storybook/csf-tools": "7.0.0-beta.30", - "@storybook/docs-mdx": "next", + "@storybook/builder-manager": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", + "@storybook/csf-tools": "7.0.12", + "@storybook/docs-mdx": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/telemetry": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/manager": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/telemetry": "7.0.12", + "@storybook/types": "7.0.12", "@types/detect-port": "^1.3.0", "@types/node": "^16.0.0", "@types/node-fetch": "^2.5.7", @@ -25948,7 +26172,7 @@ "compression": "^1.7.4", "detect-port": "^1.3.0", "express": "^4.17.3", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "globby": "^11.0.2", "ip": "^2.0.0", "lodash": "^4.17.21", @@ -25959,7 +26183,6 @@ "read-pkg-up": "^7.0.1", "semver": "^7.3.7", "serve-favicon": "^2.5.0", - "slash": "^3.0.0", "telejson": "^7.0.3", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2", @@ -25968,9 +26191,9 @@ }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, "ansi-styles": { @@ -25998,6 +26221,24 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -26006,89 +26247,88 @@ "requires": { "has-flag": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, "@storybook/core-webpack": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.0.0-beta.30.tgz", - "integrity": "sha512-zVlXka9WlJovzNmtAnuGMPBnQBvOdP2Qi62TXdqRh1ctrCX4obRtleyDJVnzdev9awn6Z+Rfbe/zqOvwISr2vw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/core-webpack/-/core-webpack-7.0.12.tgz", + "integrity": "sha512-71tLTurZg5rYfjHuSUtnT8mcKc4CugvXh6DrJSf/1lTFarWvOZkYha9oh4gVokFWpAiK3GM9LE2DlCAozc9Xnw==", "dev": true, "requires": { - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/types": "7.0.12", "@types/node": "^16.0.0", "ts-dedent": "^2.0.0" }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true } } }, "@storybook/csf": { - "version": "0.0.2-next.8", - "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.0.2-next.8.tgz", - "integrity": "sha512-3T6rflW7D9q1iXOR+bidwoNbd9rVUTyjYH/sqsnYjbXhb/aOXsQzGKwNeq9QqZIFVpKfg5BoOF5i7DCMtoGknQ==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/csf/-/csf-0.1.0.tgz", + "integrity": "sha512-uk+jMXCZ8t38jSTHk2o5btI+aV2Ksbvl6DoOv3r6VaCM1KZqeuMwtwywIQdflkA8/6q/dKT8z8L+g8hC4GC3VQ==", "dev": true, "requires": { - "expect-type": "^0.14.2", - "lodash": "^4.17.15", "type-fest": "^2.19.0" - }, - "dependencies": { - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "dev": true - } } }, "@storybook/csf-plugin": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.0.0-beta.30.tgz", - "integrity": "sha512-ny8NCrdJWjSxraCWAGdMjXP1EtHygABCjv6Qcv9OijBexmzET04YwY7HmQlW6B9tq2l86TlFLPyICVtv8wniyA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-7.0.12.tgz", + "integrity": "sha512-iiH0ynLQV5BYFc0o7RlSJS2S3GT/ffyfbV4rnCnPKdqyo4REEVvmhOuLhwzurtsXsjh+xF6VUYUDN+8/5mbkYw==", "dev": true, "requires": { - "@storybook/csf-tools": "7.0.0-beta.30", + "@storybook/csf-tools": "7.0.12", "unplugin": "^0.10.2" } }, "@storybook/csf-tools": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.0.0-beta.30.tgz", - "integrity": "sha512-/CCizDLZSqm3lNO0w+oc1Xqid4/Ix7TikKZxxaOpGipXp4Ehw8iRMjnfHbE+ANq8ZtTdQzOXBxG4LG2noUpHBw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/csf-tools/-/csf-tools-7.0.12.tgz", + "integrity": "sha512-EcDzKeENzs4awyjx0VxlONDLibiEtIPDP1XdOCcZGtv3nXXBFtS2WDsYhJHkwyvE37jWTyw2e4xKQmBi0Hjvbw==", "dev": true, "requires": { - "@babel/types": "^7.20.2", - "@storybook/csf": "next", - "@storybook/types": "7.0.0-beta.30", - "fs-extra": "^9.0.1", + "@babel/generator": "~7.21.1", + "@babel/parser": "~7.21.2", + "@babel/traverse": "~7.21.2", + "@babel/types": "~7.21.2", + "@storybook/csf": "^0.1.0", + "@storybook/types": "7.0.12", + "fs-extra": "^11.1.0", "recast": "^0.23.1", "ts-dedent": "^2.0.0" } }, "@storybook/docs-mdx": { - "version": "0.0.1-next.5", - "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.0.1-next.5.tgz", - "integrity": "sha512-EowXFPq4TBZQguKCdU8y7EzpuSv2vSu5gy7pgF/1P5mq7LG9h8YIrerOW9DL4zfp9E0GHIWlSXR5KuFIqqKc/Q==", + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/@storybook/docs-mdx/-/docs-mdx-0.1.0.tgz", + "integrity": "sha512-JDaBR9lwVY4eSH5W8EGHrhODjygPd6QImRbwjAuJNEnY0Vw4ie3bPkeGfnacB3OBW6u/agqPv2aRlR46JcAQLg==", "dev": true }, "@storybook/docs-tools": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.0.0-beta.30.tgz", - "integrity": "sha512-pPGI1K0YXWTmRLg8VDy7BiZvUPmRLfdVP05vFEMw+5LpwZNjTI1hn8eQgEIME9eESNOZFj/VhdewPNfyki9M5A==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/docs-tools/-/docs-tools-7.0.12.tgz", + "integrity": "sha512-+HykeQLgjyDyF9G7HqY0FHXlX7X5YpQcmNjftJzBrc/GO1EeO0M78d54avcOPyyTfuWOh7oZtSJ0MzjA1qrqaQ==", "dev": true, "requires": { "@babel/core": "^7.12.10", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/core-common": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/types": "7.0.12", "@types/doctrine": "^0.0.3", "doctrine": "^3.0.0", "lodash": "^4.17.21" @@ -26101,39 +26341,38 @@ "dev": true }, "@storybook/instrumenter": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.0.0-beta.30.tgz", - "integrity": "sha512-raP9Sq5QmAJ4nf4IRs5hKOBZ3dg5h/GiKtwIlJI6sA5zo3bHzvqApOD308yG4fp2hyeiaBbjFBsDi2Kchrv6uw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-7.0.12.tgz", + "integrity": "sha512-jx4rb4AMT1YIOpE0HCdfyLvpYU+94wPkC9vt7sZGWAp7nnYG+KO/lx3XCJaR9qQPIxVYejJtWkeGn4RID79SoQ==", "dev": true, "requires": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30", - "core-js": "^3.8.2" + "@storybook/preview-api": "7.0.12" } }, "@storybook/manager": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.0.0-beta.30.tgz", - "integrity": "sha512-yI9O27g/k/wYGH4/ct/59XytnAy5XU49UxLrOUI3Np1Z+lstOikslqk2g0h3Zp3IFNzXNYZkVgQ2dPWxHeLabA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/manager/-/manager-7.0.12.tgz", + "integrity": "sha512-19BsDcwJOYXn6zEarxvNGDdYLUqZyhX92x6GPHSC4cf8BoxHuhmtnz5vOTZHusCxkKIu/C9W0H6wH2Ma47kDCg==", "dev": true }, "@storybook/manager-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.0.0-beta.30.tgz", - "integrity": "sha512-cxEn56WpzI6UMBIaD5rgTeTg67VzREUOLgXIy51W1u7NWSb2T5agHrLzXg3Oaxlh1tL4bronbTibx/qveahtgA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-7.0.12.tgz", + "integrity": "sha512-3QXARtxpc6Xxqf5pviUw2UuhK53+IsINSljeWhAqdQ1Gzbywl67TpibTd7xVN6NKxhUH5Bzo9bIZTAzMZGqaKw==", "dev": true, "requires": { - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/router": "7.0.0-beta.30", - "@storybook/theming": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/router": "7.0.12", + "@storybook/theming": "7.0.12", + "@storybook/types": "7.0.12", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", @@ -26141,66 +26380,225 @@ "store2": "^2.14.2", "telejson": "^7.0.3", "ts-dedent": "^2.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + } } }, "@storybook/mdx2-csf": { - "version": "1.0.0-next.4", - "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.0.0-next.4.tgz", - "integrity": "sha512-nvRgYdpYvXsvSgCzKc4LQA1JxtJzmv47IsFAsh1rTz5FoHyK8watLU2WqX9T4w52fpFXBHx7RwGEsCRt0XgZlQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@storybook/mdx2-csf/-/mdx2-csf-1.1.0.tgz", + "integrity": "sha512-TXJJd5RAKakWx4BtpwvSNdgTDkKM6RkXU8GK34S/LhidQ5Pjz3wcnqb0TxEkfhK/ztbP8nKHqXFwLfa2CYkvQw==", "dev": true }, "@storybook/nextjs": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-7.0.0-beta.30.tgz", - "integrity": "sha512-f8lJ4SFJEc6cp6ktUekiehRd8L9u+WoJCX4QnH630K+4dj5ZoXi+mEP3bSwrW/szkwN9A+P5wobAhTiXi7KTQw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/nextjs/-/nextjs-7.0.12.tgz", + "integrity": "sha512-XFO62uKiS1Cojn2SFQCQXL1RWyylrug1ywKl88OVDmOwBVfJQ/Xm/PMJVp+4dMRFOGQFAIS86uUImNZRHyGsfA==", "dev": true, "requires": { - "@next/font": "^13.0.7", - "@storybook/addon-actions": "7.0.0-beta.30", - "@storybook/builder-webpack5": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/preset-react-webpack": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/react": "7.0.0-beta.30", + "@babel/plugin-proposal-class-properties": "^7.18.6", + "@babel/plugin-proposal-export-namespace-from": "^7.18.9", + "@babel/plugin-proposal-numeric-separator": "^7.18.6", + "@babel/plugin-proposal-object-rest-spread": "^7.20.7", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.20.0", + "@babel/plugin-transform-runtime": "^7.21.0", + "@babel/preset-env": "^7.20.2", + "@babel/preset-react": "^7.18.6", + "@babel/preset-typescript": "^7.21.0", + "@babel/runtime": "^7.21.0", + "@storybook/addon-actions": "7.0.12", + "@storybook/builder-webpack5": "7.0.12", + "@storybook/core-common": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/preset-react-webpack": "7.0.12", + "@storybook/preview-api": "7.0.12", + "@storybook/react": "7.0.12", "@types/node": "^16.0.0", + "css-loader": "^6.7.3", "find-up": "^5.0.0", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "image-size": "^1.0.0", "loader-utils": "^3.2.0", "pnp-webpack-plugin": "^1.7.0", - "postcss-loader": "^6.2.1", + "postcss": "^8.4.21", + "postcss-loader": "^7.0.2", "resolve-url-loader": "^5.0.0", "sass-loader": "^12.4.0", "semver": "^7.3.5", + "style-loader": "^3.3.1", + "styled-jsx": "5.1.1", "ts-dedent": "^2.0.0", "tsconfig-paths": "^4.0.0", "tsconfig-paths-webpack-plugin": "^3.5.2" }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true }, - "tsconfig-paths": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.1.2.tgz", - "integrity": "sha512-uhxiMgnXQp1IR622dUXI+9Ehnws7i/y6xvpZB9IbUVOPy0muvdvgXeZOn88UcGPiT98Vp3rJPTa8bFoalZ3Qhw==", + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "cosmiconfig": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.1.3.tgz", + "integrity": "sha512-/UkO2JKI18b5jVMJUp0lvKFMpa/Gye+ZgZjKD+DGEN9y7NRcf/nK1A0sp67ONmKtnDCNMS44E6jrk0Yc3bDuUw==", "dev": true, "requires": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0" } + }, + "css-loader": { + "version": "6.7.4", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.4.tgz", + "integrity": "sha512-0Y5uHtK5BswfaGJ+jrO+4pPg1msFBc0pwPIE1VqfpmVn6YbDfYfXMj8rfd7nt+4goAhJueO+H/I40VWJfcP1mQ==", + "dev": true, + "requires": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.21", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.1", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.3.8" + } + }, + "icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "dev": true, + "requires": {} + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "postcss-loader": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.0.tgz", + "integrity": "sha512-qLAFjvR2BFNz1H930P7mj1iuWJFjGey/nVhimfOAAQ1ZyPpcClAxP8+A55Sl8mBvM+K2a9Pjgdj10KpANWrNfw==", + "dev": true, + "requires": { + "cosmiconfig": "^8.1.3", + "jiti": "^1.18.2", + "klona": "^2.0.6", + "semver": "^7.3.8" + } + }, + "postcss-modules-extract-imports": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", + "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", + "dev": true, + "requires": {} + }, + "postcss-modules-local-by-default": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.1.tgz", + "integrity": "sha512-Zr/dB+IlXaEqdoslLHhhqecwj73vc3rDmOpsBNBEVk7P2aqAlz+Ijy0fFbU5Ie9PtreDOIgGa9MsLWakVGl+fA==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.1.0" + } + }, + "postcss-modules-scope": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", + "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "dev": true, + "requires": { + "postcss-selector-parser": "^6.0.4" + } + }, + "postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dev": true, + "requires": { + "icss-utils": "^5.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "style-loader": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.3.tgz", + "integrity": "sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw==", + "dev": true, + "requires": {} + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, "@storybook/node-logger": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.0.0-beta.30.tgz", - "integrity": "sha512-mAvPG4smFASwSmb1+nMvR10Zlg/zPmNFeh6IKMttOWS5O0qSVzXGv4/QH63tjBcS0w915W3TGcDLLpKDa0c+lA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/node-logger/-/node-logger-7.0.12.tgz", + "integrity": "sha512-VL+NXzc9NuOP6/9alg4Sofz9kh8tmlo3p+UtCIYCHH088yCsB3XsNhkG9lF1C5EZVWcuHxc2u6MMF3ezOjvKfQ==", "dev": true, "requires": { "@types/npmlog": "^4.1.2", @@ -26246,84 +26644,109 @@ } }, "@storybook/postinstall": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.0.0-beta.30.tgz", - "integrity": "sha512-PoM6+UVLd589bM8kg2SNer8ORNMhC3SV894/dfhvgXm7id4weqZ5xnhfZ/T0ZYH2Ts7qSuR+TQmPVAAQNHsrag==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/postinstall/-/postinstall-7.0.12.tgz", + "integrity": "sha512-RKNvBLgABBTQwvGyF2jX4vP7OMLB3KvEEOQDoeOKjqyWfekDn5smI+eT714mtmKIH0YMcwmvzLgEdZkjmM/XhA==", "dev": true }, "@storybook/preset-react-webpack": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.0.0-beta.30.tgz", - "integrity": "sha512-PF7CAXWv6nS6N5OXnEj3XZKJRIKIFRmIrWwBhdK1L30XCHmQ313/0lA9JV24UHU8EwkUOfyF1IKkikhkKBkTTg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preset-react-webpack/-/preset-react-webpack-7.0.12.tgz", + "integrity": "sha512-EBgP5p8uiwJXPpM5M6mC4SrKCKSeQEJI+oQ36olUIB7PUhysiVFhLB+rOIgkXc3nhX1uRTO/PYefd9PBMwE11A==", "dev": true, "requires": { "@babel/preset-flow": "^7.18.6", "@babel/preset-react": "^7.18.6", "@pmmmwh/react-refresh-webpack-plugin": "^0.5.5", - "@storybook/core-webpack": "7.0.0-beta.30", - "@storybook/docs-tools": "7.0.0-beta.30", - "@storybook/node-logger": "7.0.0-beta.30", - "@storybook/react": "7.0.0-beta.30", - "@storybook/react-docgen-typescript-plugin": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", + "@storybook/core-webpack": "7.0.12", + "@storybook/docs-tools": "7.0.12", + "@storybook/node-logger": "7.0.12", + "@storybook/react": "7.0.12", + "@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.0c3f3b7.0", "@types/node": "^16.0.0", "@types/semver": "^7.3.4", "babel-plugin-add-react-displayname": "^0.0.5", "babel-plugin-react-docgen": "^4.2.1", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "react-refresh": "^0.11.0", - "semver": "^7.3.7" + "semver": "^7.3.7", + "webpack": "5" }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "@storybook/preview": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.0.0-beta.30.tgz", - "integrity": "sha512-mcqs1PB7i/oEx4viFMECA6tI14x29RMGVctPtipkDIo0myo1BAsHSsgALaHRfQCw9mXl5KUiOyiwHQMf0dEkwg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preview/-/preview-7.0.12.tgz", + "integrity": "sha512-za8El/nnkyAo/uqyqAg7PMuP6DSdPoEnDRyIk4LzY7sAGly6i4Uge377cdo1nUBQLS5S4kKIc4xf8TUegb3G1Q==", "dev": true }, "@storybook/preview-api": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.0.0-beta.30.tgz", - "integrity": "sha512-3klBZJ3gC+B80vJvzvHDh4uHy8+SwNOttcKyOAJOt0IJTNYo2HiAn7rUhaMeHfKzoD/YGiFiRkTrPKJDZJAGUA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-7.0.12.tgz", + "integrity": "sha512-YI/AfHszIOYt967fsRlc7j6I0zZB+RSsBwD/nMA8y9vszdpQ0MgRhxHgQxFf6cgqbuQcdCsnTIpT0iQ4GHjDXg==", "dev": true, "requires": { - "@storybook/channel-postmessage": "7.0.0-beta.30", - "@storybook/channels": "7.0.0-beta.30", - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-events": "7.0.0-beta.30", - "@storybook/csf": "next", + "@storybook/channel-postmessage": "7.0.12", + "@storybook/channels": "7.0.12", + "@storybook/client-logger": "7.0.12", + "@storybook/core-events": "7.0.12", + "@storybook/csf": "^0.1.0", "@storybook/global": "^5.0.0", - "@storybook/types": "7.0.0-beta.30", + "@storybook/types": "7.0.12", "@types/qs": "^6.9.5", "dequal": "^2.0.2", "lodash": "^4.17.21", "memoizerific": "^1.11.3", "qs": "^6.10.0", - "slash": "^3.0.0", "synchronous-promise": "^2.0.15", "ts-dedent": "^2.0.0", "util-deprecate": "^1.0.2" } }, "@storybook/react": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.0.0-beta.30.tgz", - "integrity": "sha512-tcG+7vkf8/C2Az/Ei23DEfCx7sBqBi/odBEFIKYlZZkDTlkYWdTpcsn1P4fE/QFetwyS6F85aG3Qmluyk7YBQA==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-7.0.12.tgz", + "integrity": "sha512-dKHKc02LSgn3St7U/xj/Rr2DFLbS4dWQka+pS/AOvPPvMAR2gGHVhkmoFuFMf176hUTuE5MCoWBoNJIRMz7ZiQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-client": "7.0.0-beta.30", - "@storybook/docs-tools": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/core-client": "7.0.12", + "@storybook/docs-tools": "7.0.12", "@storybook/global": "^5.0.0", - "@storybook/preview-api": "7.0.0-beta.30", - "@storybook/types": "7.0.0-beta.30", + "@storybook/preview-api": "7.0.12", + "@storybook/react-dom-shim": "7.0.12", + "@storybook/types": "7.0.12", "@types/escodegen": "^0.0.6", "@types/estree": "^0.0.51", "@types/node": "^16.0.0", @@ -26341,23 +26764,17 @@ }, "dependencies": { "@types/node": { - "version": "16.18.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", - "integrity": "sha512-3oJbGBUWuS6ahSnEq1eN2XrCyf4YsWI8OyCvo7c64zQJNplk3mO84t53o8lfTk+2ji59g5ycfc6qQ3fdHliHuA==", - "dev": true - }, - "type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "version": "16.18.32", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.32.tgz", + "integrity": "sha512-zpnXe4dEz6PrWz9u7dqyRoq9VxwCvoXRPy/ewhmMa1CgEyVmtL1NJPQ2MX+4pf97vetquVKkpiMx0MwI8pjNOw==", "dev": true } } }, "@storybook/react-docgen-typescript-plugin": { - "version": "1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0", - "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.2-canary.6.9d540b91e815f8fc2f8829189deb00553559ff63.0.tgz", - "integrity": "sha512-eVg3BxlOm2P+chijHBTByr90IZVUtgRW56qEOLX7xlww2NBuKrcavBlcmn+HH7GIUktquWkMPtvy6e0W0NgA5w==", + "version": "1.0.6--canary.9.0c3f3b7.0", + "resolved": "https://registry.npmjs.org/@storybook/react-docgen-typescript-plugin/-/react-docgen-typescript-plugin-1.0.6--canary.9.0c3f3b7.0.tgz", + "integrity": "sha512-KUqXC3oa9JuQ0kZJLBhVdS4lOneKTOopnNBK4tUAgoxWQ3u/IjzdueZjFr7gyBrXMoU6duutk3RQR9u8ZpYJ4Q==", "dev": true, "requires": { "debug": "^4.1.1", @@ -26365,34 +26782,24 @@ "find-cache-dir": "^3.3.1", "flat-cache": "^3.0.4", "micromatch": "^4.0.2", - "react-docgen-typescript": "^2.1.1", + "react-docgen-typescript": "^2.2.2", "tslib": "^2.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, + "@storybook/react-dom-shim": { + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-7.0.12.tgz", + "integrity": "sha512-4z9J54TD7uphxPqSuLEzeKTV4oF8Fmv8qFfnT0XZJ2mpYTC2NTbkYoYZQ8N0eYzvNOk6xgfpDqBdmIANf4NaYw==", + "dev": true, + "requires": {} + }, "@storybook/router": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.0.0-beta.30.tgz", - "integrity": "sha512-hSdVv/IlBA96rf6RpmSCeS2CgxfmvgQOWVR8JR+5M97MjRMtXcIKB3f2ea8JSEPWkOa7i2k8ARunlAAVVmOiPw==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-7.0.12.tgz", + "integrity": "sha512-dOtBiCBGeDem86BCWR7AlTVQjoBk0yw/XZLXS9qcpUfpe+UDjd0Rh21ZdEEMHG1Wfu4d2AhhG5l/JSJ1IE83jQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", "memoizerific": "^1.11.3", "qs": "^6.10.0" } @@ -26447,27 +26854,27 @@ } }, "@storybook/store": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/store/-/store-7.0.0-beta.30.tgz", - "integrity": "sha512-Uzni6jW4cUee2i92jgMshRJh7AcBD79gUJpLz2HmKm7xXypi3TCzpUQi++8OAbfPgRkvk3sGwhcyrfkujJ1KqQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/store/-/store-7.0.12.tgz", + "integrity": "sha512-+gqs6y55fXp9vLrq9VyCGoAHbjfEBMZClkCNksPUBPoLRCY0knxGvhIOoDdcqHkHpm3AQGsfW/ESurbLj/Q76Q==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/preview-api": "7.0.0-beta.30" + "@storybook/client-logger": "7.0.12", + "@storybook/preview-api": "7.0.12" } }, "@storybook/telemetry": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.0.0-beta.30.tgz", - "integrity": "sha512-ufmdVxZoAiaIP5VWjbTRrruNTm6OXSvhjCYCpqBJIgMbvEosE5njNJ4ySuyZSjMtLvJy0kdnx7ca+bQQ5ALFuQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/telemetry/-/telemetry-7.0.12.tgz", + "integrity": "sha512-oxqe15bn5W+1pLpLjXTfj3H+YPZq3jExjdJwTCUHtFrrsNs0k6dyqAUk8qTOUqOTclANHb6vlNBFJDvZ6qbfEQ==", "dev": true, "requires": { - "@storybook/client-logger": "7.0.0-beta.30", - "@storybook/core-common": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", + "@storybook/core-common": "7.0.12", "chalk": "^4.1.0", "detect-package-manager": "^2.0.1", "fetch-retry": "^5.0.2", - "fs-extra": "^9.0.1", + "fs-extra": "^11.1.0", "isomorphic-unfetch": "^3.1.0", "nanoid": "^3.3.1", "read-pkg-up": "^7.0.1" @@ -26523,18 +26930,18 @@ }, "dependencies": { "@storybook/addons": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.15.tgz", - "integrity": "sha512-xT31SuSX+kYGyxCNK2nqL7WTxucs3rSmhiCLovJcUjYk+QquV3c2c53Ki7lwwdDbzfXFcNAe0HJ4hoTN4jhn0Q==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.16.tgz", + "integrity": "sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==", "dev": true, "requires": { - "@storybook/api": "6.5.15", - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/api": "6.5.16", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", - "@storybook/theming": "6.5.15", + "@storybook/router": "6.5.16", + "@storybook/theming": "6.5.16", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -26542,18 +26949,18 @@ } }, "@storybook/api": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.15.tgz", - "integrity": "sha512-BBE0KXKvj1/3jTghbIoWfrcDM0t+xO7EYtWWAXD6XlhGsZVD2Dy82Z52ONyLulMDRpMWl0OYy3h6A1YnFUH25w==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.16.tgz", + "integrity": "sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==", "dev": true, "requires": { - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", + "@storybook/router": "6.5.16", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -26567,9 +26974,9 @@ } }, "@storybook/channels": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.15.tgz", - "integrity": "sha512-gPpsBgirv2NCXbH4WbYqdkI0JLE96aiVuu7UEWfn9yu071pQ9CLHbhXGD9fSFNrfOkyBBY10ppSE7uCXw3Wexg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.16.tgz", + "integrity": "sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==", "dev": true, "requires": { "core-js": "^3.8.2", @@ -26578,9 +26985,9 @@ } }, "@storybook/client-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.15.tgz", - "integrity": "sha512-0uyxKvodq+FycGv6aUwC1wUR6suXf2+7ywMFAOlYolI4UvNj8NyU/5AfgKT5XnxYAgPmoCiAjOE700TrfHrosw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.16.tgz", + "integrity": "sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==", "dev": true, "requires": { "core-js": "^3.8.2", @@ -26588,9 +26995,9 @@ } }, "@storybook/core-events": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.15.tgz", - "integrity": "sha512-B1Ba6l5W7MeNclclqMMTMHgYgfdpB5SIhNCQFnzIz8blynzRhNFMdxvbAl6Je5G0S4xydYYd7Lno2kXQebs7HA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.16.tgz", + "integrity": "sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==", "dev": true, "requires": { "core-js": "^3.8.2" @@ -26606,25 +27013,25 @@ } }, "@storybook/instrumenter": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.15.tgz", - "integrity": "sha512-93WyH0s63RCv496eHjQ5dWFXoExXg9dlNMe7i4/FVVbWeDdb1pPVIHsLn28WxOiVQahQEAW2EA7Mao3BiBWg+A==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-6.5.16.tgz", + "integrity": "sha512-q8/GaBk8PA/cL7m5OW+ec5t63+Zja9YvYSPGXrYtW17koSv7OnNPmk6RvI7tIHHO0mODBYnaHjF4zQfEGoyR5Q==", "dev": true, "requires": { - "@storybook/addons": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/addons": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "core-js": "^3.8.2", "global": "^4.4.0" } }, "@storybook/router": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.15.tgz", - "integrity": "sha512-9t8rI8t7/Krolau29gsdjdbRQ66orONIyP0efp0EukVgv6reNFzb/U14ARrl0uHys6Tl5Xyece9FoakQUdn8Kg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.16.tgz", + "integrity": "sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==", "dev": true, "requires": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -26632,12 +27039,12 @@ } }, "@storybook/theming": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.15.tgz", - "integrity": "sha512-pgdW0lVZKKXQ4VhIfLHycMmwFSVOY7vLTKnytag4Y8Yz+aXm0bwDN/QxPntFzDH47F1Rcy2ywNnvty8ooDTvuA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.16.tgz", + "integrity": "sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==", "dev": true, "requires": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "regenerator-runtime": "^0.13.7" @@ -26662,43 +27069,41 @@ } }, "@storybook/theming": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.0.0-beta.30.tgz", - "integrity": "sha512-b3GM3vQfgAbmLvUaMPoAwYVynMAk7iH7H+ig9Dqv5/IJl8KIP7DTD5HAkP+PEzk+WrcOnw7mKDIk6Kt/lD0VWQ==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-7.0.12.tgz", + "integrity": "sha512-frBkvH7LF8j23ODaywLK4m4LLscw49oKblkZ+30QZkBAzRf2o3a/QSZW2V1zfBo7ygcXiUJ5bIjh7Y17mMJqbQ==", "dev": true, "requires": { "@emotion/use-insertion-effect-with-fallbacks": "^1.0.0", - "@storybook/client-logger": "7.0.0-beta.30", + "@storybook/client-logger": "7.0.12", "@storybook/global": "^5.0.0", "memoizerific": "^1.11.3" } }, "@storybook/types": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.0.0-beta.30.tgz", - "integrity": "sha512-udjSzDh8GPxpb0ITZqvooDv+khtyy1z1iNy/5VLOBhWe/vDWXC/mLHKPYlWdNthE9Vm3tJs61n8fTJBuPs2VZg==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/@storybook/types/-/types-7.0.12.tgz", + "integrity": "sha512-nlvU4MyO2grwPCRQ8alA3AnY1bQxGJ6A4QgJu+1MhtjVenifFlxOQX4H1OiA+YXfjlV096oO5LrxvetJPFAKKQ==", "dev": true, "requires": { - "@babel/core": "^7.12.10", - "@storybook/channels": "7.0.0-beta.30", + "@storybook/channels": "7.0.12", "@types/babel__core": "^7.0.0", "@types/express": "^4.7.0", - "express": "^4.17.3", "file-system-cache": "^2.0.0" } }, "@stripe/react-stripe-js": { - "version": "1.16.3", - "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.16.3.tgz", - "integrity": "sha512-gS6UDGEuM92K50pFB3o//EqqPxmaqpC8IrsBda4P4LxeULoO0pBFSHXJ5Ab6uA7G2lyO2bluvSLereh0OH9GrQ==", + "version": "1.16.5", + "resolved": "https://registry.npmjs.org/@stripe/react-stripe-js/-/react-stripe-js-1.16.5.tgz", + "integrity": "sha512-lVPW3IfwdacyS22pP+nBB6/GNFRRhT/4jfgAK6T2guQmtzPwJV1DogiGGaBNhiKtSY18+yS8KlHSu+PvZNclvQ==", "requires": { "prop-types": "^15.7.2" } }, "@stripe/stripe-js": { - "version": "1.46.0", - "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.46.0.tgz", - "integrity": "sha512-dkm0zCEoRLu5rTnsIgwDf/QG2DKcalOT2dk1IVgMySOHWTChLyOvQwMYhEduGgLvyYWTwNhAUV4WOLPQvjwLwA==" + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/@stripe/stripe-js/-/stripe-js-1.53.0.tgz", + "integrity": "sha512-qhhAa5WxlgVqh1J41ppyqqQVu6S1T1Q9lDAk2Ho9eI/GjrkMvAHcJpKqhekJRsZ1vjsK4P68PYOcXBXPyNCpnQ==" }, "@swc/helpers": { "version": "0.4.11", @@ -26709,9 +27114,9 @@ } }, "@tailwindcss/typography": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.7.tgz", - "integrity": "sha512-JTTSTrgZfp6Ki4svhPA4mkd9nmQ/j9EfE7SbHJ1cLtthKkpW2OxsFXzSmxbhYbEkfNIyAyhle5p4SYyKRbz/jg==", + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.9.tgz", + "integrity": "sha512-t8Sg3DyynFysV9f4JDOVISGsjazNb48AeIYQwcL+Bsq5uf4RYL75C1giZ43KISjeDGBaTN3Kxh7Xj/vRSMJUUg==", "dev": true, "requires": { "lodash.castarray": "^4.4.0", @@ -26721,16 +27126,16 @@ } }, "@tanstack/query-core": { - "version": "4.22.4", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.22.4.tgz", - "integrity": "sha512-t79CMwlbBnj+yL82tEcmRN93bL4U3pae2ota4t5NN2z3cIeWw74pzdWrKRwOfTvLcd+b30tC+ciDlfYOKFPGUw==" + "version": "4.29.7", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-4.29.7.tgz", + "integrity": "sha512-GXG4b5hV2Loir+h2G+RXhJdoZhJLnrBWsuLB2r0qBRyhWuXq9w/dWxzvpP89H0UARlH6Mr9DiVj4SMtpkF/aUA==" }, "@tanstack/react-query": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.23.0.tgz", - "integrity": "sha512-cfQsrecZQjYYueiow4WcK8ItokXJnv+b2OrK8Lf5kF7lM9uCo1ilyygFB8wo4MfxchUBVM6Cs8wq4Ed7fouwkA==", + "version": "4.29.7", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-4.29.7.tgz", + "integrity": "sha512-ijBWEzAIo09fB1yd22slRZzprrZ5zMdWYzBnCg5qiXuFbH78uGN1qtGz8+Ed4MuhaPaYSD+hykn+QEKtQviEtg==", "requires": { - "@tanstack/query-core": "4.22.4", + "@tanstack/query-core": "4.29.7", "use-sync-external-store": "^1.2.0" } }, @@ -26807,13 +27212,13 @@ "dev": true }, "@types/babel__core": { - "version": "7.1.20", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.20.tgz", - "integrity": "sha512-PVb6Bg2QuscZ30FvOU7z4guG6c926D9YRvOxEaelzndpMsvP+YM74Q/dAFASpg2l6+XLalxSGxcq/lrgYWZtyQ==", + "version": "7.20.0", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.0.tgz", + "integrity": "sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==", "dev": true, "requires": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0", + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" @@ -26839,9 +27244,9 @@ } }, "@types/babel__traverse": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.3.tgz", - "integrity": "sha512-1kbcJ40lLB7MHsj39U4Sh1uTd2E7rLEa79kmDpI6cy+XiXsteB3POdQomoq4FxszMrO3ZYchkhYJw7A2862b3w==", + "version": "7.18.5", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.18.5.tgz", + "integrity": "sha512-enCvTL8m/EHS/zIvJno9nE+ndYPh1/oNFzRYRmtUqJICG2VnCSBzMLW5VN2KCQU91f23tsNKR8v7VJJQMatl7Q==", "dev": true, "requires": { "@babel/types": "^7.3.0" @@ -26887,9 +27292,9 @@ "dev": true }, "@types/ejs": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.1.tgz", - "integrity": "sha512-RQul5wEfY7BjWm0sYY86cmUN/pcXWGyVxWX93DFFJvcrxax5zKlieLwA3T77xJGwNcZW0YW6CYG70p1m8xPFmA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz", + "integrity": "sha512-ZmiaE3wglXVWBM9fyVC17aGPkLo/UgaOjEiI2FXQfyczrCefORPxIe+2dVmnmk3zkVIbizjrlQzmPGhSYGXG5g==", "dev": true }, "@types/escodegen": { @@ -26899,9 +27304,9 @@ "dev": true }, "@types/eslint": { - "version": "8.4.10", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz", - "integrity": "sha512-Sl/HOqN8NKPmhWo2VBEPm0nvHnu2LL3v9vKo8MEq0EtbJ4eVzGPl41VNPvn5E1i5poMk4/XD8UriLHpJvEP/Nw==", + "version": "8.37.0", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.37.0.tgz", + "integrity": "sha512-Piet7dG2JBuDIfohBngQ3rCt7MgO9xCO4xIMKxBThCq5PNRB91IjlJ10eJVwfoNtvTErmxLzwBZ7rHZtbOMmFQ==", "dev": true, "requires": { "@types/estree": "*", @@ -26925,26 +27330,27 @@ "dev": true }, "@types/express": { - "version": "4.17.15", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz", - "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==", + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", "dev": true, "requires": { "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.31", + "@types/express-serve-static-core": "^4.17.33", "@types/qs": "*", "@types/serve-static": "*" } }, "@types/express-serve-static-core": { - "version": "4.17.32", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.32.tgz", - "integrity": "sha512-aI5h/VOkxOF2Z1saPy0Zsxs5avets/iaiAJYznQFm5By/pamU31xWKL//epiF4OfUA2qTOc9PV6tCUjhO8wlZA==", + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", "dev": true, "requires": { "@types/node": "*", "@types/qs": "*", - "@types/range-parser": "*" + "@types/range-parser": "*", + "@types/send": "*" } }, "@types/find-cache-dir": { @@ -26953,6 +27359,16 @@ "integrity": "sha512-frsJrz2t/CeGifcu/6uRo4b+SzAwT4NYCVPu1GN8IB9XTzrpPkGuV0tmh9mN+/L0PklAlsC3u5Fxt0ju00LXIw==", "dev": true }, + "@types/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-IO+MJPVhoqz+28h1qLAcBEH2+xHMK6MTyHJc7MTnnYb6wsoLR29POVGJ7LycmVXIqyy/4/2ShP5sUwTXuOwb/w==", + "dev": true, + "requires": { + "@types/minimatch": "^5.1.2", + "@types/node": "*" + } + }, "@types/graceful-fs": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz", @@ -27034,33 +27450,28 @@ "dev": true }, "@types/lodash": { - "version": "4.14.191", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.191.tgz", - "integrity": "sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ==" + "version": "4.14.194", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.194.tgz", + "integrity": "sha512-r22s9tAS7imvBt2lyHC9B8AGwWnXaYb1tY09oyLkXDs4vArpYJzw09nj8MLx5VfciBPGIb+ZwG0ssYnEPJxn/g==" }, "@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", "requires": { "@types/unist": "*" } }, - "@types/mdurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/mdurl/-/mdurl-1.0.2.tgz", - "integrity": "sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==" - }, "@types/mdx": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.3.tgz", - "integrity": "sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.5.tgz", + "integrity": "sha512-76CqzuD6Q7LC+AtbPqrvD9AqsN0k8bsYo2bM2J8pmNldP1aIPAbzUQ7QbobyXL4eLr1wK5x8FZFe8eF/ubRuBg==", "dev": true }, "@types/mime": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", - "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", "dev": true }, "@types/mime-types": { @@ -27069,6 +27480,12 @@ "integrity": "sha512-vXOTGVSLR2jMw440moWTC7H19iUyLtP3Z1YTj7cSsubOICinjMxFeb/V57v9QdyyPGbbWolUFSSmSiRSn94tFw==", "dev": true }, + "@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true + }, "@types/ms": { "version": "0.7.31", "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", @@ -27081,9 +27498,9 @@ "dev": true }, "@types/node-fetch": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.2.tgz", - "integrity": "sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A==", + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", + "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", "dev": true, "requires": { "@types/node": "*", @@ -27150,9 +27567,9 @@ "dev": true }, "@types/react": { - "version": "18.0.26", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.26.tgz", - "integrity": "sha512-hCR3PJQsAIXyxhTNSiDFY//LhnMZWpNNr5etoCqx/iUfGc5gXWtQR2Phl908jVR6uPXacojQWTg4qRpkxTuGug==", + "version": "18.2.6", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.6.tgz", + "integrity": "sha512-wRZClXn//zxCFW+ye/D2qY65UsYP1Fpex2YXorHc8awoNamkMZSvBxwxdYVInsHOZZd2Ppq8isnSzJL5Mpf8OA==", "requires": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -27160,9 +27577,9 @@ } }, "@types/react-redux": { - "version": "7.1.24", - "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.24.tgz", - "integrity": "sha512-7FkurKcS1k0FHZEtdbbgN8Oc6b+stGSfZYjQGicofJ0j4U0qIn/jaSvnP2pLwZKiai3/17xqqxkkrxTgN8UNbQ==", + "version": "7.1.25", + "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.25.tgz", + "integrity": "sha512-bAGh4e+w5D8dajd6InASVIyCo4pZLJ66oLb80F9OBLO1gKESbZcRCJpTT6uLXX+HAB57zw1WTdwJdAsewuTweg==", "requires": { "@types/hoist-non-react-statics": "^3.3.0", "@types/react": "*", @@ -27171,20 +27588,30 @@ } }, "@types/scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "version": "0.16.3", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.3.tgz", + "integrity": "sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==" }, "@types/semver": { - "version": "7.3.13", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", - "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.0.tgz", + "integrity": "sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw==", "dev": true }, + "@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "requires": { + "@types/mime": "^1", + "@types/node": "*" + } + }, "@types/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-z5xyF6uh8CbjAu9760KDKsH2FcDxZ2tFCsA4HIMWE6IkiYMXfVoa+4f9KX+FN0ZLsaMw1WNG2ETLA6N+/YA+cg==", + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.1.tgz", + "integrity": "sha512-NUo5XNiAdULrJENtJXZZ3fHtfMolzZwczzBbnAeBbqBwG+LaG6YaJtuwzwGSQZ2wsCrxjEhNNjAkKigy3n8teQ==", "dev": true, "requires": { "@types/mime": "*", @@ -27213,9 +27640,9 @@ "dev": true }, "@types/yargs": { - "version": "17.0.19", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.19.tgz", - "integrity": "sha512-cAx3qamwaYX9R0fzOIZAlFpo4A+1uBVCxqpKz9D26uTF4srRXaGTTsikQmaotCtNdbhzyUH7ft6p9ktz9s6UNQ==", + "version": "17.0.24", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", + "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==", "dev": true, "requires": { "@types/yargs-parser": "*" @@ -27228,178 +27655,97 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.48.1.tgz", - "integrity": "sha512-9nY5K1Rp2ppmpb9s9S2aBiF3xo5uExCehMDmYmmFqqyxgenbHJ3qbarcLt4ITgaD6r/2ypdlcFRdcuVPnks+fQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.6.tgz", + "integrity": "sha512-sXtOgJNEuRU5RLwPUb1jxtToZbgvq3M6FPpY4QENxoOggK+UpTxUBpj6tD8+Qh2g46Pi9We87E+eHnUw8YcGsw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.48.1", - "@typescript-eslint/type-utils": "5.48.1", - "@typescript-eslint/utils": "5.48.1", + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/type-utils": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", + "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", "natural-compare-lite": "^1.4.0", - "regexpp": "^3.2.0", "semver": "^7.3.7", "tsutils": "^3.21.0" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", - "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1" + "yallist": "^4.0.0" } }, - "@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true - }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" + "lru-cache": "^6.0.0" } }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "@typescript-eslint/parser": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.45.0.tgz", - "integrity": "sha512-brvs/WSM4fKUmF5Ot/gEve6qYiCMjm6w4HkHPfS6ZNmxTS0m0iNN4yOChImaCkqc1hRwFGqUyanMXuGal6oyyQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.6.tgz", + "integrity": "sha512-7pCa6al03Pv1yf/dUg/s1pXz/yGMUBAw5EeWqNTFiSueKvRNonze3hma3lhdsOrQcaOXhbk5gKu2Fludiho9VA==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.45.0", - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/typescript-estree": "5.45.0", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "debug": "^4.3.4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "@typescript-eslint/scope-manager": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.45.0.tgz", - "integrity": "sha512-noDMjr87Arp/PuVrtvN3dXiJstQR1+XlQ4R1EvzG+NMgXi8CuMCXpb8JqNtFHKceVSQ985BZhfRdowJzbv4yKw==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.6.tgz", + "integrity": "sha512-gLbY3Le9Dxcb8KdpF0+SJr6EQ+hFGYFl6tVY8VxLPFDfUZC7BHFw+Vq7bM5lE9DwWPfx4vMWWTLGXgpc0mAYyQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/visitor-keys": "5.45.0" + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6" } }, "@typescript-eslint/type-utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.48.1.tgz", - "integrity": "sha512-Hyr8HU8Alcuva1ppmqSYtM/Gp0q4JOp1F+/JH5D1IZm/bUBrV0edoewQZiEc1r6I8L4JL21broddxK8HAcZiqQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.6.tgz", + "integrity": "sha512-A4tms2Mp5yNvLDlySF+kAThV9VTBPCvGf0Rp8nl/eoDX9Okun8byTKoj3fJ52IJitjWOk0fKPNQhXEB++eNozQ==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.48.1", - "@typescript-eslint/utils": "5.48.1", + "@typescript-eslint/typescript-estree": "5.59.6", + "@typescript-eslint/utils": "5.59.6", "debug": "^4.3.4", "tsutils": "^3.21.0" - }, - "dependencies": { - "@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", - "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "@typescript-eslint/types": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.45.0.tgz", - "integrity": "sha512-QQij+u/vgskA66azc9dCmx+rev79PzX8uDHpsqSjEFtfF2gBUTRCpvYMh2gw2ghkJabNkPlSUCimsyBEQZd1DA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.6.tgz", + "integrity": "sha512-tH5lBXZI7T2MOUgOWFdVNUILsI02shyQvfzG9EJkoONWugCG77NDDa1EeDGw7oJ5IvsTAAGVV8I3Tk2PNu9QfA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.45.0.tgz", - "integrity": "sha512-maRhLGSzqUpFcZgXxg1qc/+H0bT36lHK4APhp0AEUVrpSwXiRAomm/JGjSG+kNUio5kAa3uekCYu/47cnGn5EQ==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.6.tgz", + "integrity": "sha512-vW6JP3lMAs/Tq4KjdI/RiHaaJSO7IUsbkz17it/Rl9Q+WkQ77EOuOnlbaU8kKfVIOJxMhnRiBG+olE7f3M16DA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.45.0", - "@typescript-eslint/visitor-keys": "5.45.0", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/visitor-keys": "5.59.6", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -27407,266 +27753,227 @@ "tsutils": "^3.21.0" }, "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "ms": "2.1.2" + "yallist": "^4.0.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "@typescript-eslint/utils": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.48.1.tgz", - "integrity": "sha512-SmQuSrCGUOdmGMwivW14Z0Lj8dxG1mOFZ7soeJ0TQZEJcs3n5Ndgkg0A4bcMFzBELqLJ6GTHnEU+iIoaD6hFGA==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.6.tgz", + "integrity": "sha512-vzaaD6EXbTS29cVH0JjXBdzMt6VBlv+hE31XktDRMX1j3462wZCJa7VzO2AxXEXcIl8GQqZPcOPuW/Z1tZVogg==", "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.48.1", - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/typescript-estree": "5.48.1", + "@typescript-eslint/scope-manager": "5.59.6", + "@typescript-eslint/types": "5.59.6", + "@typescript-eslint/typescript-estree": "5.59.6", "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0", "semver": "^7.3.7" }, "dependencies": { - "@typescript-eslint/scope-manager": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.48.1.tgz", - "integrity": "sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==", + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1" + "yallist": "^4.0.0" } }, - "@typescript-eslint/types": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.48.1.tgz", - "integrity": "sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.48.1.tgz", - "integrity": "sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==", + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { - "@typescript-eslint/types": "5.48.1", - "@typescript-eslint/visitor-keys": "5.48.1", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" + "lru-cache": "^6.0.0" } }, - "@typescript-eslint/visitor-keys": { - "version": "5.48.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.48.1.tgz", - "integrity": "sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.48.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, "@typescript-eslint/visitor-keys": { - "version": "5.45.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.45.0.tgz", - "integrity": "sha512-jc6Eccbn2RtQPr1s7th6jJWQHBHI6GBVQkCHoJFQ5UreaKm59Vxw+ynQUPPY2u2Amquc+7tmEoC2G52ApsGNNg==", + "version": "5.59.6", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.6.tgz", + "integrity": "sha512-zEfbFLzB9ETcEJ4HZEEsCR9HHeNku5/Qw1jSS5McYJv5BR+ftYXwFFAH5Al+xkGaZEqowMwl7uoJjQb1YSPF8Q==", "dev": true, "requires": { - "@typescript-eslint/types": "5.45.0", + "@typescript-eslint/types": "5.59.6", "eslint-visitor-keys": "^3.3.0" } }, "@webassemblyjs/ast": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", - "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dev": true, "requires": { - "@webassemblyjs/helper-numbers": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "@webassemblyjs/floating-point-hex-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", - "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true }, "@webassemblyjs/helper-api-error": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", - "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true }, "@webassemblyjs/helper-buffer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", - "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==", "dev": true }, "@webassemblyjs/helper-numbers": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", - "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", - "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true }, "@webassemblyjs/helper-wasm-section": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", - "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "@webassemblyjs/ieee754": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", - "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "requires": { "@xtuc/ieee754": "^1.2.0" } }, "@webassemblyjs/leb128": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", - "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "requires": { "@xtuc/long": "4.2.2" } }, "@webassemblyjs/utf8": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", - "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true }, "@webassemblyjs/wasm-edit": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", - "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/helper-wasm-section": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-opt": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", - "@webassemblyjs/wast-printer": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "@webassemblyjs/wasm-gen": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", - "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wasm-opt": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", - "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-buffer": "1.11.1", - "@webassemblyjs/wasm-gen": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "@webassemblyjs/wasm-parser": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", - "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/helper-api-error": "1.11.1", - "@webassemblyjs/helper-wasm-bytecode": "1.11.1", - "@webassemblyjs/ieee754": "1.11.1", - "@webassemblyjs/leb128": "1.11.1", - "@webassemblyjs/utf8": "1.11.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "@webassemblyjs/wast-printer": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", - "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dev": true, "requires": { - "@webassemblyjs/ast": "1.11.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -27772,23 +28079,6 @@ "dev": true, "requires": { "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "aggregate-error": { @@ -27894,9 +28184,9 @@ } }, "anymatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", - "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, "requires": { "normalize-path": "^3.0.0", @@ -27923,6 +28213,28 @@ "requires": { "delegates": "^1.0.0", "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "arg": { @@ -27945,9 +28257,9 @@ } }, "aria-hidden": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.2.tgz", - "integrity": "sha512-6y/ogyDTk/7YAe91T3E2PR1ALVKyM2QbTio5HwM+N1Q6CMlCKhvClyIjkckBswa0f2xJhjsfzIGa1yVSe1UMVA==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz", + "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==", "requires": { "tslib": "^2.0.0" } @@ -27961,23 +28273,15 @@ "deep-equal": "^2.0.5" } }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==", - "dev": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==", - "dev": true + "array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + } }, "array-flatten": { "version": "1.1.1", @@ -28004,12 +28308,6 @@ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==", - "dev": true - }, "array.prototype.flat": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", @@ -28059,12 +28357,6 @@ "util": "^0.12.0" } }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==", - "dev": true - }, "ast-types": { "version": "0.14.2", "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.14.2.tgz", @@ -28097,25 +28389,19 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, "atob": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==" }, "autoprefixer": { - "version": "10.4.8", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.8.tgz", - "integrity": "sha512-75Jr6Q/XpTqEf6D2ltS5uMewJIx5irCU1oBYJrWjFenq/m12WRRrz6g15L1EIoYvPLXTbEry7rDOwrcYNj77xw==", + "version": "10.4.14", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", + "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==", "dev": true, "requires": { - "browserslist": "^4.21.3", - "caniuse-lite": "^1.0.30001373", + "browserslist": "^4.21.5", + "caniuse-lite": "^1.0.30001464", "fraction.js": "^4.2.0", "normalize-range": "^0.1.2", "picocolors": "^1.0.0", @@ -28129,9 +28415,9 @@ "dev": true }, "axe-core": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.6.2.tgz", - "integrity": "sha512-b1WlTV8+XKLj9gZy2DZXgQiyDp9xkkoe2a6U6UbYccScq2wgH/YwCeI2/Jq2mgo0HzQxqJOjWZBLeA/mqsk5Mg==", + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.1.tgz", + "integrity": "sha512-sCXXUhA+cljomZ3ZAwb8i1p3oOlkABzPy08ZDAoGcYuvtBPlQ1Ytde129ArXyHWDhfeewq7rlx9F+cUx2SSlkg==", "dev": true }, "axios": { @@ -28203,15 +28489,15 @@ "dev": true }, "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", + "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" } } } @@ -28260,14 +28546,6 @@ "@babel/compat-data": "^7.17.7", "@babel/helper-define-polyfill-provider": "^0.3.3", "semver": "^6.1.1" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "babel-plugin-polyfill-corejs3": { @@ -28301,15 +28579,15 @@ } }, "babel-plugin-styled-components": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.0.7.tgz", - "integrity": "sha512-i7YhvPgVqRKfoQ66toiZ06jPNA3p6ierpfUuEWxNF+fV27Uv5gxBkf8KZLHUCc1nFA9j6+80pYoIpqCeyW3/bA==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.3.tgz", + "integrity": "sha512-jBioLwBVHpOMU4NsueH/ADcHrjS0Y/WTpt2eGVmmuSFNEv2DF3XhcMncuZlbbjxQ4vzxg+yEr6E6TNjrIQbsJQ==", "requires": { - "@babel/helper-annotate-as-pure": "^7.16.0", - "@babel/helper-module-imports": "^7.16.0", + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-module-imports": "^7.21.4", "babel-plugin-syntax-jsx": "^6.18.0", - "lodash": "^4.17.11", - "picomatch": "^2.3.0" + "lodash": "^4.17.21", + "picomatch": "^2.3.1" } }, "babel-plugin-syntax-jsx": { @@ -28328,38 +28606,6 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, "base64-arraybuffer": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", @@ -28428,6 +28674,26 @@ "buffer": "^5.5.0", "inherits": "^2.0.4", "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "body-parser": { @@ -28448,6 +28714,32 @@ "raw-body": "2.5.1", "type-is": "~1.6.18", "unpipe": "1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } } }, "boolbase": { @@ -28511,6 +28803,12 @@ "requires": { "has-flag": "^4.0.0" } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true } } }, @@ -28548,15 +28846,25 @@ "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", "dev": true }, - "browserslist": { - "version": "4.21.4", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.4.tgz", - "integrity": "sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==", + "browserify-zlib": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.1.4.tgz", + "integrity": "sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==", + "dev": true, "requires": { - "caniuse-lite": "^1.0.30001400", - "electron-to-chromium": "^1.4.251", - "node-releases": "^2.0.6", - "update-browserslist-db": "^1.0.9" + "pako": "~0.2.0" + } + }, + "browserslist": { + "version": "4.21.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", + "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001449", + "electron-to-chromium": "^1.4.284", + "node-releases": "^2.0.8", + "update-browserslist-db": "^1.0.10" } }, "bser": { @@ -28593,6 +28901,15 @@ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==" }, + "bundle-name": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-3.0.0.tgz", + "integrity": "sha512-PKA4BeSvBpQKQ8iPOGCSiell+N8P+Tf1DlwqmYhpe2gAhKPHn8EYOxVT+ShuGmhg8lN8XiSlS80yiExKXrURlw==", + "dev": true, + "requires": { + "run-applescript": "^5.0.0" + } + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -28600,9 +28917,9 @@ "dev": true }, "c8": { - "version": "7.12.0", - "resolved": "https://registry.npmjs.org/c8/-/c8-7.12.0.tgz", - "integrity": "sha512-CtgQrHOkyxr5koX1wEUmN/5cfDa2ckbHRA4Gy5LAL0zaCFtVWJS5++n+w4/sr2GWGerBxgTjpKeDclk/Qk6W/A==", + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/c8/-/c8-7.13.0.tgz", + "integrity": "sha512-/NL4hQTv1gBL6J6ei80zu3IiTrmePDKXKXOTLpHvcIWZTVYQlDhVWjjWvkhICylE8EwwnMVzDZugCvdx0/DIIA==", "dev": true, "requires": { "@bcoe/v8-coverage": "^0.2.3", @@ -28619,31 +28936,6 @@ "yargs-parser": "^20.2.9" } }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, "call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -28682,14 +28974,14 @@ "dev": true }, "camelize": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", - "integrity": "sha512-W2lPwkBkMZwFlPCXhIlYgxu+7gC/NUlCtdK652DAJ1JdgV0sTrvuPFshNPrFa1TY2JOkLhgdeEBplB4ezEa+xg==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz", + "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==" }, "caniuse-lite": { - "version": "1.0.30001418", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001418.tgz", - "integrity": "sha512-oIs7+JL3K9JRQ3jPZjlH6qyYDp+nBTCais7hjh0s+fuBwufc7uZ7hPYMXrDOJhV360KGMTcczMRObk0/iMqZRg==" + "version": "1.0.30001489", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001489.tgz", + "integrity": "sha512-x1mgZEXK8jHIfAxm+xgdpHpk50IN3z3q3zP261/WS+uvePxW8izXuCu6AHz0lkuYTlATDehiZ/tNyYBdSQsOUQ==" }, "canvg": { "version": "3.0.10", @@ -28721,6 +29013,13 @@ "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + } } }, "character-entities": { @@ -28756,9 +29055,10 @@ } }, "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "dev": true }, "chrome-trace-event": { "version": "1.0.3", @@ -28767,9 +29067,9 @@ "dev": true }, "ci-info": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.7.1.tgz", - "integrity": "sha512-4jYS4MOAaCIStSRwiuxc4B8MYhIe676yO1sYGzARnjXkWpmzZMMYxY6zu8WYWDhSuth5zhrQ1rhNSibyyvv4/w==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", + "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", "dev": true }, "cipher-base": { @@ -28781,107 +29081,15 @@ "safe-buffer": "^5.0.1" } }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "classnames": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.1.tgz", - "integrity": "sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==" + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz", + "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==" }, "clean-css": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.1.tgz", - "integrity": "sha512-lCr8OHhiWCTw4v8POJovCoh4T7I9U11yVsPjMWWnnMmp9ZowCxyad1Pathle/9HjaDp+fdQKjO9fQydE6RHTZg==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", + "integrity": "sha512-JVJbM+f3d3Q704rF4bqQ5UUyTtuJ0JRKNbTKVEeujCCBoMdkEi+V+e8oktO9qGQNSvHrFTM6JZRXrUvGR1czww==", "dev": true, "requires": { "source-map": "~0.6.0" @@ -28966,16 +29174,6 @@ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, "color": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", @@ -29014,9 +29212,9 @@ "dev": true }, "colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true }, "combined-stream": { @@ -29028,9 +29226,9 @@ } }, "comma-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.2.tgz", - "integrity": "sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==" + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", + "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==" }, "commander": { "version": "8.3.0", @@ -29050,12 +29248,6 @@ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true - }, "compressible": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", @@ -29086,6 +29278,21 @@ "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "dev": true }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -29118,10 +29325,16 @@ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "requires": { "core-util-is": "~1.0.0", @@ -29172,25 +29385,15 @@ } }, "content-type": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", - "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", "dev": true }, "convert-source-map": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz", - "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==", - "requires": { - "safe-buffer": "~5.1.1" - }, - "dependencies": { - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" - } - } + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==" }, "cookie": { "version": "0.5.0", @@ -29213,30 +29416,25 @@ "keygrip": "~1.1.0" } }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==", - "dev": true - }, "core-js": { - "version": "3.26.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.0.tgz", - "integrity": "sha512-+DkDrhoR4Y0PxDz6rurahuB+I45OsEUv8E1maPTB6OuHRohMMcznBq9TMpdpDMm/hUPob/mJJS3PqgbHpMTQgw==" + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.30.2.tgz", + "integrity": "sha512-uBJiDmwqsbJCWHAwjrx3cvjbMXP7xD72Dmsn5LOJpiRmE3WbBbN5rCqQ2Qh6Ek6/eOrjlWngEynBWo4VxerQhg==", + "devOptional": true }, "core-js-compat": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.27.1.tgz", - "integrity": "sha512-Dg91JFeCDA17FKnneN7oCMz4BkQ4TcffkgHP4OWwp9yx3pi7ubqMDXXSacfNak1PQqjc95skyt+YBLHQJnkJwA==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.2.tgz", + "integrity": "sha512-nriW1nuJjUgvkEjIot1Spwakz52V9YkYHZAQG6A1eCgC8AA1p0zngrQEP9R0+V6hji5XilWKG1Bd0YRppmGimA==", "dev": true, "requires": { - "browserslist": "^4.21.4" + "browserslist": "^4.21.5" } }, "core-js-pure": { - "version": "3.27.1", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.27.1.tgz", - "integrity": "sha512-BS2NHgwwUppfeoqOXqi08mUqS5FiZpuRuJJpKsaME7kJz0xxuk0xkhDdfMIlP/zLa80krBqss1LtD7f889heAw==", + "version": "3.30.2", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.30.2.tgz", + "integrity": "sha512-p/npFUJXXBkCCTIlEGBdghofn00jWG6ZOtdoIXSJmAu2QBvN0IqpZXWweOytcwE6cfx8ZvVUy1vw8zxhe4Y2vg==", "dev": true }, "core-util-is": { @@ -29245,9 +29443,9 @@ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "requires": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -29275,6 +29473,14 @@ "sha.js": "^2.4.0" } }, + "cross-fetch": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", + "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", + "requires": { + "node-fetch": "^2.6.11" + } + }, "cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", @@ -29315,31 +29521,78 @@ } }, "css-loader": { - "version": "6.7.3", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.3.tgz", - "integrity": "sha512-qhOH1KlBMnZP8FzRO6YCH9UHXQhVMcEGLyNdb7Hv2cpcmJbW0YrddO+tG1ab5nT41KpHIYGsbeHqxB9xPu1pKQ==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", "dev": true, "requires": { - "icss-utils": "^5.1.0", - "postcss": "^8.4.19", - "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.0", - "postcss-modules-scope": "^3.0.0", - "postcss-modules-values": "^4.0.0", - "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" }, "dependencies": { - "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "minimist": "^1.2.0" } + }, + "loader-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz", + "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + } + }, + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, @@ -29357,9 +29610,9 @@ } }, "css-to-react-native": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", - "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz", + "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==", "requires": { "camelize": "^1.0.0", "css-color-keywords": "^1.0.0", @@ -29379,9 +29632,9 @@ "dev": true }, "csstype": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.0.tgz", - "integrity": "sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA==" + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==" }, "cva": { "version": "npm:class-variance-authority@0.4.0", @@ -29396,11 +29649,11 @@ "dev": true }, "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "2.0.0" + "ms": "2.1.2" } }, "decode-named-character-reference": { @@ -29431,16 +29684,17 @@ "dev": true }, "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", + "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", "dev": true, "requires": { + "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", + "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", @@ -29448,25 +29702,11 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.0", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", "which-typed-array": "^1.1.9" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, "deep-extend": { @@ -29481,11 +29721,90 @@ "dev": true }, "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", "dev": true }, + "default-browser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", + "integrity": "sha512-wX5pXO1+BrhMkSbROFsyxUm0i/cJEScyNhA4PPxc41ICuv05ZZB/MX28s8aZx6xjmatvebIapF6hLEKEcpneUA==", + "dev": true, + "requires": { + "bundle-name": "^3.0.0", + "default-browser-id": "^3.0.0", + "execa": "^7.1.1", + "titleize": "^3.0.0" + }, + "dependencies": { + "execa": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.1.1.tgz", + "integrity": "sha512-wH0eMf/UXckdUYnO21+HDztteVv05rq2GXksxT4fCGeHkBhw1DROXh40wcjMcRqDOWE7iPJ4n3M7e2+YFP+76Q==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + } + }, + "human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true + }, + "is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true + }, + "mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true + }, + "npm-run-path": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", + "integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==", + "dev": true, + "requires": { + "path-key": "^4.0.0" + } + }, + "onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "requires": { + "mimic-fn": "^4.0.0" + } + }, + "path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true + }, + "strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true + } + } + }, "default-browser-id": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-3.0.0.tgz", @@ -29503,51 +29822,25 @@ "dev": true }, "define-properties": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", - "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", + "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", "dev": true, "requires": { "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } } }, "defined": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz", - "integrity": "sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz", + "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==", "dev": true }, "defu": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.1.tgz", - "integrity": "sha512-aA964RUCsBt0FGoNIlA3uFgo2hO+WWC0fiC6DBps/0SFzkKcYoM/3CzVLIa5xSsrFjdioMdYgAIbwo80qp2MoA==", + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.2.tgz", + "integrity": "sha512-+uO4+qr7msjNNWKYPHqN/3+Dx3NFkmIzayk2L1MyZQlvgZb/J1A0fo410dpKrN2SnqFjt8n4JL8fDJE0wIgjFQ==", "dev": true }, "del": { @@ -29631,23 +29924,6 @@ "requires": { "address": "^1.0.1", "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "detective": { @@ -29697,9 +29973,9 @@ } }, "dom-accessibility-api": { - "version": "0.5.15", - "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.15.tgz", - "integrity": "sha512-8o+oVqLQZoruQPYy3uAAQtc6YbtSiRq5aPJBhJ82YTJRHvI6ofhYAkC81WmjFTnfUbqg6T3aCglIpU9p/5e7Cw==", + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", + "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, "dom-converter": { @@ -29752,9 +30028,9 @@ } }, "dompurify": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.1.tgz", - "integrity": "sha512-ewwFzHzrrneRjxzmK6oVz/rZn9VWspGFRDb4/rRtIsM1n36t9AKma/ye8syCpcw+XJ25kOK/hOG7t1j2I2yBqA==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.4.5.tgz", + "integrity": "sha512-jggCCd+8Iqp4Tsz0nIvpcb22InKEBrGz5dw3EQJMs8HPJDsKbFIO3STYtAvCfDx26Muevn1MHVI0XxjgFfmiSA==", "optional": true }, "domutils": { @@ -29779,15 +30055,14 @@ } }, "dotenv": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", - "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", - "dev": true + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==" }, "dotenv-expand": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", - "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-10.0.0.tgz", + "integrity": "sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A==", "dev": true }, "duplexer2": { @@ -29798,10 +30073,15 @@ "readable-stream": "^2.0.2" }, "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "requires": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -29827,6 +30107,56 @@ } } }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -29834,18 +30164,19 @@ "dev": true }, "ejs": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.8.tgz", - "integrity": "sha512-/sXZeMlhS0ArkfX2Aw780gJzXSMPnKjtspYZv+f3NiKLlubezAHDU5+9xz6gd3/NhG3txQCo6xlglmTS+oTGEQ==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.9.tgz", + "integrity": "sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==", "dev": true, "requires": { "jake": "^10.8.5" } }, "electron-to-chromium": { - "version": "1.4.284", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz", - "integrity": "sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA==" + "version": "1.4.402", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.402.tgz", + "integrity": "sha512-gWYvJSkohOiBE6ecVYXkrDgNaUjo47QEKK0kQzmWyhkH+yoYiG44bwuicTGNSIQRG3WDMsWVZJLRnJnLNkbWvA==", + "dev": true }, "emoji-regex": { "version": "9.2.2", @@ -29885,9 +30216,9 @@ } }, "enhanced-resolve": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", - "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", + "version": "5.14.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.14.0.tgz", + "integrity": "sha512-+DCows0XNwLDcUhbFJPdlQEVnT2zXlCv7hPxemTz86/O+B/hCQ+mb7ydkPKiflpVraqLPCAfu7lDy+hBXueojw==", "dev": true, "requires": { "graceful-fs": "^4.2.4", @@ -29911,13 +30242,6 @@ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "requires": { "is-arrayish": "^0.2.1" - }, - "dependencies": { - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" - } } }, "error-stack-parser": { @@ -29930,43 +30254,45 @@ } }, "es-abstract": { - "version": "1.20.4", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.4.tgz", - "integrity": "sha512-0UtvRN79eMe2L+UNEF1BwRe364sj/DXhQ/k5FmivgoSdpM90b8Jc0mDzKMGo7QS0BVbOP/bTwBKNnDc9rNzaPA==", + "version": "1.21.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.2.tgz", + "integrity": "sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg==", "dev": true, "requires": { + "array-buffer-byte-length": "^1.0.0", + "available-typed-arrays": "^1.0.5", "call-bind": "^1.0.2", + "es-set-tostringtag": "^2.0.1", "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.3", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", "is-callable": "^1.2.7", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "is-string": "^1.0.7", + "is-typed-array": "^1.1.10", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.2", + "object-inspect": "^1.12.3", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", "safe-regex-test": "^1.0.0", - "string.prototype.trimend": "^1.0.5", - "string.prototype.trimstart": "^1.0.5", - "unbox-primitive": "^1.0.2" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } + "string.prototype.trim": "^1.2.7", + "string.prototype.trimend": "^1.0.6", + "string.prototype.trimstart": "^1.0.6", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.9" } }, "es-get-iterator": { @@ -29984,22 +30310,25 @@ "is-string": "^1.0.7", "isarray": "^2.0.5", "stop-iteration-iterator": "^1.0.0" - }, - "dependencies": { - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - } } }, "es-module-lexer": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", - "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.2.1.tgz", + "integrity": "sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==", "dev": true }, + "es-set-tostringtag": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", + "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.1.3", + "has": "^1.0.3", + "has-tostringtag": "^1.0.0" + } + }, "es-shim-unscopables": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", @@ -30027,33 +30356,33 @@ "dev": true }, "esbuild": { - "version": "0.16.17", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.16.17.tgz", - "integrity": "sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==", + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", "dev": true, "requires": { - "@esbuild/android-arm": "0.16.17", - "@esbuild/android-arm64": "0.16.17", - "@esbuild/android-x64": "0.16.17", - "@esbuild/darwin-arm64": "0.16.17", - "@esbuild/darwin-x64": "0.16.17", - "@esbuild/freebsd-arm64": "0.16.17", - "@esbuild/freebsd-x64": "0.16.17", - "@esbuild/linux-arm": "0.16.17", - "@esbuild/linux-arm64": "0.16.17", - "@esbuild/linux-ia32": "0.16.17", - "@esbuild/linux-loong64": "0.16.17", - "@esbuild/linux-mips64el": "0.16.17", - "@esbuild/linux-ppc64": "0.16.17", - "@esbuild/linux-riscv64": "0.16.17", - "@esbuild/linux-s390x": "0.16.17", - "@esbuild/linux-x64": "0.16.17", - "@esbuild/netbsd-x64": "0.16.17", - "@esbuild/openbsd-x64": "0.16.17", - "@esbuild/sunos-x64": "0.16.17", - "@esbuild/win32-arm64": "0.16.17", - "@esbuild/win32-ia32": "0.16.17", - "@esbuild/win32-x64": "0.16.17" + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" } }, "esbuild-plugin-alias": { @@ -30069,29 +30398,13 @@ "dev": true, "requires": { "debug": "^4.3.4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true }, "escape-html": { "version": "1.0.3", @@ -30100,9 +30413,9 @@ "dev": true }, "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" }, "escodegen": { "version": "2.0.0", @@ -30117,61 +30430,25 @@ "source-map": "~0.6.1" }, "dependencies": { - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "optional": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } } } }, "eslint": { - "version": "8.32.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.32.0.tgz", - "integrity": "sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { - "@eslint/eslintrc": "^1.4.1", + "@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", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -30181,24 +30458,22 @@ "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.4.0", - "esquery": "^1.4.0", + "eslint-scope": "^7.2.0", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", + "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^6.0.1", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "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", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -30206,7 +30481,6 @@ "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.1", - "regexpp": "^3.2.0", "strip-ansi": "^6.0.1", "strip-json-comments": "^3.1.0", "text-table": "^0.2.0" @@ -30237,25 +30511,20 @@ "supports-color": "^7.1.0" } }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "eslint-scope": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", + "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", "dev": true, "requires": { - "ms": "2.1.2" + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" } }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, "globals": { - "version": "13.19.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.19.0.tgz", - "integrity": "sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==", + "version": "13.20.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", + "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", "dev": true, "requires": { "type-fest": "^0.20.2" @@ -30276,11 +30545,19 @@ "argparse": "^2.0.1" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } }, "supports-color": { "version": "7.2.0", @@ -30290,6 +30567,12 @@ "requires": { "has-flag": "^4.0.0" } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true } } }, @@ -30314,14 +30597,6 @@ "object.assign": "^4.1.2", "object.entries": "^1.1.5", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "eslint-config-airbnb-typescript": { @@ -30334,12 +30609,12 @@ } }, "eslint-config-next": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.0.5.tgz", - "integrity": "sha512-lge94W7ME6kNCO96eCykq5GbKbllzmcDNDhh1/llMCRgNPl0+GIQ8dOoM0I7uRQVW56VmTXFybJFXgow11a5pg==", + "version": "13.4.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-13.4.3.tgz", + "integrity": "sha512-1lXwdFi29fKxzeugof/TUE7lpHyJQt5+U4LaUHyvQfHjvsWO77vFNicJv5sX6k0VDVSbnfz0lw+avxI+CinbMg==", "dev": true, "requires": { - "@next/eslint-plugin-next": "13.0.5", + "@next/eslint-plugin-next": "13.4.3", "@rushstack/eslint-patch": "^1.1.3", "@typescript-eslint/parser": "^5.42.0", "eslint-import-resolver-node": "^0.3.6", @@ -30351,9 +30626,9 @@ } }, "eslint-config-prettier": { - "version": "8.6.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.6.0.tgz", - "integrity": "sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==", + "version": "8.8.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.8.0.tgz", + "integrity": "sha512-wLbQiFre3tdGgpDv67NQKnJuTlcUVYHas3k+DZCc2U2BadthoEY4B7hLPvAxaqdyOGCzuLfii2fqGph10va7oA==", "dev": true, "requires": {} }, @@ -30376,43 +30651,29 @@ "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true } } }, "eslint-import-resolver-typescript": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.2.tgz", - "integrity": "sha512-zX4ebnnyXiykjhcBvKIf5TNvt8K7yX6bllTRZ14MiurKPjDpCAZujlszTdB8pcNXhZcOf+god4s9SjQa5GnytQ==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.5.5.tgz", + "integrity": "sha512-TdJqPHs2lW5J9Zpe17DZNQuDnox4xo2o+0tE7Pggain9Rbc19ik8kFtXdxZ250FVx2kF4vlt2RSf4qlUpG7bhw==", "dev": true, "requires": { "debug": "^4.3.4", - "enhanced-resolve": "^5.10.0", - "get-tsconfig": "^4.2.0", - "globby": "^13.1.2", - "is-core-module": "^2.10.0", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "get-tsconfig": "^4.5.0", + "globby": "^13.1.3", + "is-core-module": "^2.11.0", "is-glob": "^4.0.3", - "synckit": "^0.8.4" + "synckit": "^0.8.5" }, "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, "globby": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz", - "integrity": "sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==", + "version": "13.1.4", + "resolved": "https://registry.npmjs.org/globby/-/globby-13.1.4.tgz", + "integrity": "sha512-iui/IiiW+QrJ1X1hKH5qwlMQyv34wJAYwH1vrf8b9kBA4sNiif3gKsMHa+BrdnOpEudWjpotfa7LrTzB1ERS/g==", "dev": true, "requires": { "dir-glob": "^3.0.1", @@ -30422,12 +30683,6 @@ "slash": "^4.0.0" } }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "slash": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz", @@ -30437,9 +30692,9 @@ } }, "eslint-module-utils": { - "version": "2.7.4", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.7.4.tgz", - "integrity": "sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -30453,24 +30708,18 @@ "requires": { "ms": "^2.1.1" } - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true } } }, "eslint-plugin-import": { - "version": "2.27.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.4.tgz", - "integrity": "sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==", + "version": "2.27.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.27.5.tgz", + "integrity": "sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==", "dev": true, "requires": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.0", + "array.prototype.flatmap": "^1.3.1", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.7", @@ -30503,17 +30752,26 @@ "esutils": "^2.0.2" } }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } } } }, @@ -30539,14 +30797,6 @@ "object.entries": "^1.1.6", "object.fromentries": "^2.0.6", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "eslint-plugin-prettier": { @@ -30559,9 +30809,9 @@ } }, "eslint-plugin-react": { - "version": "7.32.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.0.tgz", - "integrity": "sha512-vSBi1+SrPiLZCGvxpiZIa28fMEUaMjXtCplrvxcIxGzmFiYdsXQDwInEjuv5/i/2CTTxbkS87tE8lsQ0Qxinbw==", + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.32.2.tgz", + "integrity": "sha512-t2fBMa+XzonrrNkyVirzKlvn5RXzzPwRHtMvLAtVZrt8oxgnTQaYbU6SXTOO1mwQgp1y5+toMSKInnzGr0Knqg==", "dev": true, "requires": { "array-includes": "^3.1.6", @@ -30600,12 +30850,6 @@ "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true } } }, @@ -30624,9 +30868,9 @@ "requires": {} }, "eslint-plugin-storybook": { - "version": "0.6.10", - "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.10.tgz", - "integrity": "sha512-3DKXRey06EhwnTKaG6fgMqGTy4C3z6Ikyv6VVixO5BvaExWQe3yGWIAufrC2Et0OaAMIaMwx9KWjqb/Wq+JxPg==", + "version": "0.6.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-storybook/-/eslint-plugin-storybook-0.6.12.tgz", + "integrity": "sha512-XbIvrq6hNVG6rpdBr+eBw63QhOMLpZneQVSooEDow8aQCWGCk/5vqtap1yxpVydNfSxi3S/3mBBRLQqKUqQRww==", "dev": true, "requires": { "@storybook/csf": "^0.0.1", @@ -30647,53 +30891,44 @@ } }, "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "requires": { "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" + "estraverse": "^4.1.1" }, "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true } } }, "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true }, "espree": { - "version": "9.4.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.4.1.tgz", - "integrity": "sha512-XwctdmTO6SIvCzd9810yyNzIrOrqNYV9Koizx4C/mRhf9uq0o4yHoCEU/670pOxOL/MSraektvSAji79kX90Vg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.1" }, "dependencies": { "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true } } @@ -30704,9 +30939,9 @@ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" }, "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -30778,106 +31013,11 @@ "strip-final-newline": "^2.0.0" } }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "expand-template": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==" }, - "expect-type": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-0.14.2.tgz", - "integrity": "sha512-ed3+tr5ujbIYXZ8Pl/VgIphwJQ0q5tBLGGdn7Zvwt1WyPBRX83xjT5pT77P/GkuQbctx0K2ZNSSan7eruJqTCQ==", - "dev": true - }, "express": { "version": "4.18.2", "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", @@ -30915,6 +31055,32 @@ "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + }, + "qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } } }, "extend": { @@ -30930,33 +31096,6 @@ "is-extendable": "^0.1.0" } }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - } - } - }, "extract-zip": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", @@ -30967,6 +31106,23 @@ "debug": "^2.6.9", "mkdirp": "^0.5.4", "yauzl": "^2.10.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } } }, "fast-deep-equal": { @@ -30976,9 +31132,9 @@ "dev": true }, "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", "dev": true }, "fast-glob": { @@ -31024,9 +31180,9 @@ "dev": true }, "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", "dev": true, "requires": { "reusify": "^1.0.4" @@ -31051,9 +31207,9 @@ } }, "fetch-retry": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.3.tgz", - "integrity": "sha512-uJQyMrX5IJZkhoEUBQ3EjxkeiZkppBd5jS/fMTJmfZxLSiaQjv2zD0kTvuvkSH89uFvgSlB6ueGpjD3HWN7Bxw==", + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/fetch-retry/-/fetch-retry-5.0.6.tgz", + "integrity": "sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==", "dev": true }, "fflate": { @@ -31071,26 +31227,13 @@ } }, "file-system-cache": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.0.2.tgz", - "integrity": "sha512-lp4BHO4CWqvRyx88Tt3quZic9ZMf4cJyquYq7UI8sH42Bm2ArlBBjKQAalZOo+UfaBassb7X123Lik5qZ/tSAA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/file-system-cache/-/file-system-cache-2.3.0.tgz", + "integrity": "sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==", "dev": true, "requires": { - "fs-extra": "^11.1.0", - "ramda": "^0.28.0" - }, - "dependencies": { - "fs-extra": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz", - "integrity": "sha512-0rcTq621PD5jM/e0a3EJoGC/1TC5ZBCERW82LQuwfGnCa1V8w7dpYH1yNu+SLb6E5dkeCBzKEyLGlFrnr+dUyw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - } + "fs-extra": "11.1.1", + "ramda": "0.29.0" } }, "filelist": { @@ -31149,6 +31292,23 @@ "parseurl": "~1.3.3", "statuses": "2.0.1", "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } } }, "find-cache-dir": { @@ -31242,15 +31402,15 @@ "dev": true }, "flow-parser": { - "version": "0.197.0", - "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.197.0.tgz", - "integrity": "sha512-yhwkJPxH1JBg0aJunk/jVRy5p3UhVZBGkzL1hq/GK+GaBh6bKr2YKkv6gDuiufaw+i3pKWQgOLtD++1cvrgXLA==", + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", "dev": true }, "follow-redirects": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", - "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", + "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==" }, "for-each": { "version": "0.3.3", @@ -31261,12 +31421,6 @@ "is-callable": "^1.1.3" } }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==", - "dev": true - }, "foreground-child": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", @@ -31333,6 +31487,24 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -31341,6 +31513,12 @@ "requires": { "has-flag": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -31366,13 +31544,26 @@ "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", "dev": true }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==", - "dev": true, + "framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", "requires": { - "map-cache": "^0.2.2" + "@emotion/is-prop-valid": "^0.8.2", + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, + "framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "requires": { + "tslib": "^2.1.0" } }, "fresh": { @@ -31382,9 +31573,9 @@ "dev": true }, "fs": { - "version": "0.0.1-security", - "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", - "integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w==" + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.2.tgz", + "integrity": "sha512-YAiVokMCrSIFZiroB1oz51hPiPRVcUtSa4x2U5RYXyhS9VAPdiFigKbPTnOSq7XY8wd3FIVPYmXpo5lMzFmxgg==" }, "fs-constants": { "version": "1.0.0", @@ -31392,12 +31583,11 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" }, "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dev": true, "requires": { - "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" @@ -31420,6 +31610,12 @@ "requires": { "yallist": "^4.0.0" } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -31485,7 +31681,8 @@ "gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==" + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true }, "get-caller-file": { "version": "2.0.5", @@ -31494,13 +31691,14 @@ "dev": true }, "get-intrinsic": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", - "integrity": "sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", "dev": true, "requires": { "function-bind": "^1.1.1", "has": "^1.0.3", + "has-proto": "^1.0.1", "has-symbols": "^1.0.3" } }, @@ -31509,6 +31707,12 @@ "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==" }, + "get-npm-tarball-url": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/get-npm-tarball-url/-/get-npm-tarball-url-2.0.3.tgz", + "integrity": "sha512-R/PW6RqyaBQNWYaSyfrh54/qtcnOp22FHCCiRhSSZj0FP3KQWCsxxt0DzIdVTbwTqe9CtQfvl/FPD4UIPt4pqw==", + "dev": true + }, "get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -31538,30 +31742,24 @@ } }, "get-tsconfig": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.2.0.tgz", - "integrity": "sha512-X8u8fREiYOE6S8hLbq99PeykTDoLVnxvF4DjWKJmz9xy2nNRdUcV8ZN9tniJFeKyTU3qnC9lL8n4Chd6LmVKHg==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.5.0.tgz", + "integrity": "sha512-MjhiaIWCJ1sAU4pIQ5i5OfOuHHxVo1oYeNsWTON7jxYkod8pHocXeh+SSbmu5OZZZK73B6cbJ2XADzXehLyovQ==", "dev": true }, "giget": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/giget/-/giget-1.0.0.tgz", - "integrity": "sha512-KWELZn3Nxq5+0So485poHrFriK9Bn3V/x9y+wgqrHkbmnGbjfLmZ685/SVA/ovW+ewoqW0gVI47pI4yW/VNobQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/giget/-/giget-1.1.2.tgz", + "integrity": "sha512-HsLoS07HiQ5oqvObOI+Qb2tyZH4Gj5nYGfF9qQcZNrPw+uEFhdXtgJr01aO2pWadGHucajYDLxxbtQkm97ON2A==", "dev": true, "requires": { "colorette": "^2.0.19", - "defu": "^6.1.1", + "defu": "^6.1.2", "https-proxy-agent": "^5.0.1", "mri": "^1.2.0", - "node-fetch-native": "^1.0.1", - "pathe": "^1.0.0", - "tar": "^6.1.12" + "node-fetch-native": "^1.0.2", + "pathe": "^1.1.0", + "tar": "^6.1.13" } }, "github-from-package": { @@ -31576,17 +31774,36 @@ "dev": true }, "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "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==", + "dev": true, + "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==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } } }, "glob-parent": { @@ -31598,6 +31815,15 @@ "is-glob": "^4.0.3" } }, + "glob-promise": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-promise/-/glob-promise-6.0.2.tgz", + "integrity": "sha512-Ni2aDyD1ekD6x8/+K4hDriRDbzzfuK4yKpqSymJ4P7IxbtARiOOuU+k40kbHM0sLIlbf1Qh0qdMkAHMZYE6XJQ==", + "dev": true, + "requires": { + "@types/glob": "^8.0.0" + } + }, "glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", @@ -31619,11 +31845,14 @@ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==" }, - "globalyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz", - "integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==", - "dev": true + "globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3" + } }, "globby": { "version": "11.1.0", @@ -31639,12 +31868,6 @@ "slash": "^3.0.0" } }, - "globrex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz", - "integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==", - "dev": true - }, "gopd": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", @@ -31655,9 +31878,9 @@ } }, "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true }, "grapheme-splitter": { @@ -31666,6 +31889,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "gray-matter": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", @@ -31677,6 +31906,68 @@ "strip-bom-string": "^1.0.0" } }, + "gunzip-maybe": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz", + "integrity": "sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==", + "dev": true, + "requires": { + "browserify-zlib": "^0.1.4", + "is-deflate": "^1.0.0", + "is-gzip": "^1.0.0", + "peek-stream": "^1.1.0", + "pumpify": "^1.3.3", + "through2": "^2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, "handlebars": { "version": "4.7.7", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", @@ -31726,6 +32017,12 @@ "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "dev": true + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -31747,72 +32044,6 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "hash-base": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", @@ -31821,12 +32052,32 @@ "inherits": "^2.0.4", "readable-stream": "^3.6.0", "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "hast-util-whitespace": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.0.tgz", - "integrity": "sha512-Pkw+xBHuV6xFeJprJe2BBEoDV+AvQySaz3pPDRUs5PNZEMQjpXJJueqrpcHIXxnWTcAGi/UOCgVShlkY6kLoqg==" + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-2.0.1.tgz", + "integrity": "sha512-nAxA0v8+vXSBDt3AnRUNjyRIQ0rD+ntpbAp4LnPkumc5M9yUbSMa4XDU9Q6etY4f1Wp4bNgvc1yjiZtsTTrSng==" }, "he": { "version": "1.2.0", @@ -31834,12 +32085,24 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, "hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "hosted-git-info": { @@ -31884,9 +32147,9 @@ } }, "html-tags": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.2.0.tgz", - "integrity": "sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", "dev": true }, "html-tokenize": { @@ -31899,35 +32162,12 @@ "minimist": "~1.2.5", "readable-stream": "~1.0.27-1", "through2": "~0.4.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" - } } }, "html-webpack-plugin": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.0.tgz", - "integrity": "sha512-sy88PC2cRTVxvETRgUHFrL4No3UxvcH8G1NepGhqaTT+GXN2kTamqasot0inS5hXeg1cMbFDt27zzo9p35lZVw==", + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.5.1.tgz", + "integrity": "sha512-cTUzZ1+NqjGEKjmVgZKLMdiFg3m9MdRXkZW2OEe69WYVi5ONLMmlnSZdXzGGMOq0C8jGDrL6EWyEDDUioHO/pA==", "dev": true, "requires": { "@types/html-minifier-terser": "^6.0.0", @@ -31998,23 +32238,6 @@ "requires": { "agent-base": "6", "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } } }, "human-signals": { @@ -32024,17 +32247,28 @@ "dev": true }, "i18next": { - "version": "22.4.9", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.4.9.tgz", - "integrity": "sha512-8gWMmUz460KJDQp/ob3MNUX84cVuDRY9PLFPnV8d+Qezz/6dkjxwOaH70xjrCNDO+JrUL25iXfAIN9wUkInNZw==", + "version": "22.5.0", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.0.tgz", + "integrity": "sha512-sqWuJFj+wJAKQP2qBQ+b7STzxZNUmnSxrehBCCj9vDOW9RDYPfqCaK1Hbh2frNYQuPziz6O2CGoJPwtzY3vAYA==", "requires": { "@babel/runtime": "^7.20.6" } }, - "i18next-fs-backend": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.1.1.tgz", - "integrity": "sha512-FTnj+UmNgT3YRml5ruRv0jMZDG7odOL/OP5PF5mOqvXud2vHrPOOs68Zdk6iqzL47cnnM0ZVkK2BAvpFeDJToA==" + "i18next-browser-languagedetector": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.0.1.tgz", + "integrity": "sha512-Pa5kFwaczXJAeHE56CHG2aWzFBMJNUNghf0Pm4SwSrEMps/PTKqW90EYWlIvhuYStf3Sn1K0vw+gH3+TLdkH1g==", + "requires": { + "@babel/runtime": "^7.19.4" + } + }, + "i18next-http-backend": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/i18next-http-backend/-/i18next-http-backend-2.2.1.tgz", + "integrity": "sha512-ZXIdn/8NJIBJ0X4hzXfc3STYxKrCKh1fYjji9HPyIpEJfvTvy8/ZlTl8RuTizzCPj2ZcWrfaecyOMKs6bQ7u5A==", + "requires": { + "cross-fetch": "3.1.6" + } }, "iconv-lite": { "version": "0.4.24", @@ -32046,11 +32280,37 @@ } }, "icss-utils": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", - "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, - "requires": {} + "requires": { + "postcss": "^7.0.14" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } }, "ieee754": { "version": "1.2.1", @@ -32058,9 +32318,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", + "version": "5.2.4", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", + "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", "dev": true }, "image-size": { @@ -32073,9 +32333,9 @@ } }, "immer": { - "version": "9.0.15", - "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.15.tgz", - "integrity": "sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==" + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==" }, "import-fresh": { "version": "3.3.0", @@ -32084,6 +32344,13 @@ "requires": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" + } } }, "imurmurhash": { @@ -32099,19 +32366,20 @@ "dev": true }, "infisical-node": { - "version": "1.0.37", - "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.0.37.tgz", - "integrity": "sha512-9ZswN5UovZq46a7Qv/4KmfaAu9pO/TmxxdcEY2PosDIAlXbpfC651hcKr7T8q1iMlRnHLA/gpYkcZMeS0es0rg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/infisical-node/-/infisical-node-1.2.1.tgz", + "integrity": "sha512-zEB0w5+1O0mv9qc68bq4f9jDjrtwdbqjJebnwodgy8U1XZElDXeMDQgSMCtgYan7JRmVlH6s/LM8X7kUF+67ZA==", "requires": { "axios": "^1.3.3", + "dotenv": "^16.0.3", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1" }, "dependencies": { "axios": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.3.4.tgz", - "integrity": "sha512-toYm+Bsyl6VC5wSkfkbbNB6ROv7KY93PEBBL6xyDczaIHasAiv4wPqQ/c4RjoQzipxRD2W5g21cOqQulZ7rHwQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", + "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", "requires": { "follow-redirects": "^1.15.0", "form-data": "^4.0.0", @@ -32146,12 +32414,12 @@ "integrity": "sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==" }, "internal-slot": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.4.tgz", - "integrity": "sha512-tA8URYccNzMo94s5MQZgH8NB/XTa6HsOo0MLfXTKKEnHVVdegzaQoFZ7Jp44bdvLvY2waT5dc+j5ICEswhi7UQ==", + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", + "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "has": "^1.0.3", "side-channel": "^1.0.4" } @@ -32188,15 +32456,6 @@ "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", "dev": true }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -32208,20 +32467,20 @@ } }, "is-array-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.1.tgz", - "integrity": "sha512-ASfLknmY8Xa2XtB4wmbz13Wu202baeA18cJBCeCy0wXUHZF0IPyVEXqKEcd+t2fNSLLL1vC6k7lxZEojNbISXQ==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", "dev": true, "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "get-intrinsic": "^1.2.0", "is-typed-array": "^1.1.10" } }, "is-arrayish": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", - "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, "is-bigint": { "version": "1.0.4", @@ -32263,22 +32522,13 @@ "dev": true }, "is-core-module": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", - "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.12.1.tgz", + "integrity": "sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg==", "requires": { "has": "^1.0.3" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, "is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -32288,16 +32538,11 @@ "has-tostringtag": "^1.0.0" } }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } + "is-deflate": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-deflate/-/is-deflate-1.0.0.tgz", + "integrity": "sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==", + "dev": true }, "is-docker": { "version": "2.2.1", @@ -32346,6 +32591,29 @@ "is-extglob": "^2.1.1" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==", + "dev": true + }, + "is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "requires": { + "is-docker": "^3.0.0" + }, + "dependencies": { + "is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true + } + } + }, "is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -32492,12 +32760,6 @@ "get-intrinsic": "^1.1.1" } }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, "is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -32508,9 +32770,10 @@ } }, "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true }, "isexe": { "version": "2.0.0", @@ -32551,14 +32814,6 @@ "@istanbuljs/schema": "^0.1.2", "istanbul-lib-coverage": "^3.2.0", "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "istanbul-lib-report": { @@ -32600,15 +32855,15 @@ } }, "jake": { - "version": "10.8.5", - "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.5.tgz", - "integrity": "sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==", + "version": "10.8.6", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.6.tgz", + "integrity": "sha512-G43Ub9IYEFfu72sua6rzooi8V8Gz2lkfk48rW20vEWCGizeaEPlKB1Kh8JIA84yQbiAEfqlPmSpGgCKKxH3rDA==", "dev": true, "requires": { "async": "^3.2.3", "chalk": "^4.0.2", - "filelist": "^1.0.1", - "minimatch": "^3.0.4" + "filelist": "^1.0.4", + "minimatch": "^3.1.2" }, "dependencies": { "ansi-styles": { @@ -32648,21 +32903,21 @@ } }, "jest-haste-map": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.3.1.tgz", - "integrity": "sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/graceful-fs": "^4.1.3", "@types/node": "*", "anymatch": "^3.0.3", "fb-watchman": "^2.0.0", "fsevents": "^2.3.2", "graceful-fs": "^4.2.9", - "jest-regex-util": "^29.2.0", - "jest-util": "^29.3.1", - "jest-worker": "^29.3.1", + "jest-regex-util": "^29.4.3", + "jest-util": "^29.5.0", + "jest-worker": "^29.5.0", "micromatch": "^4.0.4", "walker": "^1.0.8" } @@ -32736,18 +32991,18 @@ } }, "jest-regex-util": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.2.0.tgz", - "integrity": "sha512-6yXn0kg2JXzH30cr2NlThF+70iuO/3irbaB4mh5WyqNIvLLP+B6sFdluO1/1RJmslyh/f9osnefECflHvTbwVA==", + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz", + "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==", "dev": true }, "jest-util": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.3.1.tgz", - "integrity": "sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==", + "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==", "dev": true, "requires": { - "@jest/types": "^29.3.1", + "@jest/types": "^29.5.0", "@types/node": "*", "chalk": "^4.0.0", "ci-info": "^3.2.0", @@ -32792,13 +33047,13 @@ } }, "jest-worker": { - "version": "29.3.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.3.1.tgz", - "integrity": "sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==", + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.5.0.tgz", + "integrity": "sha512-NcrQnevGoSp4b5kg+akIpthoAFHxPBcb5P6mYPY0fUNT+sSvmtu6jlkEle3anczUKIKEbMxFimk9oTP/tpIPgA==", "dev": true, "requires": { "@types/node": "*", - "jest-util": "^29.3.1", + "jest-util": "^29.5.0", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, @@ -32820,10 +33075,10 @@ } } }, - "js-sdsl": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.2.0.tgz", - "integrity": "sha512-dyBIzQBDkCqCu+0upx25Y2jGdbTGxE9fshMsCdK0ViOongpV+n5tXRcZY9v7CaVQ79AGS9KA1KHtojxiM7aXSQ==", + "jiti": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.18.2.tgz", + "integrity": "sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==", "dev": true }, "js-tokens": { @@ -32846,9 +33101,9 @@ "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==" }, "jscodeshift": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.13.1.tgz", - "integrity": "sha512-lGyiEbGOvmMRKgWk4vf+lUrCWO/8YR8sUR3FKF1Cq5fovjZDlIcw3Hu5ppLHAnEXshVffvaM0eyuY/AbOeYpnQ==", + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", "dev": true, "requires": { "@babel/core": "^7.13.16", @@ -32864,10 +33119,10 @@ "chalk": "^4.1.2", "flow-parser": "0.*", "graceful-fs": "^4.2.4", - "micromatch": "^3.1.10", + "micromatch": "^4.0.4", "neo-async": "^2.5.0", "node-dir": "^0.1.17", - "recast": "^0.20.4", + "recast": "^0.21.0", "temp": "^0.8.4", "write-file-atomic": "^2.3.0" }, @@ -32881,22 +33136,13 @@ "color-convert": "^2.0.1" } }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "tslib": "^2.0.1" } }, "chalk": { @@ -32909,114 +33155,19 @@ "supports-color": "^7.1.0" } }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, "has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - } - } - }, "recast": { - "version": "0.20.5", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.20.5.tgz", - "integrity": "sha512-E5qICoPoNL4yU0H0NoBDntNB0Q5oMSNh9usFctYniLBluTthi3RsQVBXIJNbApOlvSwW/RGxIuokPcAc59J5fQ==", + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", "dev": true, "requires": { - "ast-types": "0.14.2", + "ast-types": "0.15.2", "esprima": "~4.0.0", "source-map": "~0.6.1", "tslib": "^2.0.1" @@ -33037,16 +33188,6 @@ "has-flag": "^4.0.0" } }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, "write-file-atomic": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", @@ -33085,7 +33226,8 @@ "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true }, "jsonfile": { "version": "6.1.0", @@ -33103,6 +33245,21 @@ "integrity": "sha512-pfog5gdDxPdV4eP7Kg87M8/bHgshlZ5pybl+yKxAnCZ5O7lCIn7Ixydj03wOlnDQesky2BPyA91SQ+5Y/mNwzw==", "requires": { "debug": "^2.1.3" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + } } }, "jspdf": { @@ -33140,6 +33297,11 @@ "object.assign": "^4.1.3" } }, + "jwt-decode": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", + "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==" + }, "keygrip": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", @@ -33154,9 +33316,10 @@ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" }, "kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true }, "klona": { "version": "2.0.6", @@ -33180,16 +33343,14 @@ } }, "lazy-universal-dotenv": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz", - "integrity": "sha512-prXSYk799h3GY3iOWnC6ZigYzMPjxN2svgjJ9shk7oMadSNX3wXy0B6F32PMJv7qtMnrIbUxoEHzbutvxR2LBQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/lazy-universal-dotenv/-/lazy-universal-dotenv-4.0.0.tgz", + "integrity": "sha512-aXpZJRnTkpK6gQ/z4nk+ZBLd/Qdp118cvPruLSIQzQNRhKwEcdXCOzXuF55VDqIiuAaY3UGZ10DJtvZzDcvsxg==", "dev": true, "requires": { - "@babel/runtime": "^7.5.0", "app-root-dir": "^1.0.2", - "core-js": "^3.0.4", - "dotenv": "^8.0.0", - "dotenv-expand": "^5.1.0" + "dotenv": "^16.0.0", + "dotenv-expand": "^10.0.0" } }, "leven": { @@ -33209,9 +33370,9 @@ } }, "lilconfig": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", - "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true }, "lines-and-columns": { @@ -33295,6 +33456,19 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, + "lottie-react": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/lottie-react/-/lottie-react-2.4.0.tgz", + "integrity": "sha512-pDJGj+AQlnlyHvOHFK7vLdsDcvbuqvwPZdMlJ360wrzGFurXeKPr8SiRCjLf3LrNYKANQtSsh5dz9UYQHuqx4w==", + "requires": { + "lottie-web": "^5.10.2" + } + }, + "lottie-web": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/lottie-web/-/lottie-web-5.11.0.tgz", + "integrity": "sha512-9vSt0AtdOH98GKDXwD5LPfFg9Pcmxt5+1BllAbudKM5iqPxpJnJUfuGaP45OyudDrESCOBgsjnntVUTygBNlzw==" + }, "lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -33305,17 +33479,18 @@ } }, "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, "requires": { - "yallist": "^4.0.0" + "yallist": "^3.0.2" } }, "lz-string": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", - "integrity": "sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz", + "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true }, "make-dir": { @@ -33325,14 +33500,6 @@ "dev": true, "requires": { "semver": "^6.0.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } } }, "makeerror": { @@ -33344,27 +33511,12 @@ "tmpl": "1.0.5" } }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", - "dev": true - }, "map-or-similar": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", "dev": true }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, "markdown-it": { "version": "13.0.1", "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-13.0.1.tgz", @@ -33385,9 +33537,9 @@ } }, "markdown-to-jsx": { - "version": "7.1.8", - "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.1.8.tgz", - "integrity": "sha512-rRSa1aFmFnpDRFAhv5vIkWM4nPaoB9vnzIjuIKa1wGupfn2hdCNeaQHKpu4/muoc8n8J7yowjTP2oncA4/Rbgg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.2.0.tgz", + "integrity": "sha512-3l4/Bigjm4bEqjCR6Xr+d4DtM1X6vvtGsMGSjJYyep8RjjIvcWtrXBS8Wbfe1/P+atKNMccpsraESIaWVplzVg==", "dev": true, "requires": {} }, @@ -33402,19 +33554,47 @@ } }, "mdast-util-definitions": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.1.tgz", - "integrity": "sha512-rQ+Gv7mHttxHOBx2dkF4HWTg+EE+UR78ptQWDylzPKaQuVGdG4HIoY3SrS/pCp80nZ04greFvXbVFHT+uf0JVQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", + "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", + "dev": true, "requires": { - "@types/mdast": "^3.0.0", - "@types/unist": "^2.0.0", - "unist-util-visit": "^4.0.0" + "unist-util-visit": "^2.0.0" + }, + "dependencies": { + "unist-util-is": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-4.1.0.tgz", + "integrity": "sha512-ZOQSsnce92GrxSqlnEEseX0gi7GH9zTJZ0p9dtu87WRb/37mMPO2Ilx1s/t9vBHrFhbgweUwb+t7cIn5dxPhZg==", + "dev": true + }, + "unist-util-visit": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-2.0.3.tgz", + "integrity": "sha512-iJ4/RczbJMkD0712mGktuGpm/U4By4FfDonL7N/9tATGIF4imikjOuagyMY53tnZq3NP6BcmlrHhEKAfGWjh7Q==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0", + "unist-util-visit-parents": "^3.0.0" + } + }, + "unist-util-visit-parents": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz", + "integrity": "sha512-1KROIZWo6bcMrZEwiH2UrXDyalAa0uqzWCxCJj6lPOvTve2WkfgCytoDTPaMnodXh1WrXOq0haVYHj99ynJlsg==", + "dev": true, + "requires": { + "@types/unist": "^2.0.0", + "unist-util-is": "^4.0.0" + } + } } }, "mdast-util-from-markdown": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.2.0.tgz", - "integrity": "sha512-iZJyyvKD1+K7QX1b5jXdE7Sc5dtoTry1vzV28UZZe8Z1xVnB/czKntJ7ZAkG0tANqRnBF6p3p7GpU1y19DTf2Q==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.0.tgz", + "integrity": "sha512-HN3W1gRIuN/ZW295c7zi7g9lVBllMgZE40RxCX37wrTPWXCWtpvOZdfnuK+1WNpvZje6XuJeI3Wnb4TJEUem+g==", "requires": { "@types/mdast": "^3.0.0", "@types/unist": "^2.0.0", @@ -33431,27 +33611,39 @@ } }, "mdast-util-to-hast": { - "version": "12.2.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.2.2.tgz", - "integrity": "sha512-lVkUttV9wqmdXFtEBXKcepvU/zfwbhjbkM5rxrquLW55dS1DfOrnAXCk5mg1be1sfY/WfMmayGy1NsbK1GLCYQ==", + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-12.3.0.tgz", + "integrity": "sha512-pits93r8PhnIoU4Vy9bjW39M2jJ6/tdHyja9rrot9uujkN7UTU9SDnE6WNJz/IGyQk3XHX6yNNtrBH6cQzm8Hw==", "requires": { "@types/hast": "^2.0.0", "@types/mdast": "^3.0.0", - "@types/mdurl": "^1.0.0", "mdast-util-definitions": "^5.0.0", - "mdurl": "^1.0.0", - "micromark-util-sanitize-uri": "^1.0.0", + "micromark-util-sanitize-uri": "^1.1.0", "trim-lines": "^3.0.0", - "unist-builder": "^3.0.0", "unist-util-generated": "^2.0.0", "unist-util-position": "^4.0.0", "unist-util-visit": "^4.0.0" + }, + "dependencies": { + "mdast-util-definitions": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-5.1.2.tgz", + "integrity": "sha512-8SVPMuHqlPME/z3gqVwWY4zVXn8lqKv/pAhC57FuJ40ImXyBpmO5ukh98zB2v7Blql2FiHjHv9LVztSIqjY+MA==", + "requires": { + "@types/mdast": "^3.0.0", + "@types/unist": "^2.0.0", + "unist-util-visit": "^4.0.0" + } + } } }, "mdast-util-to-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.1.0.tgz", - "integrity": "sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==" + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz", + "integrity": "sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg==", + "requires": { + "@types/mdast": "^3.0.0" + } }, "mdurl": { "version": "1.0.1", @@ -33465,9 +33657,9 @@ "dev": true }, "memfs": { - "version": "3.4.13", - "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.13.tgz", - "integrity": "sha512-omTM41g3Skpvx5dSYeZIbXKcXoAVc/AoMNwn9TKx++L/gaen/+4TTttmu8ZSch5vfVJ8uJvGbroTsIlslRg6lg==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.1.tgz", + "integrity": "sha512-UWbFJKvj5k+nETdteFndTpYxdeTMox/ULeqX5k/dpaQJCCFmj5EeKv3dBcyO2xmkRAx2vppRu5dVG7SOtsGOzA==", "dev": true, "requires": { "fs-monkey": "^1.0.3" @@ -33512,9 +33704,9 @@ "dev": true }, "micromark": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.0.10.tgz", - "integrity": "sha512-ryTDy6UUunOXy2HPjelppgJ2sNfcPz1pLlMdA6Rz9jPzhLikWXv/irpWV/I2jd68Uhmny7hHxAlAhk4+vWggpg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/micromark/-/micromark-3.1.0.tgz", + "integrity": "sha512-6Mj0yHLdUZjHnOPgr5xfWIMqMWS12zDN6iws9SLuSz76W8jTtAv24MN4/CL7gJrl5vtxGInkkqDv/JIoRsQOvA==", "requires": { "@types/debug": "^4.0.0", "debug": "^4.0.0", @@ -33533,21 +33725,6 @@ "micromark-util-symbol": "^1.0.0", "micromark-util-types": "^1.0.1", "uvu": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } } }, "micromark-core-commonmark": { @@ -33708,9 +33885,9 @@ } }, "micromark-util-sanitize-uri": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.0.0.tgz", - "integrity": "sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.1.0.tgz", + "integrity": "sha512-RoxtuSCX6sUNtxhbmsEFQfWzs8VN7cTctmBPvYivo98xb/kDEoTCtJQX5wyzIYEmk/lvNFTat4hL8oW0KndFpg==", "requires": { "micromark-util-character": "^1.0.0", "micromark-util-encode": "^1.0.0", @@ -33803,18 +33980,15 @@ } }, "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==" }, "minipass": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.0.tgz", - "integrity": "sha512-g2Uuh2jEKoht+zvO6vJqXmYpflPqzRBT+Th2h01DKh5z7wbY/AZ2gCQ78cP70YoHPyFdY30YBV5WxgLOEwOykw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true }, "minizlib": { "version": "2.1.2", @@ -33834,41 +34008,11 @@ "requires": { "yallist": "^4.0.0" } - } - } - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } @@ -33893,9 +34037,9 @@ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==" }, "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "multipipe": { "version": "1.0.2", @@ -33912,64 +34056,9 @@ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" }, "nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==" - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, "napi-build-utils": { "version": "1.0.2", @@ -34024,18 +34113,24 @@ "postcss": "8.4.14", "styled-jsx": "5.0.7", "use-sync-external-store": "1.2.0" - } - }, - "next-i18next": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/next-i18next/-/next-i18next-13.0.2.tgz", - "integrity": "sha512-aUHyKT2kztMgEP44zDB5KoW8XZUQawIdOYWXcrMH6lxAcS0kBsKX0uKMzGS5XlgLW88gvOVc3D7NdfCznLgyyg==", - "requires": { - "@babel/runtime": "^7.20.6", - "@types/hoist-non-react-statics": "^3.3.1", - "core-js": "^3", - "hoist-non-react-statics": "^3.3.2", - "i18next-fs-backend": "^2.1.0" + }, + "dependencies": { + "postcss": { + "version": "8.4.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", + "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "requires": { + "nanoid": "^3.3.4", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + } + }, + "styled-jsx": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", + "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", + "requires": {} + } } }, "no-case": { @@ -34049,23 +34144,46 @@ } }, "node-abi": { - "version": "3.30.0", - "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.30.0.tgz", - "integrity": "sha512-qWO5l3SCqbwQavymOmtTVuCWZE23++S+rxyoHjXqUmPyzRcaoI4lA2gO55/drddGnedAyjA7sk76SfQ5lfUMnw==", + "version": "3.40.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.40.0.tgz", + "integrity": "sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA==", "requires": { "semver": "^7.3.5" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "node-abort-controller": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", - "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", "dev": true }, "node-addon-api": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.0.0.tgz", - "integrity": "sha512-CvkDw2OEnme7ybCykJpVcKH+uAOLV2qLqiyla128dN9TkEWfrYmxG6C2boDe5KcNQqZF3orkqzGgOMvZ/JNekA==" + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz", + "integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==" }, "node-dir": { "version": "0.1.17", @@ -34077,17 +34195,17 @@ } }, "node-fetch": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.8.tgz", - "integrity": "sha512-RZ6dBYuj8dRSfxpUSu+NsdF1dpPpluJxwOp+6IoDp/sH2QNDSvurYsAa+F1WxY2RjA1iP93xhcsUoYbF2XBqVg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "requires": { "whatwg-url": "^5.0.0" } }, "node-fetch-native": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz", - "integrity": "sha512-VzW+TAk2wE4X9maiKMlT+GsPU4OMmR1U9CrHSmd3DFLn2IcZ9VJ6M6BBugGfYUnPCLSYxXdZy17M0BEJyhUTwg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.1.1.tgz", + "integrity": "sha512-9VvspTSUp2Sxbl+9vbZTlFGq9lHwE8GDVVekxx6YsNd1YH59sb3Ba8v3Y3cD8PkLNcileGGcA21PFjVl0jzDaw==", "dev": true }, "node-int64": { @@ -34097,9 +34215,10 @@ "dev": true }, "node-releases": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.6.tgz", - "integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==" + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.11.tgz", + "integrity": "sha512-+M0PwXeU80kRohZ3aT4J/OnR+l9/KD2nVLNNoRgFtnf+umQVFdGBAO2N8+nCnEi0xlh/Wk3zOGC+vNNx+uM79Q==", + "dev": true }, "normalize-package-data": { "version": "2.5.0", @@ -34168,80 +34287,6 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==" }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "object-hash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", @@ -34249,9 +34294,9 @@ "dev": true }, "object-inspect": { - "version": "1.12.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", - "integrity": "sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", "dev": true }, "object-is": { @@ -34265,26 +34310,10 @@ } }, "object-keys": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", - "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true }, "object.assign": { "version": "4.1.4", @@ -34296,14 +34325,6 @@ "define-properties": "^1.1.4", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" - }, - "dependencies": { - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - } } }, "object.entries": { @@ -34338,23 +34359,6 @@ "es-abstract": "^1.20.4" } }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, "object.values": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", @@ -34405,9 +34409,9 @@ } }, "open": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz", - "integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==", + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", "dev": true, "requires": { "define-lazy-prop": "^2.0.0", @@ -34416,17 +34420,44 @@ } }, "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", + "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.6", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "word-wrap": "~1.2.3" + }, + "dependencies": { + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + } } }, "p-limit": { @@ -34462,6 +34493,12 @@ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true }, + "pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", + "dev": true + }, "param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", @@ -34507,12 +34544,6 @@ "tslib": "^2.0.3" } }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==", - "dev": true - }, "path-browserify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", @@ -34554,11 +34585,76 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==" }, "pathe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.0.0.tgz", - "integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.0.tgz", + "integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==", "dev": true }, + "peek-stream": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/peek-stream/-/peek-stream-1.1.3.tgz", + "integrity": "sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "duplexify": "^3.5.0", + "through2": "^2.0.3" + }, + "dependencies": { + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + } + } + }, "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", @@ -34620,18 +34716,24 @@ "@babel/runtime": "^7.17.8" } }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==", - "dev": true + "popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "requires": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } }, "postcss": { - "version": "8.4.14", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.14.tgz", - "integrity": "sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig==", + "version": "8.4.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", + "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "dev": true, "requires": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } @@ -34648,77 +34750,199 @@ } }, "postcss-js": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz", - "integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, "requires": { "camelcase-css": "^2.0.1" } }, - "postcss-load-config": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", - "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "postcss-loader": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", + "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", "dev": true, "requires": { - "lilconfig": "^2.0.5", - "yaml": "^1.10.2" + "cosmiconfig": "^7.0.0", + "klona": "^2.0.4", + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0", + "semver": "^7.3.4" }, "dependencies": { - "yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true } } }, - "postcss-loader": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz", - "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==", + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", "dev": true, "requires": { - "cosmiconfig": "^7.0.0", - "klona": "^2.0.5", - "semver": "^7.3.5" + "postcss": "^7.0.5" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, - "postcss-modules-extract-imports": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", - "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", - "dev": true, - "requires": {} - }, "postcss-modules-local-by-default": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", - "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz", + "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==", "dev": true, "requires": { - "icss-utils": "^5.0.0", + "icss-utils": "^4.1.1", + "postcss": "^7.0.32", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.1.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", "dev": true, "requires": { - "postcss-selector-parser": "^6.0.4" + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "postcss-modules-values": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", - "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "requires": { - "icss-utils": "^5.0.0" + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" + }, + "dependencies": { + "picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "requires": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "postcss-nested": { @@ -34746,11 +34970,10 @@ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, "posthog-js": { - "version": "1.39.4", - "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.39.4.tgz", - "integrity": "sha512-Elpf1gwyuObueXi89iH+9pP+WhpkiivP8Qwej4RzOLwSTa7Floaa4rgAw7rnCnX1PtRoJ3F0kqb6q9T+aZjRiA==", + "version": "1.58.0", + "resolved": "https://registry.npmjs.org/posthog-js/-/posthog-js-1.58.0.tgz", + "integrity": "sha512-PpH/MwjwV6UHDsv78xFvteEWYgY3O/HTKBnotzmkNCDWgsKzNr978B1AKzgtBU2GzBsnwUfuK+u2O6mxRzFSWw==", "requires": { - "@sentry/types": "7.22.0", "fflate": "^0.4.1", "rrweb-snapshot": "^1.1.14" } @@ -34781,9 +35004,9 @@ "dev": true }, "prettier": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.3.tgz", - "integrity": "sha512-tJ/oJ4amDihPoufT5sM0Z1SKEuKay8LfVAMlbbhnnkvt6BUserZylqo2PN+p9KeljLr0OHa2rXHU1T8reeoTrw==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "prettier-linter-helpers": { @@ -34796,9 +35019,9 @@ } }, "prettier-plugin-tailwindcss": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.2.tgz", - "integrity": "sha512-5RjUbWRe305pUpc48MosoIp6uxZvZxrM6GyOgsbGLTce+ehePKNm7ziW2dLG2air9aXbGuXlHVSQQw4Lbosq3w==", + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.8.tgz", + "integrity": "sha512-KgPcEnJeIijlMjsA6WwYgRs5rh3/q76oInqtMXBA/EMcamrcYJpyhtRhyX1ayT9hnHlHTuO8sIifHF10WuSDKg==", "dev": true, "requires": {} }, @@ -34868,14 +35091,6 @@ "requires": { "kleur": "^3.0.3", "sisteransi": "^1.0.5" - }, - "dependencies": { - "kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true - } } }, "prop-types": { @@ -34886,6 +35101,13 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "property-expr": { @@ -34894,9 +35116,9 @@ "integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA==" }, "property-information": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.1.1.tgz", - "integrity": "sha512-hrzC564QIl0r0vy4l6MvRLhafmUowhO/O3KgVSoXIbbA2Sz4j8HGpJc6T2cubRVwMwpdiG/vKGfhT4IixmKN9w==" + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.2.0.tgz", + "integrity": "sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==" }, "proxy-addr": { "version": "2.0.7", @@ -34922,10 +35144,33 @@ "once": "^1.3.1" } }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, "punycode": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.2.0.tgz", - "integrity": "sha512-LN6QV1IJ9ZhxWTNdktaPClrNfp8xdSAYS0Zk2ddX7XsXZAxckMHPCBcHRo0cTcEIgYPRiGEkmji3Idkh2yFtYw==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", "dev": true }, "puppeteer-core": { @@ -34952,13 +35197,18 @@ "integrity": "sha512-TMeqbNl2fMW0nMjTEPOwe3J/PRFP4vqeoNuQMG0HlMrtm5QxKqdvAkZ1pRBQ/ulIyDD5Yq0nJ7YbdD8ey0TO3g==", "dev": true }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "dev": true, "requires": { - "ms": "2.1.2" + "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" } }, "https-proxy-agent": { @@ -34977,12 +35227,6 @@ "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, "rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", @@ -35004,9 +35248,9 @@ } }, "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.11.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", + "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", "dev": true, "requires": { "side-channel": "^1.0.4" @@ -35059,9 +35303,9 @@ "integrity": "sha512-tQkJl2GRWh83ui2DiPTJz9wEiMN20syf+5oKfB03yYP7ioZcJwsIK8FjrtLwH1m7C7e+Tt2yYBlrOpdT+dyeIQ==" }, "ramda": { - "version": "0.28.0", - "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.28.0.tgz", - "integrity": "sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==", + "version": "0.29.0", + "resolved": "https://registry.npmjs.org/ramda/-/ramda-0.29.0.tgz", + "integrity": "sha512-BBea6L67bYLtdbOqfp8f58fPMqEwx0doL+pAi8TZyp2YWz8R9G8z9x75CZI8W+ftqhFHCpEX2cRnUUXK130iKA==", "dev": true }, "randombytes": { @@ -35137,9 +35381,9 @@ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, "react-redux": { - "version": "7.2.8", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.8.tgz", - "integrity": "sha512-6+uDjhs3PSIclqoCk0kd6iX74gzrGc3W5zcAjbrFgEdIjRSQObdIwfx80unTkVUYvbQ95Y8Av3OvFHq1w5EOUw==", + "version": "7.2.9", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.9.tgz", + "integrity": "sha512-Gx4L3uM182jEEayZfRbI/G11ZpYdNAnBs70lFVMNdHJI76XYtR+7m0MN+eAs7UHBPhWXcnFPaS+9owSCJQHNpQ==", "requires": { "@babel/runtime": "^7.15.4", "@types/react-redux": "^7.1.20", @@ -35284,17 +35528,17 @@ } }, "react-hook-form": { - "version": "7.43.0", - "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.0.tgz", - "integrity": "sha512-/rVEz7T0gLdSFwPqutJ1kn2e0sQNyb9ci/hmwEYr2YG0KF/LSuRLvNrf9QWJM+gj88CjDpDW5Bh/1AD7B2+z9Q==", + "version": "7.43.9", + "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.43.9.tgz", + "integrity": "sha512-AUDN3Pz2NSeoxQ7Hs6OhQhDr6gtF9YRuutGDwPQqhSUAHJSgGl2VeY3qN19MG0SucpjgDiuMJ4iC5T5uB+eaNQ==", "requires": {} }, "react-i18next": { - "version": "12.1.1", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.1.1.tgz", - "integrity": "sha512-mFdieOI0LDy84q3JuZU6Aou1DoWW2fhapcTGeBS8+vWSJuViuoCLQAMYSb0QoHhXS8B0WKUOPpx4cffAP7r/aA==", + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", "requires": { - "@babel/runtime": "^7.14.5", + "@babel/runtime": "^7.20.6", "html-parse-stringify": "^3.0.1" } }, @@ -35306,9 +35550,9 @@ "requires": {} }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" }, "react-mailchimp-subscribe": { "version": "2.1.3", @@ -35321,9 +35565,9 @@ } }, "react-markdown": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.3.tgz", - "integrity": "sha512-We36SfqaKoVNpN1QqsZwWSv/OZt5J15LNgTLWynwAN5b265hrQrsjMtlRNwUvS+YyR3yDM8HpTNc4pK9H/Gc0A==", + "version": "8.0.7", + "resolved": "https://registry.npmjs.org/react-markdown/-/react-markdown-8.0.7.tgz", + "integrity": "sha512-bvWbzG4MtOU62XqBx3Xx+zB2raaFFsq4mYiAzfjXJMEz2sixgeAfraA3tvzULF02ZdOMUOKTBFFaZJDDrq+BJQ==", "requires": { "@types/hast": "^2.0.0", "@types/prop-types": "^15.0.0", @@ -35336,23 +35580,16 @@ "remark-parse": "^10.0.0", "remark-rehype": "^10.0.0", "space-separated-tokens": "^2.0.0", - "style-to-object": "^0.3.0", + "style-to-object": "^0.4.0", "unified": "^10.0.0", "unist-util-visit": "^4.0.0", "vfile": "^5.0.0" - }, - "dependencies": { - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - } } }, "react-redux": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.2.tgz", - "integrity": "sha512-nBwiscMw3NoP59NFCXFf02f8xdo+vSHT/uZ1ldDwF7XaTpzm+Phk97VT4urYBl5TYAPNVaFm12UHAEyzkpNzRA==", + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.0.5.tgz", + "integrity": "sha512-Q2f6fCKxPFpkXt1qNRZdEDLlScsDWyrgSj0mliK59qU6W5gvBiKkdMEG2lJzhd1rCctf0hb6EtePPLZ2e0m1uw==", "requires": { "@babel/runtime": "^7.12.1", "@types/hoist-non-react-statics": "^3.3.1", @@ -35360,13 +35597,6 @@ "hoist-non-react-statics": "^3.3.2", "react-is": "^18.0.0", "use-sync-external-store": "^1.0.0" - }, - "dependencies": { - "react-is": { - "version": "18.2.0", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" - } } }, "react-refresh": { @@ -35397,9 +35627,9 @@ } }, "react-resizable": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.4.tgz", - "integrity": "sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/react-resizable/-/react-resizable-3.0.5.tgz", + "integrity": "sha512-vKpeHhI5OZvYn82kXOs1bC8aOXktGU5AmKAgaZS4F5JPburCtbmDPqE7Pzp+1kN4+Wb81LlF33VpGwWwtXem+w==", "requires": { "prop-types": "15.x", "react-draggable": "^4.0.3" @@ -35507,13 +35737,21 @@ } }, "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" + } } }, "readdirp": { @@ -35526,9 +35764,9 @@ } }, "recast": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.1.tgz", - "integrity": "sha512-RokaBcoxSjXUDzz1TXSZmZsSW6ZpLmlA3GGqJ8uuTrQ9hZhEz+4Tpsc+gRvYRJ2BU4H+ZyUlg91eSGDw7bwy7g==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.2.tgz", + "integrity": "sha512-Qv6cPfVZyMOtPszK6PgW70pUgm7gPlFitAPf0Q69rlOA0zLw2XdDcNmPbVGYicFGT9O8I7TZ/0ryJD+6COvIPw==", "dev": true, "requires": { "assert": "^2.0.0", @@ -35565,17 +35803,17 @@ } }, "redux": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.0.tgz", - "integrity": "sha512-oSBmcKKIuIR4ME29/AeNUnl5L+hvBq7OaJWzaptTQJAntaPvxIJqfnjbaEiCzzaIz+XmVILfqAM3Ob0aXLPfjA==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", "requires": { "@babel/runtime": "^7.9.2" } }, "redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz", + "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==", "requires": {} }, "regenerate": { @@ -35607,52 +35845,6 @@ "@babel/runtime": "^7.8.4" } }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, "regex-parser": { "version": "2.2.11", "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.2.11.tgz", @@ -35660,42 +35852,30 @@ "dev": true }, "regexp.prototype.flags": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.4.3.tgz", - "integrity": "sha512-fjggEOO3slI6Wvgjwflkc4NFRCTZAu5CnNfBd5qOMYhWdn67nJBBu34/TkD++eeFmd8C9r9jfXJ27+nSiRkSUA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", + "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", "dev": true, "requires": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "functions-have-names": "^1.2.3" } }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, "regexpu-core": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.2.2.tgz", - "integrity": "sha512-T0+1Zp2wjF/juXMrMxHxidqGYn8U4R+zleSJhX9tQ1PUsS8a9UtYfbsF9LdiVgNX3kiX8RNaKM42nfSgvFJjmw==", + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", "dev": true, "requires": { + "@babel/regjsgen": "^0.8.0", "regenerate": "^1.4.2", "regenerate-unicode-properties": "^10.1.0", - "regjsgen": "^0.7.1", "regjsparser": "^0.9.1", "unicode-match-property-ecmascript": "^2.0.0", "unicode-match-property-value-ecmascript": "^2.1.0" } }, - "regjsgen": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.7.1.tgz", - "integrity": "sha512-RAt+8H2ZEzHeYWxZ3H2z6tF18zyyOnlcdaafLrm21Bguj7uZy6ULibiAFdXEtKQY4Sy7wDTwDiOazasMLc4KPA==", - "dev": true - }, "regjsparser": { "version": "0.9.1", "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", @@ -35732,15 +35912,6 @@ "unist-util-visit": "^2.0.0" }, "dependencies": { - "mdast-util-definitions": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-4.0.0.tgz", - "integrity": "sha512-k8AJ6aNnUkB7IE+5azR9h81O5EQ/cTDXtWdMq9Kk5KcEW/8ritU5CeLg/9HhOC++nALHBlaogJ5jz0Ybk3kPMQ==", - "dev": true, - "requires": { - "unist-util-visit": "^2.0.0" - } - }, "space-separated-tokens": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz", @@ -35777,9 +35948,9 @@ } }, "remark-parse": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.1.tgz", - "integrity": "sha512-1fUyHr2jLsVOkhbvPRBJ5zTKZZyD6yZzYaWCS6BPBdQ8vEMBCH+9zNCDA6tET/zHCi/jLqjCWtlJZUPk+DbnFw==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-10.0.2.tgz", + "integrity": "sha512-3ydxgHa/ZQzG8LvC7jTXccARYDcRld3VfcgIIFs7bI6vbRSxJJmzgLEIIoYKyrfhaY+ujuWaf/PJiMZXoiCXgw==", "requires": { "@types/mdast": "^3.0.0", "mdast-util-from-markdown": "^1.0.0", @@ -35856,18 +36027,6 @@ "strip-ansi": "^6.0.1" } }, - "repeat-element": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", - "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -35892,29 +36051,24 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==" }, "reselect": { - "version": "4.1.6", - "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.6.tgz", - "integrity": "sha512-ZovIuXqto7elwnxyXbBtCPo9YFEr3uJqj2rRbcOOog1bmu2Ag85M4hixSwFWyaBMKXNgvPaJ9OSu9SkBPIeJHQ==" + "version": "4.1.8", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz", + "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ==" }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.2", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", + "integrity": "sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==", "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.11.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } }, "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==" - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true }, "resolve-url-loader": { @@ -35949,12 +36103,6 @@ } } }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, "reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -35974,6 +36122,22 @@ "dev": true, "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==", + "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" + } + } } }, "ripemd160": { @@ -35990,6 +36154,15 @@ "resolved": "https://registry.npmjs.org/rrweb-snapshot/-/rrweb-snapshot-1.1.14.tgz", "integrity": "sha512-eP5pirNjP5+GewQfcOQY4uBiDnpqxNRc65yKPW0eSoU1XamDfc4M8oqpXGMyUyvLyxFDB0q0+DChuxxiU2FXBQ==" }, + "run-applescript": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-5.0.0.tgz", + "integrity": "sha512-XcT5rBksx1QdIhlFOCtgZkB99ZEouFZ1E2Kc2LHqNW13U3/74YGdkQRmThTwxy4QIyookibDKYZOPqX//6BlAg==", + "dev": true, + "requires": { + "execa": "^5.0.0" + } + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -36012,15 +36185,6 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, "safe-regex-test": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", @@ -36058,9 +36222,9 @@ } }, "schema-utils": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", - "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.2.tgz", + "integrity": "sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==", "dev": true, "requires": { "@types/json-schema": "^7.0.8", @@ -36078,12 +36242,10 @@ } }, "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true }, "send": { "version": "0.18.0", @@ -36106,6 +36268,23 @@ "statuses": "2.0.1" }, "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + }, + "dependencies": { + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true + } + } + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -36169,38 +36348,9 @@ "dev": true }, "set-cookie-parser": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.5.1.tgz", - "integrity": "sha512-1jeBGaKNGdEq4FgIrORu/N570dwoPYio8lSoYLWmX7sQ//0JY08Xh9o5pBcgmHQ/MbsYp/aZnOe1s1lIsbLprQ==" - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.6.0.tgz", + "integrity": "sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==" }, "setprototypeof": { "version": "1.2.0", @@ -36232,18 +36382,41 @@ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" }, "sharp": { - "version": "0.31.2", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.31.2.tgz", - "integrity": "sha512-DUdNVEXgS5A97cTagSLIIp8dUZ/lZtk78iNVZgHdHbx1qnQR7JAHY0BnXnwwH39Iw+VKhO08CTYhIg0p98vQ5Q==", + "version": "0.32.1", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.1.tgz", + "integrity": "sha512-kQTFtj7ldpUqSe8kDxoGLZc1rnMFU0AO2pqbX6pLy3b7Oj8ivJIdoKNwxHVQG2HN6XpHPJqCSM2nsma2gOXvOg==", "requires": { "color": "^4.2.3", "detect-libc": "^2.0.1", - "node-addon-api": "^5.0.0", + "node-addon-api": "^6.1.0", "prebuild-install": "^7.1.1", - "semver": "^7.3.8", + "semver": "^7.5.0", "simple-get": "^4.0.1", "tar-fs": "^2.1.1", "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "semver": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", + "requires": { + "lru-cache": "^6.0.0" + } + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } } }, "shebang-command": { @@ -36270,6 +36443,22 @@ "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" + }, + "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" + } + } } }, "side-channel": { @@ -36310,6 +36499,13 @@ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", "requires": { "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } } }, "simple-update-notifier": { @@ -36341,150 +36537,6 @@ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -36495,19 +36547,6 @@ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==" }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, "source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -36532,21 +36571,15 @@ } } }, - "source-map-url": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", - "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", - "dev": true - }, "space-separated-tokens": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.1.tgz", - "integrity": "sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==" + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", + "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==" }, "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", "dev": true, "requires": { "spdx-expression-parse": "^3.0.0", @@ -36570,9 +36603,9 @@ } }, "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", + "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", "dev": true }, "split-on-first": { @@ -36580,51 +36613,6 @@ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==" }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } - }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -36642,90 +36630,6 @@ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", "dev": true }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "statuses": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", @@ -36748,43 +36652,43 @@ "dev": true }, "storybook": { - "version": "7.0.0-beta.30", - "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.0.0-beta.30.tgz", - "integrity": "sha512-hfOtpvNnQ/rXLfojznCs2WdOFbojKx0Gf1W1Ra6DzOBrmUdXzWwRL8X1RUkI6jwUfYuaE97D8gQpfNRlvoqv4A==", + "version": "7.0.12", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-7.0.12.tgz", + "integrity": "sha512-HKi7NQQTZhBGEU3KUFxTNGtIZcG8+hokiO5TwcIr7s7smAVKdvj9vY5YGsVkiWF39o+5UtafW1B/i9D8lBFsYg==", "dev": true, "requires": { - "@storybook/cli": "7.0.0-beta.30" + "@storybook/cli": "7.0.12" } }, "storybook-dark-mode": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-2.0.5.tgz", - "integrity": "sha512-egOMu2tgGttGAMtFZcDLZobs1xc7LzFOh+pRVqaW59AVp05ABdQ3Hj6IX2Pz7tYGmF9AmaK+nBv0hDFxPe7Hfg==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/storybook-dark-mode/-/storybook-dark-mode-2.1.1.tgz", + "integrity": "sha512-Ops6u/htODxIUXnAYASttqcbd2PRN723o0uIKpoYQn1+so2g6gYalpAhuysxnRhCG8yHsm6NJuX5drzzI+uFvQ==", "dev": true, "requires": { "@storybook/addons": "^6.5.14", "@storybook/api": "^6.5.14", "@storybook/components": "^6.5.14", "@storybook/core-events": "^6.5.14", + "@storybook/global": "^5.0.0", "@storybook/theming": "^6.5.14", "fast-deep-equal": "^3.1.3", - "global": "^4.4.0", "memoizerific": "^1.11.3" }, "dependencies": { "@storybook/addons": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.15.tgz", - "integrity": "sha512-xT31SuSX+kYGyxCNK2nqL7WTxucs3rSmhiCLovJcUjYk+QquV3c2c53Ki7lwwdDbzfXFcNAe0HJ4hoTN4jhn0Q==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/addons/-/addons-6.5.16.tgz", + "integrity": "sha512-p3DqQi+8QRL5k7jXhXmJZLsE/GqHqyY6PcoA1oNTJr0try48uhTGUOYkgzmqtDaa/qPFO5LP+xCPzZXckGtquQ==", "dev": true, "requires": { - "@storybook/api": "6.5.15", - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/api": "6.5.16", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", - "@storybook/theming": "6.5.15", + "@storybook/router": "6.5.16", + "@storybook/theming": "6.5.16", "@types/webpack-env": "^1.16.0", "core-js": "^3.8.2", "global": "^4.4.0", @@ -36792,18 +36696,18 @@ } }, "@storybook/api": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.15.tgz", - "integrity": "sha512-BBE0KXKvj1/3jTghbIoWfrcDM0t+xO7EYtWWAXD6XlhGsZVD2Dy82Z52ONyLulMDRpMWl0OYy3h6A1YnFUH25w==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/api/-/api-6.5.16.tgz", + "integrity": "sha512-HOsuT8iomqeTMQJrRx5U8nsC7lJTwRr1DhdD0SzlqL4c80S/7uuCy4IZvOt4sYQjOzW5fOo/kamcoBXyLproTA==", "dev": true, "requires": { - "@storybook/channels": "6.5.15", - "@storybook/client-logger": "6.5.15", - "@storybook/core-events": "6.5.15", + "@storybook/channels": "6.5.16", + "@storybook/client-logger": "6.5.16", + "@storybook/core-events": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/router": "6.5.15", + "@storybook/router": "6.5.16", "@storybook/semver": "^7.3.2", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "fast-deep-equal": "^3.1.3", "global": "^4.4.0", @@ -36817,9 +36721,9 @@ } }, "@storybook/channels": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.15.tgz", - "integrity": "sha512-gPpsBgirv2NCXbH4WbYqdkI0JLE96aiVuu7UEWfn9yu071pQ9CLHbhXGD9fSFNrfOkyBBY10ppSE7uCXw3Wexg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/channels/-/channels-6.5.16.tgz", + "integrity": "sha512-VylzaWQZaMozEwZPJdyJoz+0jpDa8GRyaqu9TGG6QGv+KU5POoZaGLDkRE7TzWkyyP0KQLo80K99MssZCpgSeg==", "dev": true, "requires": { "core-js": "^3.8.2", @@ -36828,9 +36732,9 @@ } }, "@storybook/client-logger": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.15.tgz", - "integrity": "sha512-0uyxKvodq+FycGv6aUwC1wUR6suXf2+7ywMFAOlYolI4UvNj8NyU/5AfgKT5XnxYAgPmoCiAjOE700TrfHrosw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/client-logger/-/client-logger-6.5.16.tgz", + "integrity": "sha512-pxcNaCj3ItDdicPTXTtmYJE3YC1SjxFrBmHcyrN+nffeNyiMuViJdOOZzzzucTUG0wcOOX8jaSyak+nnHg5H1Q==", "dev": true, "requires": { "core-js": "^3.8.2", @@ -36838,14 +36742,14 @@ } }, "@storybook/components": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.15.tgz", - "integrity": "sha512-bHTT0Oa3s4g+MBMaLBbX9ofMtb1AW59AzIUNGrfqW1XqJMGuUHMiJ7TSo+i5dRSFpbFygnwMEG9LfHxpR2Z0Dw==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-6.5.16.tgz", + "integrity": "sha512-LzBOFJKITLtDcbW9jXl0/PaG+4xAz25PK8JxPZpIALbmOpYWOAPcO6V9C2heX6e6NgWFMUxjplkULEk9RCQMNA==", "dev": true, "requires": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "@storybook/csf": "0.0.2--canary.4566f4d.1", - "@storybook/theming": "6.5.15", + "@storybook/theming": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -36854,9 +36758,9 @@ } }, "@storybook/core-events": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.15.tgz", - "integrity": "sha512-B1Ba6l5W7MeNclclqMMTMHgYgfdpB5SIhNCQFnzIz8blynzRhNFMdxvbAl6Je5G0S4xydYYd7Lno2kXQebs7HA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/core-events/-/core-events-6.5.16.tgz", + "integrity": "sha512-qMZQwmvzpH5F2uwNUllTPg6eZXr2OaYZQRRN8VZJiuorZzDNdAFmiVWMWdkThwmyLEJuQKXxqCL8lMj/7PPM+g==", "dev": true, "requires": { "core-js": "^3.8.2" @@ -36872,12 +36776,12 @@ } }, "@storybook/router": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.15.tgz", - "integrity": "sha512-9t8rI8t7/Krolau29gsdjdbRQ66orONIyP0efp0EukVgv6reNFzb/U14ARrl0uHys6Tl5Xyece9FoakQUdn8Kg==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/router/-/router-6.5.16.tgz", + "integrity": "sha512-ZgeP8a5YV/iuKbv31V8DjPxlV4AzorRiR8OuSt/KqaiYXNXlOoQDz/qMmiNcrshrfLpmkzoq7fSo4T8lWo2UwQ==", "dev": true, "requires": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "qs": "^6.10.0", @@ -36885,12 +36789,12 @@ } }, "@storybook/theming": { - "version": "6.5.15", - "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.15.tgz", - "integrity": "sha512-pgdW0lVZKKXQ4VhIfLHycMmwFSVOY7vLTKnytag4Y8Yz+aXm0bwDN/QxPntFzDH47F1Rcy2ywNnvty8ooDTvuA==", + "version": "6.5.16", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-6.5.16.tgz", + "integrity": "sha512-hNLctkjaYLRdk1+xYTkC1mg4dYz2wSv6SqbLpcKMbkPHTE0ElhddGPHQqB362md/w9emYXNkt1LSMD8Xk9JzVQ==", "dev": true, "requires": { - "@storybook/client-logger": "6.5.15", + "@storybook/client-logger": "6.5.16", "core-js": "^3.8.2", "memoizerific": "^1.11.3", "regenerator-runtime": "^0.13.7" @@ -36914,18 +36818,21 @@ } } }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, "strict-uri-encode": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", "integrity": "sha512-QwiXZgpRcKkhTj2Scnn++4PKtWsH0kpzZ62L2R6c/LUVYv7hVnZqcg2+sMuT6R7Jusu1vviK/MFsu6kNJfWlEQ==" }, "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" }, "string-width": { "version": "4.2.3", @@ -36962,6 +36869,17 @@ "side-channel": "^1.0.4" } }, + "string.prototype.trim": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", + "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.4", + "es-abstract": "^1.20.4" + } + }, "string.prototype.trimend": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", @@ -37026,24 +36944,60 @@ "dev": true }, "style-loader": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.1.tgz", - "integrity": "sha512-GPcQ+LDJbrcxHORTRes6Jy2sfvK2kS6hpSfI/fXhPt+spVzxF6LJ1dHLN9zIGmVaaP044YKaIatFaufENRiDoQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.3.0.tgz", + "integrity": "sha512-V7TCORko8rs9rIqkSrlMfkqA63DfoGBBJmK1kKGCcSi+BWb4cqz0SRsnp4l6rU5iwOEd0/2ePv68SV22VXon4Q==", "dev": true, - "requires": {} + "requires": { + "loader-utils": "^2.0.0", + "schema-utils": "^2.7.0" + }, + "dependencies": { + "loader-utils": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", + "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^2.1.2" + } + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + } + } }, "style-to-object": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.3.0.tgz", - "integrity": "sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==", + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-0.4.1.tgz", + "integrity": "sha512-HFpbb5gr2ypci7Qw+IOhnP2zOU7e77b+rzM+wTzXzfi1PrtBCX0E7Pk4wL4iTLnhzZ+JgEGAhX81ebTg/aYjQw==", "requires": { "inline-style-parser": "0.1.1" } }, + "style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "requires": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, "styled-components": { - "version": "5.3.7", - "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.7.tgz", - "integrity": "sha512-JL1b4A79OGqav4TxkrNsuuQfy6ZnrpyQx6hBDQ3Hd3JyuR2IQuVNBpF+FCEWFNZpN5hj+fhkaEVWteVJ18f0tw==", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.10.tgz", + "integrity": "sha512-3kSzSBN0TiCnGJM04UwO1HklIQQSXW7rCARUk+VyMR7clz8XVlA3jijtf5ypqoDIdNMKx3la4VvaPFR855SFcg==", "requires": { "@babel/helper-module-imports": "^7.0.0", "@babel/traverse": "^7.4.5", @@ -37055,18 +37009,36 @@ "hoist-non-react-statics": "^3.0.0", "shallowequal": "^1.1.0", "supports-color": "^5.5.0" + }, + "dependencies": { + "@emotion/is-prop-valid": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz", + "integrity": "sha512-61Mf7Ufx4aDxx1xlDeOm8aFFigGHE4z+0sKCa+IHCeZKiyP9RLD0Mmx7m8b9/Cf37f7NAvQOOJAbQQGVr5uERw==", + "requires": { + "@emotion/memoize": "^0.8.1" + } + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + } } }, "styled-jsx": { - "version": "5.0.7", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.0.7.tgz", - "integrity": "sha512-b3sUzamS086YLRuvnaDigdAewz1/EFYlHpYBP5mZovKEdQQOIIYq8lApylub3HHZ6xFjV051kkGU7cudJmrXEA==", - "requires": {} + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "dev": true, + "requires": { + "client-only": "0.0.1" + } }, "stylis": { - "version": "4.0.13", - "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.13.tgz", - "integrity": "sha512-xGPXiFVl4YED9Jh7Euv2V220mriG9u4B2TA6Ybjc1catrstKD2PpIdU3U0RKpkVBC2EhmL/F0sPCr9vrFTNRag==" + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz", + "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==" }, "supports-color": { "version": "5.5.0", @@ -37088,30 +37060,30 @@ "optional": true }, "synchronous-promise": { - "version": "2.0.16", - "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.16.tgz", - "integrity": "sha512-qImOD23aDfnIDNqlG1NOehdB9IYsn1V9oByPjKY1nakv2MQYCEMyX033/q+aEtYCpmYK1cv2+NTmlH+ra6GA5A==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/synchronous-promise/-/synchronous-promise-2.0.17.tgz", + "integrity": "sha512-AsS729u2RHUfEra9xJrE39peJcc2stq2+poBXX8bcM08Y6g9j/i/PUzwNQqkaJde7Ntg1TO7bSREbR5sdosQ+g==", "dev": true }, "synckit": { - "version": "0.8.4", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.4.tgz", - "integrity": "sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==", + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.5.tgz", + "integrity": "sha512-L1dapNV6vu2s/4Sputv8xGsCdAVlb5nRDMFU/E27D44l5U6cw1g0dGd45uLc+OXjNMmF4ntiMdCimzcjFKQI8Q==", "dev": true, "requires": { "@pkgr/utils": "^2.3.1", - "tslib": "^2.4.0" + "tslib": "^2.5.0" } }, "tailwind-merge": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.8.1.tgz", - "integrity": "sha512-+fflfPxvHFr81hTJpQ3MIwtqgvefHZFUHFiIHpVIRXvG/nX9+gu2P7JNlFu2bfDMJ+uHhi/pUgzaYacMoXv+Ww==" + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.12.0.tgz", + "integrity": "sha512-Y17eDp7FtN1+JJ4OY0Bqv9OA41O+MS8c1Iyr3T6JFLnOgLg3EvcyMKZAnQ8AGyvB5Nxm3t9Xb5Mhe139m8QT/g==" }, "tailwindcss": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz", - "integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==", + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.7.tgz", + "integrity": "sha512-B6DLqJzc21x7wntlH/GsZwEXTBttVSl1FtCzC8WP4oBc/NKef7kaax5jeihkkCEWc831/5NDJ9gRNDK6NEioQQ==", "dev": true, "requires": { "arg": "^5.0.2", @@ -37128,27 +37100,42 @@ "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.0.0", - "postcss": "^8.4.18", + "postcss": "^8.0.9", "postcss-import": "^14.1.0", "postcss-js": "^4.0.0", "postcss-load-config": "^3.1.4", "postcss-nested": "6.0.0", - "postcss-selector-parser": "^6.0.10", + "postcss-selector-parser": "^6.0.11", "postcss-value-parser": "^4.2.0", "quick-lru": "^5.1.1", "resolve": "^1.22.1" }, "dependencies": { - "postcss": { - "version": "8.4.21", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", - "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", + "postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", "dev": true, "requires": { - "nanoid": "^3.3.4", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" } + }, + "postcss-selector-parser": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.13.tgz", + "integrity": "sha512-EaV1Gl4mUEV4ddhDnv/xtj7sxwrwxdetHdWUGnT4VJQf+4d05v6lHYZr8N573k5Z0BViss7BDhfWtKS3+sfAqQ==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true } } }, @@ -37159,30 +37146,30 @@ "dev": true }, "tar": { - "version": "6.1.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", - "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", "dev": true, "requires": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", - "minipass": "^4.0.0", + "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, "mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } }, @@ -37195,6 +37182,13 @@ "mkdirp-classic": "^0.5.2", "pump": "^3.0.0", "tar-stream": "^2.1.4" + }, + "dependencies": { + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + } } }, "tar-stream": { @@ -37207,12 +37201,32 @@ "fs-constants": "^1.0.0", "inherits": "^2.0.3", "readable-stream": "^3.1.1" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "requires": { + "safe-buffer": "~5.2.0" + } + } } }, "telejson": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.0.4.tgz", - "integrity": "sha512-J4QEuCnYGXAI9KSN7RXK0a0cOW2ONpjc4IQbInGZ6c3stvplLAYyZjTnScrRd8deXVjNCFV1wXcLC7SObDuQYA==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/telejson/-/telejson-7.1.0.tgz", + "integrity": "sha512-jFJO4P5gPebZAERPkJsqMAQ0IMA1Hi0AoSfxpnUaV6j6R2SZqlpkbS20U6dEUtA3RUYt2Ak/mTlkQzHH9Rv/hA==", "dev": true, "requires": { "memoizerific": "^1.11.3" @@ -37227,6 +37241,20 @@ "rimraf": "~2.6.2" }, "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" + } + }, "rimraf": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", @@ -37266,9 +37294,9 @@ } }, "terser": { - "version": "5.16.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.1.tgz", - "integrity": "sha512-xvQfyfA1ayT0qdK47zskQgRZeWLoOQ8JQ6mIgRGVNwZKdQMU+5FkCBjmv4QjcrTzyZquRw2FVtlJSRUmMKQslw==", + "version": "5.17.5", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.5.tgz", + "integrity": "sha512-NqFkzBX34WExkCbk3K5urmNCpEWqMPZnwGI1pMHwqvJ/zDlXC75u3NI7BrzoR8/pryy8Abx2e1i8ChrWkhH1Hg==", "dev": true, "requires": { "@jridgewell/source-map": "^0.3.2", @@ -37278,9 +37306,9 @@ }, "dependencies": { "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "commander": { @@ -37292,16 +37320,16 @@ } }, "terser-webpack-plugin": { - "version": "5.3.6", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", - "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", + "version": "5.3.9", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz", + "integrity": "sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==", "dev": true, "requires": { - "@jridgewell/trace-mapping": "^0.3.14", + "@jridgewell/trace-mapping": "^0.3.17", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", - "serialize-javascript": "^6.0.0", - "terser": "^5.14.1" + "serialize-javascript": "^6.0.1", + "terser": "^5.16.8" }, "dependencies": { "has-flag": { @@ -37341,6 +37369,22 @@ "@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-segmentation": { @@ -37372,26 +37416,10 @@ "xtend": "~2.1.1" }, "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==" - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==" + "object-keys": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-0.4.0.tgz", + "integrity": "sha512-ncrLw+X55z7bkl5PnUvHwFK9FcGuFYo9gtjws2XtSzL+aZ8tm830P60WJ0dSmFVaSalWieW5MD7kEdnXda9yJw==" }, "xtend": { "version": "2.1.2", @@ -37403,20 +37431,16 @@ } } }, - "tiny-glob": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz", - "integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==", - "dev": true, - "requires": { - "globalyzer": "0.1.0", - "globrex": "^0.1.2" - } - }, "tiny-invariant": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.2.0.tgz", - "integrity": "sha512-1Uhn/aqw5C6RI4KejVeTg6mIS7IqxnLJ8Mv2tV5rTc0qWobay7pDUz6Wi392Cnc8ak1H0F2cjoRzb2/AW4+Fvg==" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.1.tgz", + "integrity": "sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==" + }, + "titleize": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/titleize/-/titleize-3.0.0.tgz", + "integrity": "sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==", + "dev": true }, "tmpl": { "version": "1.0.5", @@ -37429,84 +37453,10 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==" }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "to-querystring": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/to-querystring/-/to-querystring-1.1.1.tgz", - "integrity": "sha512-ZgIacl9TXAoT7sGXUYjQiy0MW7Tf/7CJQLt757hYHfXXc8JBzOVBMx4DckqKUO4hi36J72/m8UcH/GCHK+n97g==" - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - } - }, - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - } - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/to-querystring/-/to-querystring-1.2.0.tgz", + "integrity": "sha512-V4qvlRNOltdNxvWGuDS71sNMH6FtFNx3GP967WT8gb6xzi4thJTUfogIln9hvz1ZmWcm9hY35LklMexo0YVHdg==" }, "to-regex-range": { "version": "5.0.1", @@ -37556,26 +37506,14 @@ "dev": true }, "tsconfig-paths": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.1.tgz", - "integrity": "sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", "dev": true, "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.1", + "json5": "^2.2.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" - }, - "dependencies": { - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - } } }, "tsconfig-paths-webpack-plugin": { @@ -37614,6 +37552,15 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -37622,13 +37569,25 @@ "requires": { "has-flag": "^4.0.0" } + }, + "tsconfig-paths": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", + "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "dev": true, + "requires": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } } } }, "tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz", + "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA==" }, "tsscmp": { "version": "1.0.6", @@ -37680,9 +37639,9 @@ } }, "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", "dev": true }, "type-is": { @@ -37695,6 +37654,17 @@ "mime-types": "~2.1.24" } }, + "typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + } + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", @@ -37702,9 +37672,9 @@ "dev": true }, "typescript": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.3.tgz", - "integrity": "sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==", + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", "devOptional": true }, "uc.micro": { @@ -37779,18 +37749,6 @@ "vfile": "^5.0.0" } }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, "unique-string": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", @@ -37800,44 +37758,39 @@ "crypto-random-string": "^2.0.0" } }, - "unist-builder": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-builder/-/unist-builder-3.0.0.tgz", - "integrity": "sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==", + "unist-util-generated": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.1.tgz", + "integrity": "sha512-qF72kLmPxAw0oN2fwpWIqbXAVyEqUzDHMsbtPvOudIlUzXYFIeQIuxXQCRCFh22B7cixvU0MG7m3MW8FTq/S+A==" + }, + "unist-util-is": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.2.1.tgz", + "integrity": "sha512-u9njyyfEh43npf1M+yGKDGVPbY/JWEemg5nH05ncKPfi+kBbKBJoTdsogMu33uhytuLlv9y0O7GH7fEdwLdLQw==", "requires": { "@types/unist": "^2.0.0" } }, - "unist-util-generated": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-generated/-/unist-util-generated-2.0.0.tgz", - "integrity": "sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==" - }, - "unist-util-is": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-5.1.1.tgz", - "integrity": "sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==" - }, "unist-util-position": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.3.tgz", - "integrity": "sha512-p/5EMGIa1qwbXjA+QgcBXaPWjSnZfQ2Sc3yBEEfgPwsEmJd8Qh+DSk3LGnmOM4S1bY2C0AjmMnB8RuEYxpPwXQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-4.0.4.tgz", + "integrity": "sha512-kUBE91efOWfIVBo8xzh/uZQ7p9ffYRtUbMRZBNFYwf0RK8koUMx6dGUfwylLOKmaT2cs4wSW96QoYUSXAyEtpg==", "requires": { "@types/unist": "^2.0.0" } }, "unist-util-stringify-position": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.2.tgz", - "integrity": "sha512-7A6eiDCs9UtjcwZOcCpM4aPII3bAAGv13E96IkawkOAW0OhH+yRxtY0lzo8KiHpzEMfH7Q+FizUmwp8Iqy5EWg==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz", + "integrity": "sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg==", "requires": { "@types/unist": "^2.0.0" } }, "unist-util-visit": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.1.tgz", - "integrity": "sha512-n9KN3WV9k4h1DxYR1LoajgN93wpEi/7ZplVe02IoB4gH5ctI1AaF2670BLHQYbwj+pY83gFtyeySFiyMHJklrg==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-4.1.2.tgz", + "integrity": "sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==", "requires": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0", @@ -37845,9 +37798,9 @@ } }, "unist-util-visit-parents": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.1.tgz", - "integrity": "sha512-gks4baapT/kNRaWxuGkl5BIhoanZo7sC/cUT/JToSRNL1dYoXRFl75d++NkjYk4TAu2uv2Px+l8guMajogeuiw==", + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-5.1.3.tgz", + "integrity": "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==", "requires": { "@types/unist": "^2.0.0", "unist-util-is": "^5.0.0" @@ -37883,55 +37836,9 @@ }, "dependencies": { "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", - "dev": true - } - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true } } @@ -37943,9 +37850,10 @@ "dev": true }, "update-browserslist-db": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", - "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.11.tgz", + "integrity": "sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==", + "dev": true, "requires": { "escalade": "^3.1.1", "picocolors": "^1.0.0" @@ -37960,18 +37868,6 @@ "punycode": "^2.1.0" } }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, "use-callback-ref": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.0.tgz", @@ -37992,6 +37888,15 @@ "integrity": "sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==", "requires": {} }, + "use-resize-observer": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/use-resize-observer/-/use-resize-observer-9.1.0.tgz", + "integrity": "sha512-R25VqO9Wb3asSD4eqtcxk8sJalvIOYBqS8MNZlpDSQ4l4xMQxC/J7Id9HoTqPq8FwULIn0PVW+OAqF2dyYbjow==", + "dev": true, + "requires": { + "@juggle/resize-observer": "^3.3.1" + } + }, "use-sidecar": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", @@ -38051,12 +37956,6 @@ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" }, - "uuid-browser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid-browser/-/uuid-browser-3.1.0.tgz", - "integrity": "sha512-dsNgbLaTrd6l3MMxTtouOCFw4CBFc/3a+GgYA2YyrJvyQ1u6q4pcu3ktLoUZ/VN/Aw9WsauazbgsgdfVWgAKQg==", - "dev": true - }, "uuidv4": { "version": "6.2.13", "resolved": "https://registry.npmjs.org/uuidv4/-/uuidv4-6.2.13.tgz", @@ -38075,12 +37974,19 @@ "diff": "^5.0.0", "kleur": "^4.0.3", "sade": "^1.7.3" + }, + "dependencies": { + "kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==" + } } }, "v8-to-istanbul": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.0.1.tgz", - "integrity": "sha512-74Y4LqY74kLE6IFyIjPtkSTWzUZmj8tdHT9Ii/26dvQ6K9Dl2NbEfj0XgU2sHCtKgt5VupqhlO/5aWuqS+IY1w==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", "dev": true, "requires": { "@jridgewell/trace-mapping": "^0.3.12", @@ -38105,9 +38011,9 @@ "dev": true }, "vfile": { - "version": "5.3.5", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.5.tgz", - "integrity": "sha512-U1ho2ga33eZ8y8pkbQLH54uKqGhFJ6GYIHnnG5AhRpAh3OWjkrRHKa/KogbmQn8We+c0KVV3rTOgR9V/WowbXQ==", + "version": "5.3.7", + "resolved": "https://registry.npmjs.org/vfile/-/vfile-5.3.7.tgz", + "integrity": "sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==", "requires": { "@types/unist": "^2.0.0", "is-buffer": "^2.0.0", @@ -38116,9 +38022,9 @@ } }, "vfile-message": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.2.tgz", - "integrity": "sha512-QjSNP6Yxzyycd4SVOtmKKyTsSvClqBPJcd00Z0zuPj3hOIjg0rUPG6DbFGPvUKRgYyaIWLPKpuEclcuvb3H8qA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-3.1.4.tgz", + "integrity": "sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==", "requires": { "@types/unist": "^2.0.0", "unist-util-stringify-position": "^3.0.0" @@ -38154,22 +38060,22 @@ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" }, "webpack": { - "version": "5.76.1", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.76.1.tgz", - "integrity": "sha512-4+YIK4Abzv8172/SGqObnUjaIHjLEuUasz9EwQj/9xmPPkYJy2Mh03Q/lJfSD3YLzbxy5FeTq5Uw0323Oh6SJQ==", + "version": "5.83.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.83.1.tgz", + "integrity": "sha512-TNsG9jDScbNuB+Lb/3+vYolPplCS3bbEaJf+Bj0Gw4DhP3ioAflBb1flcRt9zsWITyvOhM96wMQNRWlSX52DgA==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", - "@types/estree": "^0.0.51", - "@webassemblyjs/ast": "1.11.1", - "@webassemblyjs/wasm-edit": "1.11.1", - "@webassemblyjs/wasm-parser": "1.11.1", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", "acorn": "^8.7.1", "acorn-import-assertions": "^1.7.6", "browserslist": "^4.14.5", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.10.0", - "es-module-lexer": "^0.9.0", + "enhanced-resolve": "^5.14.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", @@ -38178,41 +38084,31 @@ "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^3.1.0", + "schema-utils": "^3.1.2", "tapable": "^2.1.1", - "terser-webpack-plugin": "^5.1.3", + "terser-webpack-plugin": "^5.3.7", "watchpack": "^2.4.0", "webpack-sources": "^3.2.3" }, "dependencies": { + "@types/estree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.1.tgz", + "integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==", + "dev": true + }, "acorn": { - "version": "8.8.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz", - "integrity": "sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==", + "version": "8.8.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", + "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", "dev": true }, "acorn-import-assertions": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", - "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "dev": true, "requires": {} - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true } } }, @@ -38257,15 +38153,15 @@ "dev": true }, "schema-utils": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", - "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.1.tgz", + "integrity": "sha512-lELhBAAly9NowEsX0yZBlw9ahZG+sK/1RJ21EpzdYHKEs13Vku3LJ+MIPhh4sMs0oCCeufZQEQbMekiA4vuVIQ==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "ajv": "^8.8.0", + "ajv": "^8.9.0", "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.0.0" + "ajv-keywords": "^5.1.0" } } } @@ -38418,9 +38314,9 @@ } }, "ws": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", - "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", + "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", "dev": true, "requires": {} }, @@ -38437,14 +38333,15 @@ "dev": true }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true }, "yaml": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.1.tgz", - "integrity": "sha512-e0WHiYql7+9wr4cWMx3TVQrNwejKaEe7/rHNmQmqRjazfOP5W8PB6Jpebb5o6fIapbz9o9+2ipcaTM2ZwDI6lw==" + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz", + "integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==" }, "yargs": { "version": "16.2.0", diff --git a/frontend/package.json b/frontend/package.json index d53e40ca7..9d5071736 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,7 +19,7 @@ "@fortawesome/free-brands-svg-icons": "^6.1.2", "@fortawesome/free-regular-svg-icons": "^6.1.1", "@fortawesome/free-solid-svg-icons": "^6.1.2", - "@fortawesome/react-fontawesome": "^0.1.19", + "@fortawesome/react-fontawesome": "^0.2.0", "@headlessui/react": "^1.7.7", "@hookform/resolvers": "^2.9.10", "@octokit/rest": "^19.0.7", @@ -31,11 +31,13 @@ "@radix-ui/react-hover-card": "^1.0.3", "@radix-ui/react-label": "^2.0.0", "@radix-ui/react-popover": "^1.0.3", + "@radix-ui/react-popper": "^1.1.1", "@radix-ui/react-progress": "^1.0.1", "@radix-ui/react-select": "^1.2.0", "@radix-ui/react-switch": "^1.0.1", "@radix-ui/react-tabs": "^1.0.2", "@radix-ui/react-toast": "^1.1.2", + "@radix-ui/react-tooltip": "^1.0.4", "@reduxjs/toolkit": "^1.8.3", "@stripe/react-stripe-js": "^1.16.3", "@stripe/stripe-js": "^1.46.0", @@ -49,17 +51,21 @@ "classnames": "^2.3.1", "cookies": "^0.8.0", "cva": "npm:class-variance-authority@^0.4.0", - "fs": "^0.0.1-security", + "framer-motion": "^6.2.3", + "fs": "^0.0.2", "gray-matter": "^4.0.3", "http-proxy": "^1.18.1", - "i18next": "^22.4.9", + "i18next": "^22.4.15", + "i18next-browser-languagedetector": "^7.0.1", + "i18next-http-backend": "^2.2.0", "infisical-node": "^1.0.37", "jspdf": "^2.5.1", "jsrp": "^0.2.4", + "lottie-react": "^2.4.0", + "jwt-decode": "^3.1.2", "markdown-it": "^13.0.1", "next": "^12.3.4", - "next-i18next": "^13.0.2", - "posthog-js": "^1.39.4", + "posthog-js": "^1.58.0", "query-string": "^7.1.3", "react": "^17.0.2", "react-beautiful-dnd": "^13.1.1", @@ -67,20 +73,20 @@ "react-dom": "^17.0.2", "react-grid-layout": "^1.3.4", "react-hook-form": "^7.43.0", - "react-i18next": "^12.1.1", + "react-i18next": "^12.2.2", "react-mailchimp-subscribe": "^2.1.3", "react-markdown": "^8.0.3", "react-redux": "^8.0.2", "react-table": "^7.8.0", "set-cookie-parser": "^2.5.1", - "sharp": "^0.31.2", + "sharp": "^0.32.0", "styled-components": "^5.3.7", "tailwind-merge": "^1.8.1", "tweetnacl": "^1.0.3", "tweetnacl-util": "^0.15.1", "uuid": "^8.3.2", "uuidv4": "^6.2.13", - "yaml": "^2.2.0", + "yaml": "^2.2.2", "yup": "^0.32.11" }, "devDependencies": { diff --git a/frontend/public/data/frequentConstants.ts b/frontend/public/data/frequentConstants.ts index 8a69465ac..e873f1a72 100644 --- a/frontend/public/data/frequentConstants.ts +++ b/frontend/public/data/frequentConstants.ts @@ -12,9 +12,13 @@ const integrationSlugNameMapping: Mapping = { 'github': 'GitHub', 'gitlab': 'GitLab', 'render': 'Render', + 'railway': 'Railway', 'flyio': 'Fly.io', 'circleci': 'CircleCI', - 'travisci': 'TravisCI' + 'travisci': 'TravisCI', + 'supabase': 'Supabase', + 'checkly': 'Checkly', + 'hashicorp-vault': 'Vault' } const envMapping: Mapping = { diff --git a/frontend/public/images/gradientLogo.svg b/frontend/public/images/gradientLogo.svg new file mode 100644 index 000000000..7698d8e90 --- /dev/null +++ b/frontend/public/images/gradientLogo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/frontend/public/images/integrations/Checkly.png b/frontend/public/images/integrations/Checkly.png new file mode 100644 index 000000000..563513d4b Binary files /dev/null and b/frontend/public/images/integrations/Checkly.png differ diff --git a/frontend/public/images/integrations/Railway.png b/frontend/public/images/integrations/Railway.png new file mode 100644 index 000000000..61d53cf62 Binary files /dev/null and b/frontend/public/images/integrations/Railway.png differ diff --git a/frontend/public/images/integrations/Supabase.png b/frontend/public/images/integrations/Supabase.png new file mode 100644 index 000000000..843be59ca Binary files /dev/null and b/frontend/public/images/integrations/Supabase.png differ diff --git a/frontend/public/images/integrations/Vault.png b/frontend/public/images/integrations/Vault.png new file mode 100644 index 000000000..3cba8d11d Binary files /dev/null and b/frontend/public/images/integrations/Vault.png differ diff --git a/frontend/public/locales/en/activity.json b/frontend/public/locales/en/activity.json deleted file mode 100644 index 4db29f274..000000000 --- a/frontend/public/locales/en/activity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Audit Logs", - "subtitle": "Event history for this Infisical project.", - "event": { - "readSecrets": "Secrets Viewed", - "updateSecrets": "Secrets Updated", - "addSecrets": "Secrets Added", - "deleteSecrets": "Secrets Deleted" - }, - "ip-address": "IP Address" -} diff --git a/frontend/public/locales/en/billing.json b/frontend/public/locales/en/billing.json deleted file mode 100644 index 20c43c0a3..000000000 --- a/frontend/public/locales/en/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Usage & Billing", - "description": "View and manage your organization's subscription here", - "subscription": "Subscription", - "starter": { - "name": "Starter", - "price-explanation": "up to 5 team members", - "text": "Manage any project with 5 members for free!", - "subtext": "$5 per member/month afterwards." - }, - "professional": { - "name": "Professional", - "price-explanation": "/member/month", - "subtext": "Includes unlimited projects & members.", - "text": "Keep up with key management as you grow." - }, - "enterprise": { - "name": "Enterprise", - "text": "Keep up with key management as you grow." - }, - "current-usage": "Current Usage", - "free": "Free", - "downgrade": "Downgrade", - "upgrade": "Upgrade", - "learn-more": "Learn More", - "custom-pricing": "Custom Pricing", - "schedule-demo": "Schedule a Demo" -} diff --git a/frontend/public/locales/en/common.json b/frontend/public/locales/en/common.json deleted file mode 100644 index 4c966f09c..000000000 --- a/frontend/public/locales/en/common.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "A project with this name already exists.", - "no-mobile": " To use Infisical, please log in through a device with larger dimensions. ", - "email": "Email", - "password": "Password", - "first-name": "First Name", - "last-name": "Last Name", - "logout": "Log Out", - "validate-required": "Please input your {{name}}", - "maintenance-alert": "We are experiencing minor technical difficulties. We are working on solving it right now. Please come back in a few minutes.", - "click-to-copy": "Click to copy", - "project-id": "Project ID", - "save-changes": "Save Changes", - "saved": "Saved", - "drop-zone": "Drag and drop a .env, .json, or .yml file here.", - "drop-zone-keys": "Drag and drop a .env, .json, or .yml file here to add more secrets.", - "role": "Role", - "role_admin": "admin", - "display-name": "Display Name", - "environment": "Environment", - "expired-in": "Expires in", - "language": "Language", - "search": "Search...", - "note": "Note", - "view-more": "View More", - "end-of-history": "End of History", - "select-event": "Select an event", - "event": "Event", - "user": "User", - "source": "Source", - "time": "Time", - "timestamp": "Timestamp" -} \ No newline at end of file diff --git a/frontend/public/locales/en/dashboard.json b/frontend/public/locales/en/dashboard.json deleted file mode 100644 index 263887360..000000000 --- a/frontend/public/locales/en/dashboard.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "title": "Secrets", - "og-title": "Manage your .env files in seconds", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", - "search-keys": "Search keys...", - "add-key": "Add Key", - "personal": "Personal", - "personal-description": "Personal keys are only visible to you", - "shared": "Shared", - "shared-description": "Shared keys are visible to your whole team", - "make-shared": "Make Shared", - "make-personal": "Make Personal", - "add-secret": "Add a new secret", - "check-docs": { - "button": "Check Docs", - "title": "Good job!", - "line1": "Congrats on adding more secrets.", - "line2": "Here is how to connect them to your codebase." - }, - "sidebar": { - "secret": "Secret", - "key": "Key", - "value": "Value", - "override": "Override value with a personal value", - "version-history": "Version History", - "comments": "Comments & Notes", - "personal-explanation": "This secret is personal. It is not shared with any of your teammates.", - "generate-random-hex": "Generate Random Hex", - "digits": "digits", - "delete-key-dialog": { - "title": "Delete Key", - "confirm-delete-message": "Are you sure you want to delete this secret? This cannot be undone." - } - } - -} diff --git a/frontend/public/locales/en/integrations.json b/frontend/public/locales/en/integrations.json deleted file mode 100644 index 1fc92ca4e..000000000 --- a/frontend/public/locales/en/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Project Integrations", - "description": "Manage your integrations of Infisical with third-party services.", - "no-integrations1": "You don't have any integrations set up yet. When you do, they will appear here.", - "no-integrations2": "To start, click on any of the options below. It takes 5 clicks to set up.", - "available": "Platform & Cloud Integrations", - "available-text1": "Click on the integration you want to connect. This will let your environment variables flow automatically into selected third-party services.", - "available-text2": "Note: during an integration with Heroku, for security reasons, it is impossible to maintain end-to-end encryption. In theory, this lets Infisical decrypt yor environment variables. In practice, we can assure you that this will never be done, and it allows us to protect your secrets from bad actors online. The core Infisical service will always stay end-to-end encrypted. With any questions, reach out support@infisical.com.", - "cloud-integrations": "Cloud Integrations", - "framework-integrations": "Framework Integrations", - "click-to-start": "Click on an integration to begin syncing secrets to it.", - "click-to-setup": "Click on a framework to get the setup instructions.", - "grant-access-to-secrets": "Grant Infisical access to your secrets", - "why-infisical-needs-access": "Most cloud integrations require Infisical to be able to decrypt your secrets so they can be forwarded over.", - "grant-access-button": "Grant access" -} diff --git a/frontend/public/locales/en/login.json b/frontend/public/locales/en/login.json deleted file mode 100644 index 75b56a014..000000000 --- a/frontend/public/locales/en/login.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "Login", - "og-title": "Log In to Infisical", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", - "login": "Log In", - "need-account": "Need an Infisical account?", - "create-account": "Create an account", - "forgot-password": "Forgot your password?", - "error-login": "Wrong credentials." -} diff --git a/frontend/public/locales/en/mfa.json b/frontend/public/locales/en/mfa.json deleted file mode 100644 index 2cc50c509..000000000 --- a/frontend/public/locales/en/mfa.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Sign Up", - "og-title": "Replace .env files with 1 line of code. Sign Up for Infisical in 3 minutes.", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage API-keys and environemntal variables. Works with Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Sign Up", - "already-have-account": "Have an account? Log in", - "forgot-password": "Forgot your password?", - "verify": "Verify", - "step1-start": "Let's get started", - "step1-privacy": "By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.", - "step1-submit": "Get Started", - "step2-message": "We've sent a verification code to", - "step2-code-error": "Oops. Your code is wrong. Tries left:", - "step2-resend-alert": "Don't see the code?", - "step2-resend-submit": "Resend", - "step2-resend-progress": "Resending...", - "step2-spam-alert": "Make sure to check your spam inbox.", - "step3-message": "Almost there!", - "step4-message": "Save your Emergency Kit", - "step4-description1": "If you get locked out of your account, your Emergency Kit is the only way to sign in.", - "step4-description2": "We recommend you download it and keep it somewhere safe.", - "step4-description3": "It contains your Secret Key which we cannot access or recover for you if you lose it.", - "step4-download": "Download PDF", - "step5-send-invites": "Send Invites", - "step5-invite-team": "Invite your team", - "step5-subtitle": "Infisical is meant to be used with your teammates. Invite them to test it out.", - "step5-skip": "Skip" -} diff --git a/frontend/public/locales/en/nav.json b/frontend/public/locales/en/nav.json deleted file mode 100644 index 3d0c6faca..000000000 --- a/frontend/public/locales/en/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "Join Slack Forum", - "docs": "Read Docs", - "issue": "Open a Github Issue", - "email": "Send us an Email" - }, - "user": { - "signed-in-as": "SIGNED IN AS", - "current-organization": "CURRENT ORGANIZATION", - "usage-billing": "Usage & Billing", - "invite": "Invite Members", - "other-organizations": "OTHER ORGANIZATION" - }, - "menu": { - "project": "PROJECT", - "secrets": "Secrets", - "members": "Members", - "integrations": "Integrations", - "project-settings": "Project Settings" - } -} diff --git a/frontend/public/locales/en/section-api-key.json b/frontend/public/locales/en/section-api-key.json deleted file mode 100644 index 3419744fe..000000000 --- a/frontend/public/locales/en/section-api-key.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "api-keys": "Service Tokens", - "api-keys-description": "Every service token is specific to you, a certain project and a certain environment within this project.", - "add-new": "Add New Token", - "add-dialog": { - "title": "Add an API Key", - "description": "Specify the name and expiry period. When an API key is generated, you will only be able to see it once before it disappears. Make sure to save it somewhere.", - "name": "API Key Name", - "add": "Add API Key", - "copy-service-token": "Copy your API key", - "copy-service-token-description": "Once you close this popup, you will never see your API key again" - } -} diff --git a/frontend/public/locales/en/section-incident.json b/frontend/public/locales/en/section-incident.json deleted file mode 100644 index de8f3e7b7..000000000 --- a/frontend/public/locales/en/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "incident-contacts": "Incident Contacts", - "incident-contacts-description": "These contacts will be notified in the unlikely event of a severe incident.", - "no-incident-contacts": "No incident contacts found.", - "add-contact": "Add Contact", - "add-dialog": { - "title": "Add an Incident Contact", - "description": "This contact will be notified in the unlikely event of a severe incident.", - "add-incident": "Add Incident Contact" - } -} diff --git a/frontend/public/locales/en/section-members.json b/frontend/public/locales/en/section-members.json deleted file mode 100644 index 89dbd2fea..000000000 --- a/frontend/public/locales/en/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "Add Member", - "org-members": "Organization Members", - "org-members-description": "Manage members of your organization. These users could afterwards be formed into projects.", - "search-members": "Search members...", - "add-dialog": { - "add-member-to-project": "Add a member to your project", - "already-all-invited": "All the users in your organization are already invited.", - "add-user-org-first": "Add more users to the organization first.", - "user-will-email": "The user will receive an email with the instructions.", - "looking-add": "<0>If you are looking to add users to your org,<1>click here", - "add-user-to-org": "Add Users to Organization" - } -} diff --git a/frontend/public/locales/en/section-password.json b/frontend/public/locales/en/section-password.json deleted file mode 100644 index 9c0410d6c..000000000 --- a/frontend/public/locales/en/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "Password", - "change": "Change password", - "current": "Current password", - "current-wrong": "The current password may be wrong", - "new": "New password", - "validate-base": "Password should contain at least:", - "validate-length": "14 characters", - "validate-case": "1 lowercase character", - "validate-number": "1 number" -} diff --git a/frontend/public/locales/en/section-token.json b/frontend/public/locales/en/section-token.json deleted file mode 100644 index ce468b1af..000000000 --- a/frontend/public/locales/en/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "service-tokens": "Service Tokens", - "service-tokens-description": "Every service token is specific to you, a certain project and a certain environment within this project.", - "add-new": "Add New Token", - "add-dialog": { - "title": "Add a service token for {{target}}", - "description": "When a token is generated, you will only be able to see it once before it disappears. Make sure to save it somewhere.", - "name": "Service Token Name", - "add": "Add Service Token", - "copy-service-token": "Copy your service token", - "copy-service-token-description": "Once you close this popup, you will never see your service token again" - } -} diff --git a/frontend/public/locales/en/settings-members.json b/frontend/public/locales/en/settings-members.json deleted file mode 100644 index 128a649a0..000000000 --- a/frontend/public/locales/en/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Project Members", - "description": "This page shows the members of the selected project, and allows you to modify their permissions." -} diff --git a/frontend/public/locales/en/settings-org.json b/frontend/public/locales/en/settings-org.json deleted file mode 100644 index d17baa7cd..000000000 --- a/frontend/public/locales/en/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Organization Settings", - "description": "Manage members of your organization. These users could afterwards be formed into projects." -} diff --git a/frontend/public/locales/en/settings-personal.json b/frontend/public/locales/en/settings-personal.json deleted file mode 100644 index 66a90b6c3..000000000 --- a/frontend/public/locales/en/settings-personal.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Personal Settings", - "description": "View and manage your personal information here.", - "emergency": { - "name": "Emergency Kit", - "text1": "Your Emergency Kit contains the information you’ll need to sign in to your Infisical account.", - "text2": "Only the latest issued Emergency Kit remains valid. To get a new Emergency Kit, verify your password.", - "download": "Download Emergency Kit" - }, - "change-language": "Change Language", - "api-keys": { - "title": "API Keys", - "description": "Manage your personal API Keys to access the Infisical API.", - "add-new": "Add new" - } -} diff --git a/frontend/public/locales/en/settings-project.json b/frontend/public/locales/en/settings-project.json deleted file mode 100644 index 3f3401f2e..000000000 --- a/frontend/public/locales/en/settings-project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "Project Settings", - "description": "These settings only apply to the currently selected Project.", - "danger-zone": "Danger Zone", - "delete-project": "Delete Project", - "project-to-delete": "Project to be Deleted", - "danger-zone-note": "As soon as you delete this project, you will not be able to undo it. This will immediately remove all the keys. If you still want to do that, please enter the name of the project below.", - "delete-project-note": "Note: You can only delete a project in case you have more than one", - "project-id-description": "To integrate Infisical into your code base and get automatic injection of environmental variables, you should use the following Project ID.", - "project-id-description2": "For more guidance, including code snipets for various languages and frameworks, see ", - "auto-generated": "This is your project's auto-generated unique identifier. It can't be changed.", - "docs": "Infisical Docs", - "auto-capitalization": "Auto Capitalization", - "auto-capitalization-description": "According to standards, Infisical will automatically capitalize your keys. If you want to disable this feature, you can do so here." -} diff --git a/frontend/public/locales/en/signup.json b/frontend/public/locales/en/signup.json deleted file mode 100644 index 5fa5742e3..000000000 --- a/frontend/public/locales/en/signup.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Sign Up", - "og-title": "Replace .env files with 1 line of code. Sign Up for Infisical in 3 minutes.", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage API-keys and environemntal variables. Works with Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Sign Up", - "already-have-account": "Have an account? Log in", - "forgot-password": "Forgot your password?", - "verify": "Verify", - "step1-start": "Let's get started", - "step1-privacy": "By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.", - "step1-submit": "Get Started", - "step2-message": "We've sent a verification code to", - "step2-code-error": "Oops. Your code is wrong. Please try again.", - "step2-resend-alert": "Don't see the code?", - "step2-resend-submit": "Resend", - "step2-resend-progress": "Resending...", - "step2-spam-alert": "Make sure to check your spam inbox.", - "step3-message": "Almost there!", - "step4-message": "Save your Emergency Kit", - "step4-description1": "If you get locked out of your account, your Emergency Kit is the only way to sign in.", - "step4-description2": "We recommend you download it and keep it somewhere safe.", - "step4-description3": "It contains your Secret Key which we cannot access or recover for you if you lose it.", - "step4-download": "Download PDF", - "step5-send-invites": "Send Invites", - "step5-invite-team": "Invite your team", - "step5-subtitle": "Infisical is meant to be used with your teammates. Invite them to test it out.", - "step5-skip": "Skip" -} diff --git a/frontend/public/locales/en/translations.json b/frontend/public/locales/en/translations.json new file mode 100644 index 000000000..c387d938b --- /dev/null +++ b/frontend/public/locales/en/translations.json @@ -0,0 +1,326 @@ +{ + "activity": { + "title": "Audit Logs", + "subtitle": "Event history for this Infisical project.", + "event": { + "readSecrets": "Secrets Viewed", + "updateSecrets": "Secrets Updated", + "addSecrets": "Secrets Added", + "deleteSecrets": "Secrets Deleted" + }, + "ip-address": "IP Address" + }, + "billing": { + "title": "Usage & Billing", + "description": "View and manage your organization's subscription here", + "subscription": "Subscription", + "starter": { + "name": "Starter", + "price-explanation": "up to 5 team members", + "text": "Manage up to 3 project with up to 5 team members for free!", + "subtext": "" + }, + "professional": { + "name": "Professional", + "price-explanation": "/member/month", + "subtext": "Includes unlimited projects & members.", + "text": "Keep up with key management as you grow." + }, + "enterprise": { + "name": "Enterprise", + "text": "Keep up with key management as you grow." + }, + "current-usage": "Current Usage", + "free": "Free", + "downgrade": "Downgrade", + "upgrade": "Upgrade", + "learn-more": "Learn More", + "custom-pricing": "Custom Pricing", + "schedule-demo": "Schedule a Demo" + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "A project with this name already exists.", + "no-mobile": " To use Infisical, please log in through a device with larger dimensions. ", + "email": "Email", + "password": "Password", + "first-name": "First Name", + "last-name": "Last Name", + "logout": "Log Out", + "validate-required": "Please input your {{name}}", + "maintenance-alert": "We are experiencing minor technical difficulties. We are working on solving it right now. Please come back in a few minutes.", + "click-to-copy": "Click to copy", + "project-id": "Project ID", + "save-changes": "Save Changes", + "saved": "Saved", + "drop-zone": "Drag and drop a .env, .json, or .yml file here.", + "drop-zone-keys": "Drag and drop a .env, .json, or .yml file here to add more secrets.", + "role": "Role", + "role_admin": "admin", + "display-name": "Display Name", + "environment": "Environment", + "expired-in": "Expires in", + "language": "Language", + "search": "Search...", + "note": "Note", + "view-more": "View More", + "end-of-history": "End of History", + "select-event": "Select an event", + "event": "Event", + "user": "User", + "source": "Source", + "time": "Time", + "timestamp": "Timestamp" + }, + "dashboard": { + "title": "Secrets", + "og-title": "Manage your .env files in seconds", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", + "search-keys": "Search keys...", + "add-key": "Add Key", + "personal": "Personal", + "personal-description": "Personal keys are only visible to you", + "shared": "Shared", + "shared-description": "Shared keys are visible to your whole team", + "make-shared": "Make Shared", + "make-personal": "Make Personal", + "add-secret": "Add a new secret", + "check-docs": { + "button": "Check Docs", + "title": "Good job!", + "line1": "Congrats on adding more secrets.", + "line2": "Here is how to connect them to your codebase." + }, + "sidebar": { + "secret": "Secret", + "key": "Key", + "value": "Value", + "override": "Override value with a personal value", + "version-history": "Version History", + "comments": "Comments & Notes", + "personal-explanation": "This secret is personal. It is not shared with any of your teammates.", + "generate-random-hex": "Generate Random Hex", + "digits": "digits", + "delete-key-dialog": { + "title": "Delete Key", + "confirm-delete-message": "Are you sure you want to delete this secret? This cannot be undone." + } + } + }, + "integrations": { + "title": "Project Integrations", + "description": "Manage your integrations of Infisical with third-party services.", + "no-integrations1": "You don't have any integrations set up yet. When you do, they will appear here.", + "no-integrations2": "To start, click on any of the options below. It takes 5 clicks to set up.", + "available": "Platform & Cloud Integrations", + "available-text1": "Click on the integration you want to connect. This will let your environment variables flow automatically into selected third-party services.", + "available-text2": "Note: during an integration with Heroku, for security reasons, it is impossible to maintain end-to-end encryption. In theory, this lets Infisical decrypt yor environment variables. In practice, we can assure you that this will never be done, and it allows us to protect your secrets from bad actors online. The core Infisical service will always stay end-to-end encrypted. With any questions, reach out support@infisical.com.", + "cloud-integrations": "Cloud Integrations", + "framework-integrations": "Framework Integrations", + "click-to-start": "Click on an integration to begin syncing secrets to it.", + "click-to-setup": "Click on a framework to get the setup instructions.", + "grant-access-to-secrets": "Grant Infisical access to your secrets", + "why-infisical-needs-access": "Most cloud integrations require Infisical to be able to decrypt your secrets so they can be forwarded over.", + "grant-access-button": "Grant access" + }, + "login": { + "title": "Login", + "og-title": "Log In to Infisical", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", + "login": "Log In", + "need-account": "Need an Infisical account?", + "create-account": "Create an account", + "forgot-password": "Forgot your password?", + "error-login": "Wrong credentials.", + "continue-with-google": "Continue with Google", + "continue-with-email": "Continue with Email", + "other-option": "Log in with another option" + }, + "mfa": { + "title": "Sign Up", + "og-title": "Replace .env files with 1 line of code. Sign Up for Infisical in 3 minutes.", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage API-keys and environemntal variables. Works with Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Sign Up", + "already-have-account": "Have an account? Log in", + "forgot-password": "Forgot your password?", + "verify": "Verify", + "step1-start": "Let's get started", + "step1-privacy": "By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.", + "step1-submit": "Get Started", + "step2-message": "We've sent a verification code to", + "step2-code-error": "Oops. Your code is wrong. Tries left:", + "step2-resend-alert": "Don't see the code?", + "step2-resend-submit": "Resend", + "step2-resend-progress": "Resending...", + "step2-spam-alert": "Make sure to check your spam inbox.", + "step3-message": "Almost there!", + "step4-message": "Save your Emergency Kit", + "step4-description1": "If you get locked out of your account, your Emergency Kit is the only way to sign in.", + "step4-description2": "We recommend you download it and keep it somewhere safe.", + "step4-description3": "It contains your Secret Key which we cannot access or recover for you if you lose it.", + "step4-download": "Download PDF", + "step5-send-invites": "Send Invites", + "step5-invite-team": "Invite your team", + "step5-subtitle": "Infisical is meant to be used with your teammates. Invite them to test it out.", + "step5-skip": "Skip" + }, + "nav": { + "support": { + "slack": "Join Slack Forum", + "docs": "Read Docs", + "issue": "Open a Github Issue", + "email": "Send us an Email" + }, + "user": { + "signed-in-as": "SIGNED IN AS", + "current-organization": "CURRENT ORGANIZATION", + "usage-billing": "Usage & Billing", + "invite": "Invite Members", + "other-organizations": "OTHER ORGANIZATION" + }, + "menu": { + "project": "PROJECT", + "secrets": "Secrets", + "members": "Members", + "integrations": "Integrations", + "project-settings": "Project Settings" + } + }, + "section": { + "api-key": { + "api-keys": "Service Tokens", + "api-keys-description": "Every service token is specific to you, a certain project and a certain environment within this project.", + "add-new": "Add New Token", + "add-dialog": { + "title": "Add an API Key", + "description": "Specify the name and expiry period. When an API key is generated, you will only be able to see it once before it disappears. Make sure to save it somewhere.", + "name": "API Key Name", + "add": "Add API Key", + "copy-service-token": "Copy your API key", + "copy-service-token-description": "Once you close this popup, you will never see your API key again" + } + }, + "incident": { + "incident-contacts": "Incident Contacts", + "incident-contacts-description": "These contacts will be notified in the unlikely event of a severe incident.", + "no-incident-contacts": "No incident contacts found.", + "add-contact": "Add Contact", + "add-dialog": { + "title": "Add an Incident Contact", + "description": "This contact will be notified in the unlikely event of a severe incident.", + "add-incident": "Add Incident Contact" + } + }, + "members": { + "add-member": "Add Member", + "org-members": "Organization Members", + "org-members-description": "Manage members of your organization. These users could afterwards be formed into projects.", + "search-members": "Search members...", + "add-dialog": { + "add-member-to-project": "Add a member to your project", + "already-all-invited": "All the users in your organization are already invited.", + "add-user-org-first": "Add more users to the organization first.", + "user-will-email": "The user will receive an email with the instructions.", + "looking-add": "<0>If you are looking to add users to your org,<1>click here", + "add-user-to-org": "Add Users to Organization" + } + }, + "password": { + "password": "Password", + "change": "Change password", + "current": "Current password", + "current-wrong": "The current password may be wrong", + "new": "New password", + "validate-base": "Password should contain at least:", + "validate-length": "14 characters", + "validate-case": "1 lowercase character", + "validate-number": "1 number" + }, + "token": { + "service-tokens": "Service Tokens", + "service-tokens-description": "Every service token is specific to you, a certain project and a certain environment within this project.", + "add-new": "Add New Token", + "add-dialog": { + "title": "Add a service token for {{target}}", + "description": "When a token is generated, you will only be able to see it once before it disappears. Make sure to save it somewhere.", + "name": "Service Token Name", + "add": "Add Service Token", + "copy-service-token": "Copy your service token", + "copy-service-token-description": "Once you close this popup, you will never see your service token again" + } + } + }, + "settings": { + "members": { + "title": "Project Members", + "description": "This page shows the members of the selected project, and allows you to modify their permissions." + }, + "org": { + "title": "Organization Settings", + "description": "Manage members of your organization. These users could afterwards be formed into projects." + }, + "personal": { + "title": "Personal Settings", + "description": "View and manage your personal information here.", + "emergency": { + "name": "Emergency Kit", + "text1": "Your Emergency Kit contains the information you’ll need to sign in to your Infisical account.", + "text2": "Only the latest issued Emergency Kit remains valid. To get a new Emergency Kit, verify your password.", + "download": "Download Emergency Kit" + }, + "change-language": "Change Language", + "api-keys": { + "title": "API Keys", + "description": "Manage your personal API Keys to access the Infisical API.", + "add-new": "Add new" + } + }, + "project": { + "title": "Project Settings", + "description": "These settings only apply to the currently selected Project.", + "danger-zone": "Danger Zone", + "delete-project": "Delete Project", + "project-to-delete": "Project to be Deleted", + "danger-zone-note": "As soon as you delete this project, you will not be able to undo it. This will immediately remove all the keys. If you still want to do that, please enter the name of the project below.", + "delete-project-note": "Note: You can only delete a project in case you have more than one", + "project-id-description": "To integrate Infisical into your code base and get automatic injection of environmental variables, you should use the following Project ID.", + "project-id-description2": "For more guidance, including code snipets for various languages and frameworks, see ", + "auto-generated": "This is your project's auto-generated unique identifier. It can't be changed.", + "docs": "Infisical Docs", + "auto-capitalization": "Auto Capitalization", + "auto-capitalization-description": "According to standards, Infisical will automatically capitalize your keys. If you want to disable this feature, you can do so here." + } + }, + "signup": { + "title": "Sign Up", + "og-title": "Replace .env files with 1 line of code. Sign Up for Infisical in 3 minutes.", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage API-keys and environemntal variables. Works with Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Sign Up", + "already-have-account": "Have an account? Log in", + "forgot-password": "Forgot your password?", + "initial-title": "Create your Infisical account", + "continue-with-google": "Continue with Google", + "continue-with-email": "Continue with Email", + "create-policy": "By signing up, you agree to our Terms of Service and Privacy Policy.", + "verify": "Verify", + "step1-start": "Let's get started", + "step1-privacy": "By creating an account, you agree to our Terms and have read and acknowledged the Privacy Policy.", + "step1-submit": "Get Started", + "step2-message": "We've sent a verification code to", + "step2-code-error": "Oops. Your code is wrong. Please try again.", + "step2-resend-alert": "Don't see the code?", + "step2-resend-submit": "Resend", + "step2-resend-progress": "Resending...", + "step2-spam-alert": "Make sure to check your spam inbox.", + "step3-message": "Almost there!", + "step4-message": "Save your Emergency Kit", + "step4-description1": "If you get locked out of your account, your Emergency Kit is the only way to sign in.", + "step4-description2": "We recommend you download it and keep it somewhere safe.", + "step4-description3": "It contains your Secret Key which we cannot access or recover for you if you lose it.", + "step4-download": "Download PDF", + "step5-send-invites": "Send Invites", + "step5-invite-team": "Invite your team", + "step5-subtitle": "Infisical is meant to be used with your teammates. Invite them to test it out.", + "step5-skip": "Skip" + } +} diff --git a/frontend/public/locales/es/activity.json b/frontend/public/locales/es/activity.json deleted file mode 100644 index ef275e39c..000000000 --- a/frontend/public/locales/es/activity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Historial de eventos", - "subtitle": "Historial de eventos para este proyecto de Infisical.", - "event": { - "readSecrets": "Secrets vistas", - "updateSecrets": "Secrets actualizadas", - "addSecrets": "Secrets añadidas", - "deleteSecrets": "Secrets eliminadas" - }, - "ip-address": "Dirección IP" -} diff --git a/frontend/public/locales/es/billing.json b/frontend/public/locales/es/billing.json deleted file mode 100644 index 8ffc62c84..000000000 --- a/frontend/public/locales/es/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Uso & Facturación", - "description": "Visualiza y gestiona la suscripción de tu organización", - "subscription": "Suscripción", - "starter": { - "name": "Starter", - "price-explanation": "hasta 5 miembros", - "text": "¡Hasta 5 personas gratis!", - "subtext": "Después, $5 por miembro/mes." - }, - "professional": { - "name": "Professional", - "price-explanation": "/miembro/mes", - "subtext": "Includes unlimited projects & members.", - "text": "Mantén la gestión de claves a medida que creces." - }, - "enterprise": { - "name": "Enterprise", - "text": "Mantén la gestión de claves a medida que creces." - }, - "current-usage": "Uso actual", - "free": "Gratis", - "downgrade": "Reducir", - "upgrade": "Mejorar", - "learn-more": "Saber más", - "custom-pricing": "A medida", - "schedule-demo": "Solicitar una demo" -} diff --git a/frontend/public/locales/es/common.json b/frontend/public/locales/es/common.json deleted file mode 100644 index 8b0446085..000000000 --- a/frontend/public/locales/es/common.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "Ya existe un proyecto con este nombre.", - "no-mobile": "Para usar Infisical, inicia sesión con un dispositivo de mayores dimesiones.", - "email": "Correo electrónico", - "password": "Contraseña", - "first-name": "Nombre", - "last-name": "Apellidos", - "logout": "Cerrar sesión", - "validate-required": "Por favor, introduce tu {{name}}", - "maintenance-alert": "Estamos experimentando problemas técnicos. Estamos trabajando para resolverlos. Por favor, vuelve en unos minutos.", - "click-to-copy": "Click para copiar", - "project-id": "ID de proyecto", - "save-changes": "Guardar cambios", - "saved": "Guardado", - "drop-zone": "Arrastra y suelta un archivo .env, .json o .yml aquí.", - "drop-zone-keys": "Arrastra y suelta un archivo .env, .json, or .yml aquí para añadir más secrets.", - "role": "Rol", - "role_admin": "admin", - "display-name": "Nombre visible", - "environment": "Entorno", - "expired-in": "Expira en", - "language": "Idioma", - "search": "Buscar...", - "note": "Nota", - "view-more": "Ver más", - "end-of-history": "Fin del historial", - "select-event": "Selecciona un evento", - "event": "Evento", - "user": "Usuario", - "source": "Fuente", - "time": "Hora", - "timestamp": "Marca temporal" -} \ No newline at end of file diff --git a/frontend/public/locales/es/dashboard.json b/frontend/public/locales/es/dashboard.json deleted file mode 100644 index ac3cef0dd..000000000 --- a/frontend/public/locales/es/dashboard.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "title": "Secrets", - "og-title": "Gestiona tus archivos .env en segundos", - "og-description": "Infisical es una solución cifrada de extremo a extremo que habilita a los equipos a compartir archivos .env de forma sencilla.", - "search-keys": "Buscar claves...", - "add-key": "Añadir clave", - "personal": "Personal", - "personal-description": "Las claves personales solo son visibles para ti", - "shared": "Compartido", - "shared-description": "Claves compartidas son visibles para todo tu equipo", - "make-shared": "Hacer compartida", - "make-personal": "Hacer personal", - "add-secret": "Añadir una nueva clave", - "check-docs": { - "button": "Comprueba la documentación", - "title": "¡Buen trabajo!", - "line1": "Enhorabuena por añadir claves.", - "line2": "Averigua como usarlo desde tu código." - }, - "sidebar": { - "secret": "Secret", - "key": "Clave", - "value": "valor", - "override": "Sobreescribir valor con el valor personal", - "version-history": "Historial de versiones", - "comments": "Comentarios & Notas", - "personal-explanation": "Esta clave es personal. No será compartida con ninguno de tus compañeros.", - "generate-random-hex": "Generar Hex aleatorio", - "digits": "dígitos", - "delete-key-dialog": { - "title": "Eliminar clave", - "confirm-delete-message": "¿Estás seguro de que quieres eliminar esta clave? Esta operación no se puede deshacer." - } - } -} diff --git a/frontend/public/locales/es/integrations.json b/frontend/public/locales/es/integrations.json deleted file mode 100644 index 38d299d5a..000000000 --- a/frontend/public/locales/es/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Integraciones del proyecto", - "description": "Gestiona tus integraciones de Infisical con aplicaciones de terceros.", - "no-integrations1": "No tienes ninguna integración configurada. Cuando las tengas, aparecerán aquí.", - "no-integrations2": "Para empezar haz click en cualquiera de las opciones siguientes. Se necesitan tan solo 5 pasos.", - "available": "Integraciones con la nube", - "available-text1": "Haz click en la integración que quieras conectar. Esto hará que las variables de entorno se configuren automáticamente en los servicios de terceros seleccionados.", - "available-text2": "Nota: en la integración con Heroku, por motivos de seguridad, es imposible mantener el cifrado de extremo a extremo. En teoría, esto permite a Infisical descifrar tus variables de entorno. En la práctica, te podemos asegurar que esto nunca va a suceder. El núcleo del servicio Infisical siempre estará cifrado de extremo a extremo. Si tienes dudas, escríbenos a support@infisical.com.", - "cloud-integrations": "Integraciones con la nube", - "framework-integrations": "Integraciones con frameworks", - "click-to-start": "Haz click en una integración para empezar a sincronizar las claves.", - "click-to-setup": "Haz click en un framework para ver las instrucciones de uso.", - "grant-access-to-secrets": "Autorizar Infisical el acceso a tus claves", - "why-infisical-needs-access": "La mayoría de las integraciones en la nube requieren a Infisical tener permiso para descifrar tus claves, para que puedan ser enviadas.", - "grant-access-button": "Autorizar acceso" -} diff --git a/frontend/public/locales/es/login.json b/frontend/public/locales/es/login.json deleted file mode 100644 index 1fdd5b970..000000000 --- a/frontend/public/locales/es/login.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "Iniciar sesión", - "og-title": "Iniciar sesión en Infisical", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", - "login": "Iniciar sesión", - "need-account": "¿Necesitas una cuenta de Infisical?", - "create-account": "Crea una cuenta", - "forgot-password": "¿Has olvidado tu contraseña?", - "error-login": "Datos incorrectos." -} diff --git a/frontend/public/locales/es/mfa.json b/frontend/public/locales/es/mfa.json deleted file mode 100644 index 35d41adf5..000000000 --- a/frontend/public/locales/es/mfa.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Registrarse", - "og-title": "Reemplaza los archivos .env con una línea de código. Regístrate en Infisical en solo 3 minutos.", - "og-description": "Infisical es una plataforma sencilla cifrada de extremo a extremo que permite a equipos sincronizar y gestionar API-keys y variables de entorno. Funciona con Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Registrarse", - "already-have-account": "¿Ya tienes una cuenta? Inicia sesión", - "forgot-password": "¿Has olvidado tu contraseña?", - "verify": "Verificar", - "step1-start": "Vamos a empezar", - "step1-privacy": "Al crear la cuenta, aceptas nuestros Términos y has leído y comprendido nuestra Política de privacidad.", - "step1-submit": "Empezar", - "step2-message": "Hemos enviado un código a", - "step2-code-error": "Oops. Tu código es incorrecto. Intentos restantes:", - "step2-resend-alert": "¿No ves el código?", - "step2-resend-submit": "Volver a enviar", - "step2-resend-progress": "Reenviando...", - "step2-spam-alert": "Asegúrate de comprobar la carpeta de spam.", - "step3-message": "¡Casi hemos terminado!", - "step4-message": "Guarda tu Kit de emergencia", - "step4-description1": "Si pierdes el acceso a tu cuenta, tu Kit de emergencia es la única forma de iniciar sesión.", - "step4-description2": "Te recomendamos que lo descargues y lo guardes en un sitio seguro.", - "step4-description3": "Contiene tu Clave secreta, a la que no tenemos acceso y tampoco podemos recuperar si la pierdes.", - "step4-download": "Descargar PDF", - "step5-send-invites": "Enviar invitaciones", - "step5-invite-team": "Invita a tu equipo", - "step5-subtitle": "Infisical está pensado para usarlo con tus compañeros. Invítalos a probarlo.", - "step5-skip": "Saltar" -} diff --git a/frontend/public/locales/es/nav.json b/frontend/public/locales/es/nav.json deleted file mode 100644 index a83446626..000000000 --- a/frontend/public/locales/es/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "Unirse al Slack", - "docs": "Leer documentación", - "issue": "Abrir una Github Issue", - "email": "Envíanos un correo electrónico" - }, - "user": { - "signed-in-as": "INICIADO COMO", - "current-organization": "ORGANIZACIÓN ACTUAL", - "usage-billing": "Uso & Facturación", - "invite": "Invitar miembros", - "other-organizations": "OTRA ORGANIZACIÓN" - }, - "menu": { - "project": "PROYECTO", - "secrets": "Claves", - "members": "Miembros", - "integrations": "Integraciones", - "project-settings": "Configuración del proyecto" - } -} diff --git a/frontend/public/locales/es/section-api-key.json b/frontend/public/locales/es/section-api-key.json deleted file mode 100644 index bf385862b..000000000 --- a/frontend/public/locales/es/section-api-key.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "api-keys": "Tokens de servicio", - "api-keys-description": "Cada token de servicio es específico para ti, para cada proyecto y para cada entorno en este proyecto.", - "add-new": "Añadir nuevo token", - "add-dialog": { - "title": "Añadir una API Key", - "description": "Especifica el nombre y el período de expiración. Cuando una API key es generada, solo podrás verla una vez hasta que desaparezca. Asegúrate de guardarla en algún lado.", - "name": "Nombre de la API Key", - "add": "Añadir API Key", - "copy-service-token": "Copia tu API key", - "copy-service-token-description": "Una vez que cierres esta ventana, no volverás a ver tu API key" - } -} diff --git a/frontend/public/locales/es/section-incident.json b/frontend/public/locales/es/section-incident.json deleted file mode 100644 index 79505ab60..000000000 --- a/frontend/public/locales/es/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "incident-contacts": "Contactos de incidencias", - "incident-contacts-description": "Estos contactos serán notificados en caso de una incidencia grave.", - "no-incident-contacts": "No se han encontrado contactos para incidencias.", - "add-contact": "Añadir contacto", - "add-dialog": { - "title": "Añadir un contacto de incidencias", - "description": "Este contacto será notificado en el caso de una incidencia grave.", - "add-incident": "Añadir contacto de incidencias" - } -} diff --git a/frontend/public/locales/es/section-members.json b/frontend/public/locales/es/section-members.json deleted file mode 100644 index 26996d697..000000000 --- a/frontend/public/locales/es/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "Añadir miembro", - "org-members": "Miembros de la organización", - "org-members-description": "Gestiona los miembros de tu organización. Estos usuarios podrán ser agrupados en proyectos más tarde.", - "search-members": "Buscar miembros...", - "add-dialog": { - "add-member-to-project": "Añadir un miembro al proyecto", - "already-all-invited": "Todos los uaurios en tu organización han sido invitados.", - "add-user-org-first": "Añadir primero más usuarios a la organización.", - "user-will-email": "El usuario recibirá un correo electrónico con la invitación.", - "looking-add": "<0>Si quieres añadir usuarios a tu organización, haz<1>click aquí", - "add-user-to-org": "Añadir usuarios a la organización" - } -} diff --git a/frontend/public/locales/es/section-password.json b/frontend/public/locales/es/section-password.json deleted file mode 100644 index f3b957ee2..000000000 --- a/frontend/public/locales/es/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "Contraseña", - "change": "Cambiar contraseña", - "current": "Contraseña actual", - "current-wrong": "La contraseña actual puede puede que sea incorrecta", - "new": "Nueva contraseña", - "validate-base": "La contraseña debe contener como mínimo:", - "validate-length": "14 caracteres", - "validate-case": "1 letra en minúsculas", - "validate-number": "1 número" -} diff --git a/frontend/public/locales/es/section-token.json b/frontend/public/locales/es/section-token.json deleted file mode 100644 index fdf04e600..000000000 --- a/frontend/public/locales/es/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "service-tokens": "Tokens de servicio", - "service-tokens-description": "Cada token de servicio es específico para ti, para cada proyecto y para cada entorno en este proyectos.", - "add-new": "Añadir nuevo token", - "add-dialog": { - "title": "Añade un nuevo token de servicio para {{target}}", - "description": "Cuando se genera un token, solo podrás verlo una vez antes de que desaparezca. Asegúrate de guardarlo en algún lugar.", - "name": "Nombre del token de servicio", - "add": "Añadir token de servicio", - "copy-service-token": "Copiar tu token de servicio", - "copy-service-token-description": "Una vez cierres esta ventana, no volverás a ver tu token de nuevo" - } -} diff --git a/frontend/public/locales/es/settings-members.json b/frontend/public/locales/es/settings-members.json deleted file mode 100644 index bf6a0c106..000000000 --- a/frontend/public/locales/es/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Miembros del proyecto", - "description": "Esta página muestra los miembros del proyecto seleccionado, y permite modificar sus permisos." -} diff --git a/frontend/public/locales/es/settings-org.json b/frontend/public/locales/es/settings-org.json deleted file mode 100644 index 3988bd165..000000000 --- a/frontend/public/locales/es/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Configuración de la organización", - "description": "Gestiona los miembros de tu organización. Estos usuarios podrán ser gestionados en proyectos más adelante." -} diff --git a/frontend/public/locales/es/settings-personal.json b/frontend/public/locales/es/settings-personal.json deleted file mode 100644 index 540386578..000000000 --- a/frontend/public/locales/es/settings-personal.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Preferencias personales", - "description": "Visualiza y gestiona aquí tu información personal.", - "emergency": { - "name": "Kit de emergencia", - "text1": "Tu Kit de emergencia contiene la información que necesitarás para iniciar sesión en tu cuenta de Infisical.", - "text2": "Solo el último Kit de emergencia descargado es válido. Para conseguir uno nuevo, introduce tu contraseña.", - "download": "Descargar Kit de emergencia" - }, - "change-language": "Cambiar idioma", - "api-keys": { - "title": "API Keys", - "description": "Gestiona tus API Keys personales para acceder a la API de Infisical.", - "add-new": "Añadir" - } -} diff --git a/frontend/public/locales/es/settings-project.json b/frontend/public/locales/es/settings-project.json deleted file mode 100644 index b1757d072..000000000 --- a/frontend/public/locales/es/settings-project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "Configuración de proyecto", - "description": "Esta configuración solo afecta al proyecto seleccionado.", - "danger-zone": "Zona de peligro", - "delete-project": "Eliminar proyecto", - "project-to-delete": "Proyecto a eliminar", - "danger-zone-note": "Tan pronto como elimines el proyecto, no podrás volver atrás. Esto eliminará todas las claves. Si aún quieres hacerlo, introduce el nombre del proyecto a continuación.", - "delete-project-note": "Nota: Solo puedes eliminar un proyecto si tienes más de uno", - "project-id-description": "Para integrar Infisical en tu aplicación y obtener la inyección automática de variables de entorno, debes usar el siguiente ID de Proyecto.", - "project-id-description2": "Para más guías, incluyendo ejemplos de código en diferentes lenguajes y frameworks, visita ", - "auto-generated": "Este es el ID único y autogenerado de proyecto. No se puede modificar.", - "docs": "Documentación de Infisical", - "auto-capitalization": "Mayúsculas automáticas", - "auto-capitalization-description": "De acuerdo con los estándares, Infisical pondrá en mayúsculas tus claves. Si quieres desactivar esta funcionalidad, lo puedes hacer aquí." -} diff --git a/frontend/public/locales/es/signup.json b/frontend/public/locales/es/signup.json deleted file mode 100644 index 35d41adf5..000000000 --- a/frontend/public/locales/es/signup.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Registrarse", - "og-title": "Reemplaza los archivos .env con una línea de código. Regístrate en Infisical en solo 3 minutos.", - "og-description": "Infisical es una plataforma sencilla cifrada de extremo a extremo que permite a equipos sincronizar y gestionar API-keys y variables de entorno. Funciona con Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Registrarse", - "already-have-account": "¿Ya tienes una cuenta? Inicia sesión", - "forgot-password": "¿Has olvidado tu contraseña?", - "verify": "Verificar", - "step1-start": "Vamos a empezar", - "step1-privacy": "Al crear la cuenta, aceptas nuestros Términos y has leído y comprendido nuestra Política de privacidad.", - "step1-submit": "Empezar", - "step2-message": "Hemos enviado un código a", - "step2-code-error": "Oops. Tu código es incorrecto. Intentos restantes:", - "step2-resend-alert": "¿No ves el código?", - "step2-resend-submit": "Volver a enviar", - "step2-resend-progress": "Reenviando...", - "step2-spam-alert": "Asegúrate de comprobar la carpeta de spam.", - "step3-message": "¡Casi hemos terminado!", - "step4-message": "Guarda tu Kit de emergencia", - "step4-description1": "Si pierdes el acceso a tu cuenta, tu Kit de emergencia es la única forma de iniciar sesión.", - "step4-description2": "Te recomendamos que lo descargues y lo guardes en un sitio seguro.", - "step4-description3": "Contiene tu Clave secreta, a la que no tenemos acceso y tampoco podemos recuperar si la pierdes.", - "step4-download": "Descargar PDF", - "step5-send-invites": "Enviar invitaciones", - "step5-invite-team": "Invita a tu equipo", - "step5-subtitle": "Infisical está pensado para usarlo con tus compañeros. Invítalos a probarlo.", - "step5-skip": "Saltar" -} diff --git a/frontend/public/locales/es/translations.json b/frontend/public/locales/es/translations.json new file mode 100644 index 000000000..e734fb3f2 --- /dev/null +++ b/frontend/public/locales/es/translations.json @@ -0,0 +1,319 @@ +{ + "activity": { + "title": "Historial de eventos", + "subtitle": "Historial de eventos para este proyecto de Infisical.", + "event": { + "readSecrets": "Secrets vistas", + "updateSecrets": "Secrets actualizadas", + "addSecrets": "Secrets añadidas", + "deleteSecrets": "Secrets eliminadas" + }, + "ip-address": "Dirección IP" + }, + "billing": { + "title": "Uso & Facturación", + "description": "Visualiza y gestiona la suscripción de tu organización", + "subscription": "Suscripción", + "starter": { + "name": "Starter", + "price-explanation": "hasta 5 miembros", + "text": "¡Hasta 5 personas gratis!", + "subtext": "Después, $5 por miembro/mes." + }, + "professional": { + "name": "Professional", + "price-explanation": "/miembro/mes", + "subtext": "Includes unlimited projects & members.", + "text": "Mantén la gestión de claves a medida que creces." + }, + "enterprise": { + "name": "Enterprise", + "text": "Mantén la gestión de claves a medida que creces." + }, + "current-usage": "Uso actual", + "free": "Gratis", + "downgrade": "Reducir", + "upgrade": "Mejorar", + "learn-more": "Saber más", + "custom-pricing": "A medida", + "schedule-demo": "Solicitar una demo" + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "Ya existe un proyecto con este nombre.", + "no-mobile": "Para usar Infisical, inicia sesión con un dispositivo de mayores dimesiones.", + "email": "Correo electrónico", + "password": "Contraseña", + "first-name": "Nombre", + "last-name": "Apellidos", + "logout": "Cerrar sesión", + "validate-required": "Por favor, introduce tu {{name}}", + "maintenance-alert": "Estamos experimentando problemas técnicos. Estamos trabajando para resolverlos. Por favor, vuelve en unos minutos.", + "click-to-copy": "Click para copiar", + "project-id": "ID de proyecto", + "save-changes": "Guardar cambios", + "saved": "Guardado", + "drop-zone": "Arrastra y suelta un archivo .env, .json o .yml aquí.", + "drop-zone-keys": "Arrastra y suelta un archivo .env, .json, or .yml aquí para añadir más secrets.", + "role": "Rol", + "role_admin": "admin", + "display-name": "Nombre visible", + "environment": "Entorno", + "expired-in": "Expira en", + "language": "Idioma", + "search": "Buscar...", + "note": "Nota", + "view-more": "Ver más", + "end-of-history": "Fin del historial", + "select-event": "Selecciona un evento", + "event": "Evento", + "user": "Usuario", + "source": "Fuente", + "time": "Hora", + "timestamp": "Marca temporal" + }, + "dashboard": { + "title": "Secrets", + "og-title": "Gestiona tus archivos .env en segundos", + "og-description": "Infisical es una solución cifrada de extremo a extremo que habilita a los equipos a compartir archivos .env de forma sencilla.", + "search-keys": "Buscar claves...", + "add-key": "Añadir clave", + "personal": "Personal", + "personal-description": "Las claves personales solo son visibles para ti", + "shared": "Compartido", + "shared-description": "Claves compartidas son visibles para todo tu equipo", + "make-shared": "Hacer compartida", + "make-personal": "Hacer personal", + "add-secret": "Añadir una nueva clave", + "check-docs": { + "button": "Comprueba la documentación", + "title": "¡Buen trabajo!", + "line1": "Enhorabuena por añadir claves.", + "line2": "Averigua como usarlo desde tu código." + }, + "sidebar": { + "secret": "Secret", + "key": "Clave", + "value": "valor", + "override": "Sobreescribir valor con el valor personal", + "version-history": "Historial de versiones", + "comments": "Comentarios & Notas", + "personal-explanation": "Esta clave es personal. No será compartida con ninguno de tus compañeros.", + "generate-random-hex": "Generar Hex aleatorio", + "digits": "dígitos", + "delete-key-dialog": { + "title": "Eliminar clave", + "confirm-delete-message": "¿Estás seguro de que quieres eliminar esta clave? Esta operación no se puede deshacer." + } + } + }, + "integrations": { + "title": "Integraciones del proyecto", + "description": "Gestiona tus integraciones de Infisical con aplicaciones de terceros.", + "no-integrations1": "No tienes ninguna integración configurada. Cuando las tengas, aparecerán aquí.", + "no-integrations2": "Para empezar haz click en cualquiera de las opciones siguientes. Se necesitan tan solo 5 pasos.", + "available": "Integraciones con la nube", + "available-text1": "Haz click en la integración que quieras conectar. Esto hará que las variables de entorno se configuren automáticamente en los servicios de terceros seleccionados.", + "available-text2": "Nota: en la integración con Heroku, por motivos de seguridad, es imposible mantener el cifrado de extremo a extremo. En teoría, esto permite a Infisical descifrar tus variables de entorno. En la práctica, te podemos asegurar que esto nunca va a suceder. El núcleo del servicio Infisical siempre estará cifrado de extremo a extremo. Si tienes dudas, escríbenos a support@infisical.com.", + "cloud-integrations": "Integraciones con la nube", + "framework-integrations": "Integraciones con frameworks", + "click-to-start": "Haz click en una integración para empezar a sincronizar las claves.", + "click-to-setup": "Haz click en un framework para ver las instrucciones de uso.", + "grant-access-to-secrets": "Autorizar Infisical el acceso a tus claves", + "why-infisical-needs-access": "La mayoría de las integraciones en la nube requieren a Infisical tener permiso para descifrar tus claves, para que puedan ser enviadas.", + "grant-access-button": "Autorizar acceso" + }, + "login": { + "title": "Iniciar sesión", + "og-title": "Iniciar sesión en Infisical", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", + "login": "Iniciar sesión", + "need-account": "¿Necesitas una cuenta de Infisical?", + "create-account": "Crea una cuenta", + "forgot-password": "¿Has olvidado tu contraseña?", + "error-login": "Datos incorrectos." + }, + "mfa": { + "title": "Registrarse", + "og-title": "Reemplaza los archivos .env con una línea de código. Regístrate en Infisical en solo 3 minutos.", + "og-description": "Infisical es una plataforma sencilla cifrada de extremo a extremo que permite a equipos sincronizar y gestionar API-keys y variables de entorno. Funciona con Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Registrarse", + "already-have-account": "¿Ya tienes una cuenta? Inicia sesión", + "forgot-password": "¿Has olvidado tu contraseña?", + "verify": "Verificar", + "step1-start": "Vamos a empezar", + "step1-privacy": "Al crear la cuenta, aceptas nuestros Términos y has leído y comprendido nuestra Política de privacidad.", + "step1-submit": "Empezar", + "step2-message": "Hemos enviado un código a", + "step2-code-error": "Oops. Tu código es incorrecto. Intentos restantes:", + "step2-resend-alert": "¿No ves el código?", + "step2-resend-submit": "Volver a enviar", + "step2-resend-progress": "Reenviando...", + "step2-spam-alert": "Asegúrate de comprobar la carpeta de spam.", + "step3-message": "¡Casi hemos terminado!", + "step4-message": "Guarda tu Kit de emergencia", + "step4-description1": "Si pierdes el acceso a tu cuenta, tu Kit de emergencia es la única forma de iniciar sesión.", + "step4-description2": "Te recomendamos que lo descargues y lo guardes en un sitio seguro.", + "step4-description3": "Contiene tu Clave secreta, a la que no tenemos acceso y tampoco podemos recuperar si la pierdes.", + "step4-download": "Descargar PDF", + "step5-send-invites": "Enviar invitaciones", + "step5-invite-team": "Invita a tu equipo", + "step5-subtitle": "Infisical está pensado para usarlo con tus compañeros. Invítalos a probarlo.", + "step5-skip": "Saltar" + }, + "nav": { + "support": { + "slack": "Unirse al Slack", + "docs": "Leer documentación", + "issue": "Abrir una Github Issue", + "email": "Envíanos un correo electrónico" + }, + "user": { + "signed-in-as": "INICIADO COMO", + "current-organization": "ORGANIZACIÓN ACTUAL", + "usage-billing": "Uso & Facturación", + "invite": "Invitar miembros", + "other-organizations": "OTRA ORGANIZACIÓN" + }, + "menu": { + "project": "PROYECTO", + "secrets": "Claves", + "members": "Miembros", + "integrations": "Integraciones", + "project-settings": "Configuración del proyecto" + } + }, + "section": { + "api-key": { + "api-keys": "Tokens de servicio", + "api-keys-description": "Cada token de servicio es específico para ti, para cada proyecto y para cada entorno en este proyecto.", + "add-new": "Añadir nuevo token", + "add-dialog": { + "title": "Añadir una API Key", + "description": "Especifica el nombre y el período de expiración. Cuando una API key es generada, solo podrás verla una vez hasta que desaparezca. Asegúrate de guardarla en algún lado.", + "name": "Nombre de la API Key", + "add": "Añadir API Key", + "copy-service-token": "Copia tu API key", + "copy-service-token-description": "Una vez que cierres esta ventana, no volverás a ver tu API key" + } + }, + "incident": { + "incident-contacts": "Contactos de incidencias", + "incident-contacts-description": "Estos contactos serán notificados en caso de una incidencia grave.", + "no-incident-contacts": "No se han encontrado contactos para incidencias.", + "add-contact": "Añadir contacto", + "add-dialog": { + "title": "Añadir un contacto de incidencias", + "description": "Este contacto será notificado en el caso de una incidencia grave.", + "add-incident": "Añadir contacto de incidencias" + } + }, + "members": { + "add-member": "Añadir miembro", + "org-members": "Miembros de la organización", + "org-members-description": "Gestiona los miembros de tu organización. Estos usuarios podrán ser agrupados en proyectos más tarde.", + "search-members": "Buscar miembros...", + "add-dialog": { + "add-member-to-project": "Añadir un miembro al proyecto", + "already-all-invited": "Todos los uaurios en tu organización han sido invitados.", + "add-user-org-first": "Añadir primero más usuarios a la organización.", + "user-will-email": "El usuario recibirá un correo electrónico con la invitación.", + "looking-add": "<0>Si quieres añadir usuarios a tu organización, haz<1>click aquí", + "add-user-to-org": "Añadir usuarios a la organización" + } + }, + "password": { + "password": "Contraseña", + "change": "Cambiar contraseña", + "current": "Contraseña actual", + "current-wrong": "La contraseña actual puede puede que sea incorrecta", + "new": "Nueva contraseña", + "validate-base": "La contraseña debe contener como mínimo:", + "validate-length": "14 caracteres", + "validate-case": "1 letra en minúsculas", + "validate-number": "1 número" + }, + "token": { + "service-tokens": "Tokens de servicio", + "service-tokens-description": "Cada token de servicio es específico para ti, para cada proyecto y para cada entorno en este proyectos.", + "add-new": "Añadir nuevo token", + "add-dialog": { + "title": "Añade un nuevo token de servicio para {{target}}", + "description": "Cuando se genera un token, solo podrás verlo una vez antes de que desaparezca. Asegúrate de guardarlo en algún lugar.", + "name": "Nombre del token de servicio", + "add": "Añadir token de servicio", + "copy-service-token": "Copiar tu token de servicio", + "copy-service-token-description": "Una vez cierres esta ventana, no volverás a ver tu token de nuevo" + } + } + }, + "settings": { + "members": { + "title": "Miembros del proyecto", + "description": "Esta página muestra los miembros del proyecto seleccionado, y permite modificar sus permisos." + }, + "org": { + "title": "Configuración de la organización", + "description": "Gestiona los miembros de tu organización. Estos usuarios podrán ser gestionados en proyectos más adelante." + }, + "personal": { + "title": "Preferencias personales", + "description": "Visualiza y gestiona aquí tu información personal.", + "emergency": { + "name": "Kit de emergencia", + "text1": "Tu Kit de emergencia contiene la información que necesitarás para iniciar sesión en tu cuenta de Infisical.", + "text2": "Solo el último Kit de emergencia descargado es válido. Para conseguir uno nuevo, introduce tu contraseña.", + "download": "Descargar Kit de emergencia" + }, + "change-language": "Cambiar idioma", + "api-keys": { + "title": "API Keys", + "description": "Gestiona tus API Keys personales para acceder a la API de Infisical.", + "add-new": "Añadir" + } + }, + "project": { + "title": "Configuración de proyecto", + "description": "Esta configuración solo afecta al proyecto seleccionado.", + "danger-zone": "Zona de peligro", + "delete-project": "Eliminar proyecto", + "project-to-delete": "Proyecto a eliminar", + "danger-zone-note": "Tan pronto como elimines el proyecto, no podrás volver atrás. Esto eliminará todas las claves. Si aún quieres hacerlo, introduce el nombre del proyecto a continuación.", + "delete-project-note": "Nota: Solo puedes eliminar un proyecto si tienes más de uno", + "project-id-description": "Para integrar Infisical en tu aplicación y obtener la inyección automática de variables de entorno, debes usar el siguiente ID de Proyecto.", + "project-id-description2": "Para más guías, incluyendo ejemplos de código en diferentes lenguajes y frameworks, visita ", + "auto-generated": "Este es el ID único y autogenerado de proyecto. No se puede modificar.", + "docs": "Documentación de Infisical", + "auto-capitalization": "Mayúsculas automáticas", + "auto-capitalization-description": "De acuerdo con los estándares, Infisical pondrá en mayúsculas tus claves. Si quieres desactivar esta funcionalidad, lo puedes hacer aquí." + } + }, + "signup": { + "title": "Registrarse", + "og-title": "Reemplaza los archivos .env con una línea de código. Regístrate en Infisical en solo 3 minutos.", + "og-description": "Infisical es una plataforma sencilla cifrada de extremo a extremo que permite a equipos sincronizar y gestionar API-keys y variables de entorno. Funciona con Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Registrarse", + "already-have-account": "¿Ya tienes una cuenta? Inicia sesión", + "forgot-password": "¿Has olvidado tu contraseña?", + "verify": "Verificar", + "step1-start": "Vamos a empezar", + "step1-privacy": "Al crear la cuenta, aceptas nuestros Términos y has leído y comprendido nuestra Política de privacidad.", + "step1-submit": "Empezar", + "step2-message": "Hemos enviado un código a", + "step2-code-error": "Oops. Tu código es incorrecto. Intentos restantes:", + "step2-resend-alert": "¿No ves el código?", + "step2-resend-submit": "Volver a enviar", + "step2-resend-progress": "Reenviando...", + "step2-spam-alert": "Asegúrate de comprobar la carpeta de spam.", + "step3-message": "¡Casi hemos terminado!", + "step4-message": "Guarda tu Kit de emergencia", + "step4-description1": "Si pierdes el acceso a tu cuenta, tu Kit de emergencia es la única forma de iniciar sesión.", + "step4-description2": "Te recomendamos que lo descargues y lo guardes en un sitio seguro.", + "step4-description3": "Contiene tu Clave secreta, a la que no tenemos acceso y tampoco podemos recuperar si la pierdes.", + "step4-download": "Descargar PDF", + "step5-send-invites": "Enviar invitaciones", + "step5-invite-team": "Invita a tu equipo", + "step5-subtitle": "Infisical está pensado para usarlo con tus compañeros. Invítalos a probarlo.", + "step5-skip": "Saltar" + } +} diff --git a/frontend/public/locales/fr/activity.json b/frontend/public/locales/fr/activity.json deleted file mode 100644 index 4360d7d0c..000000000 --- a/frontend/public/locales/fr/activity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Journaux d'activité", - "subtitle": "Historique des événements pour ce projet Infisical.", - "event": { - "readSecrets": "Secrets Visualisés", - "updateSecrets": "Secrets Mis à jour", - "addSecrets": "Secrets Ajoutés", - "deleteSecrets": "Secrets Supprimés" - }, - "ip-address": "Adresse IP" -} diff --git a/frontend/public/locales/fr/billing.json b/frontend/public/locales/fr/billing.json deleted file mode 100644 index 1acb44339..000000000 --- a/frontend/public/locales/fr/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Utilisation et Facturation", - "description": "Voir et gérer l'abonnement de votre organisation ici", - "subscription": "Abonnement", - "starter": { - "name": "Starter", - "price-explanation": "jusqu'à 5 membres de l'équipe", - "text": "Gérez n'importe quel projet jusqu'à 5 membres gratuitement!", - "subtext": "$5 par membre / mois par la suite." - }, - "professional": { - "name": "Professionnel", - "price-explanation": "/membre/mois", - "subtext": "Comprend des projets et des membres illimités.", - "text": "Suivez la gestion clé à mesure que vous grandissez." - }, - "enterprise": { - "name": "Entreprise", - "text": "Suivez la gestion clé à mesure que vous grandissez." - }, - "current-usage": "Utilisation actuelle", - "free": "Gratuit", - "downgrade": "Rétrograder", - "upgrade": "Améliorer", - "learn-more": "En savoir plus", - "custom-pricing": "Prix personnalisés", - "schedule-demo": "Planifier une démo" -} diff --git a/frontend/public/locales/fr/common.json b/frontend/public/locales/fr/common.json deleted file mode 100644 index 1f6a52447..000000000 --- a/frontend/public/locales/fr/common.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "Un projet avec ce nom existe déjà.", - "no-mobile": " Pour utiliser Infisical, veuillez vous connecter avec un appareil avec des dimensions plus grandes. ", - "email": "Email", - "password": "Mot de passe", - "first-name": "Prénom", - "last-name": "Nom", - "logout": "Déconnexion", - "validate-required": "Veuillez saisir votre {{name}}", - "maintenance-alert": "Nous rencontrons des difficultés techniques mineures. Nous travaillons sur leurs résolution dès maintenant. Revenez dans quelques minutes.", - "click-to-copy": "Cliquez pour copiez", - "project-id": "Identifiant du Projet", - "save-changes": "Sauvegarder les modifications", - "saved": "Enregistrée", - "drop-zone": "Glissez et déposez un fichier .env ou .yml ici.", - "drop-zone-keys": "Glissez et déposez un fichier .env ou .yml ici pour ajouter plus de clés.", - "role": "Rôle", - "role_admin": "administrateur", - "display-name": "Nom d'affichage", - "environment": "Environnement", - "expired-in": "Expire dans", - "language": "Langue", - "search": "Recherche...", - "note": "Note", - "view-more": "Voir plus", - "end-of-history": "Fin de l'historique", - "select-event": "Sélectionnez un événement", - "event": "Événement", - "user": "Utilisateur", - "source": "Source", - "time": "Heure", - "timestamp": "Horodatage" -} \ No newline at end of file diff --git a/frontend/public/locales/fr/dashboard.json b/frontend/public/locales/fr/dashboard.json deleted file mode 100644 index f90bf1fc2..000000000 --- a/frontend/public/locales/fr/dashboard.json +++ /dev/null @@ -1,36 +0,0 @@ -{ - "title": "Secrets", - "og-title": "Gérez vos fichiers .env rapidement", - "og-description": "Infisical une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer leurs fichiers .env.", - "search-keys": "Recherche les clefs...", - "add-key": "Ajouter une clef", - "personal": "Personnel", - "personal-description": "Les clés personnelles ne sont visibles que pour vous", - "shared": "Partagé", - "shared-description": "Les clés partagées sont visibles à toute votre équipe", - "make-shared": "Rendre Partagé", - "make-personal": "Rendre Personnel", - "add-secret": "Ajouter un nouveau secret", - "check-docs": { - "button": "Vérifier la documentation", - "title": "Bon travail!", - "line1": "Félicitations pour avoir ajouté plus de secrets.", - "line2": "Voici comment les connecter à votre base de code." - }, - "sidebar": { - "secret": "Secret", - "key": "Clef", - "value": "Valeur", - "override": "Remplacer la valeur avec une valeur personnelle", - "version-history": "Historique des versions", - "comments": "Commentaires & Notes", - "personal-explanation": "Ce secret est personnel. Il n'est partagé avec aucun de vos coéquipiers.", - "generate-random-hex": "Générer un Hex aléatoire", - "digits": "chiffres", - "delete-key-dialog": { - "title": "Supprimer la clef", - "confirm-delete-message": "Êtes-vous sûr de vouloir supprimer ce secret? Cela ne peut pas être annulé." - } - } - -} diff --git a/frontend/public/locales/fr/integrations.json b/frontend/public/locales/fr/integrations.json deleted file mode 100644 index 887e79dfd..000000000 --- a/frontend/public/locales/fr/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Intégrations de Projet", - "description": "Gérez vos intégrations d'Infisical avec des services tiers.", - "no-integrations1": "Vous n'avez pas encore d'intégration. Quand vous en aurez, elles apparaîtront ici.", - "no-integrations2": "Pour commencer, cliquez sur l'une des options ci-dessous. La configuration se fait en 5 clics.", - "available": "Intégrations de plate-forme et cloud", - "available-text1": "Cliquez sur l'intégration que vous souhaitez connecter. Cela permettra à vos variables d'environnement de circuler automatiquement dans les services tiers sélectionnés.", - "available-text2": "Remarque: Lors d'une intégration avec Heroku, pour des raisons de sécurité, il est impossible de maintenir le chiffrage de bout en bout. En théorie, cela permet à Infisical de déchiffrer les variables d'environnement. En pratique, nous pouvons vous assurer que cela ne sera jamais fait, et cela nous permet de protéger vos secrets des mauvais acteurs en ligne. Le service Infisical de base restera toujours chiffré de bout en bout. Pour toutes vos intérogations, contactez support@infisical.com.", - "cloud-integrations": "Intégrations Cloud", - "framework-integrations": "Intégrations Framework", - "click-to-start": "Cliquez sur une intégration pour commencer à synchroniser les secrets avec elle.", - "click-to-setup": "Cliquez sur un framework pour obtenir les instructions de configuration.", - "grant-access-to-secrets": "Accordez un accès Infisical à vos secrets", - "why-infisical-needs-access": "La plupart des intégrations cloud nécessitent qu'Infisical puisse déchiffrer vos secrets afin qu'ils puissent être transmis.", - "grant-access-button": "Autoriser l'accès" -} diff --git a/frontend/public/locales/fr/login.json b/frontend/public/locales/fr/login.json deleted file mode 100644 index 8c93da9fb..000000000 --- a/frontend/public/locales/fr/login.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "Connexion", - "og-title": "Connectez-vous à Infisical", - "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout permettant aux équipes de synchroniser et de gérer leurs fichiers .env.", - "login": "Se connecter", - "need-account": "Besoin d'un compte Infisical?", - "create-account": "Créer un compte", - "forgot-password": "Mot de passe oublié?", - "error-login": "Mauvais identifiants." -} diff --git a/frontend/public/locales/fr/mfa.json b/frontend/public/locales/fr/mfa.json deleted file mode 100644 index 60e3201ed..000000000 --- a/frontend/public/locales/fr/mfa.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "S'inscrire", - "og-title": "Remplacez les fichiers .env par 1 ligne de code. Inscrivez-vous à Infisical en 3 minutes.", - "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer des clefs API et des variables d'environnement. Fonctionne avec Node.js, Next.js, Gatsby, Nest.js ...", - "signup": "S'inscrire", - "already-have-account": "Déjà inscris? Se connecter", - "forgot-password": "Mot de passe oublié?", - "verify": "Vérifier", - "step1-start": "Bon, on commence!", - "step1-privacy": "En créant votre compte, vous acceptez nos conditions et avez lu et reconnu notre politique de confidentialité.", - "step1-submit": "C'est parti", - "step2-message": "Nous avons envoyé un email de vérification à", - "step2-code-error": "Oops. Votre code est faux. Essais restants:", - "step2-resend-alert": "Vous ne voyez pas le code?", - "step2-resend-submit": "Renvoyer", - "step2-resend-progress": "Envoie en cours...", - "step2-spam-alert": "Assurez-vous de vérifier vos spams.", - "step3-message": "Nous y sommes presque!", - "step4-message": "Enregistrez votre kit d'urgence", - "step4-description1": "Si vous n'arrivez plus à vous connecter à votre compte, votre kit d'urgence est le seul moyen d'y arriver.", - "step4-description2": "Nous vous recommandons de le télécharger et de le garder en sécurité.", - "step4-description3": "Il contient votre clef secrète que nous ne pouvons pas récupérer pour vous si vous la perdez.", - "step4-download": "Téléchargez le PDF", - "step5-send-invites": "Envoyer les invitations", - "step5-invite-team": "Invitez votre équipe", - "step5-subtitle": "Infisical a pour but d'être utilisé avec vos coéquipiers. Invitez-les à le tester.", - "step5-skip": "Passer" -} diff --git a/frontend/public/locales/fr/nav.json b/frontend/public/locales/fr/nav.json deleted file mode 100644 index 1fda27af9..000000000 --- a/frontend/public/locales/fr/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "[NEW] Rejoignez le forum Slack", - "docs": "Lire les documentations", - "issue": "Ouvrir une issue Github", - "email": "Envoyez-nous un email" - }, - "user": { - "signed-in-as": "CONNECTÉ EN TANT QUE", - "current-organization": "ORGANISATION ACTUELLE", - "usage-billing": "Utilisation & Facturation", - "invite": "Inviter des membres", - "other-organizations": "AUTRE ORGANISATION" - }, - "menu": { - "project": "PROJET", - "secrets": "Secrets", - "members": "Membres", - "integrations": "Intégrations", - "project-settings": "Paramètres du Projet" - } -} diff --git a/frontend/public/locales/fr/section-incident.json b/frontend/public/locales/fr/section-incident.json deleted file mode 100644 index 95b77ea13..000000000 --- a/frontend/public/locales/fr/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "incident-contacts": "Contacts Incidents", - "incident-contacts-description": "Ces contacts seront informés dans le cas improbable d'un incident grave.", - "no-incident-contacts": "Aucun contact incident trouvé.", - "add-contact": "Ajouter un contact", - "add-dialog": { - "title": "Ajouter un contact incident", - "description": "Ce contact sera informé dans le cas improbable d'un incident grave.", - "add-incident": "Ajouter un contact incident" - } -} diff --git a/frontend/public/locales/fr/section-members.json b/frontend/public/locales/fr/section-members.json deleted file mode 100644 index 8faed80e7..000000000 --- a/frontend/public/locales/fr/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "Ajouter un Membre", - "org-members": "Membres de l'organisation", - "org-members-description": "Gérer les membres de votre organisation. Ces utilisateurs pourraient ensuite être répartis en projets.", - "search-members": "Recherche des membres...", - "add-dialog": { - "add-member-to-project": "Ajoutez un membre à votre projet", - "already-all-invited": "Tous les utilisateurs de votre organisation sont déjà invités.", - "add-user-org-first": "Ajoutez d'abord plus d'utilisateurs à l'organisation.", - "user-will-email": "L'utilisateur recevra un email avec les instructions.", - "looking-add": "<0>Si vous cherchez à ajouter des utilisateurs à votre organisation,<1>cliquez ici", - "add-user-to-org": "Ajouter des Utilisateurs à l'Organisation" - } -} diff --git a/frontend/public/locales/fr/section-password.json b/frontend/public/locales/fr/section-password.json deleted file mode 100644 index 0928233e6..000000000 --- a/frontend/public/locales/fr/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "Mot de passe", - "change": "Changer le mot de passe", - "current": "Mot de passe actuel", - "current-wrong": "Le mot de passe actuel peut être érroné", - "new": "Nouveau mot de passe", - "validate-base": "Le mot de passe doit contenir au moins:", - "validate-length": "14 caractères", - "validate-case": "1 caractère miniscule", - "validate-number": "1 chiffre" -} diff --git a/frontend/public/locales/fr/section-token.json b/frontend/public/locales/fr/section-token.json deleted file mode 100644 index 1f2a3b233..000000000 --- a/frontend/public/locales/fr/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "service-tokens": "Jetons de service", - "service-tokens-description": "Chaque jeton de service vous est spécifique, à un certain projet et à un certain environnement dans ce projet.", - "add-new": "Ajouter un nouveau jeton", - "add-dialog": { - "title": "Ajouter un jeton de service pour {{target}}", - "description": "Spécifiez le nom, l'environnement et la période d'expiration. Lorsqu'un jeton est généré, vous ne pourrez le voir qu'une seule fois avant qu'il ne disparaisse. Assurez-vous de le sauvegarder quelque part.", - "name": "Nom du jeton de service", - "add": "Ajouter un jeton de service", - "copy-service-token": "Copiez votre jeton de service", - "copy-service-token-description": "Une fois que vous aurez fermé cette fenêtre, vous ne reverrez plus jamais votre jeton de service" - } -} diff --git a/frontend/public/locales/fr/settings-members.json b/frontend/public/locales/fr/settings-members.json deleted file mode 100644 index 9f34c7a68..000000000 --- a/frontend/public/locales/fr/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Membres du projet", - "description": "Cette page affiche les membres du projet sélectionné." -} diff --git a/frontend/public/locales/fr/settings-org.json b/frontend/public/locales/fr/settings-org.json deleted file mode 100644 index 952bd68c8..000000000 --- a/frontend/public/locales/fr/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Paramètres d'Organisation", - "description": "Gérer les membres de votre organisation. Ces utilisateurs pourraient ensuite être répartis en projets." -} diff --git a/frontend/public/locales/fr/settings-personal.json b/frontend/public/locales/fr/settings-personal.json deleted file mode 100644 index 30a3d6fa3..000000000 --- a/frontend/public/locales/fr/settings-personal.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Paramètres Personnels", - "description": "Consultez et gérez vos informations personnelles ici.", - "emergency": { - "name": "Kit d'urgence", - "text1": "Votre kit d'urgence contient les informations dont vous aurez besoin pour vous connecter à votre compte Infisical.", - "text2": "Seul le dernier kit d'urgence émis reste valide. Pour obtenir un nouveau kit d'urgence, vérifiez votre mot de passe.", - "download": "Télécharger le kit d'urgence" - }, - "change-language": "Changer de langue" -} diff --git a/frontend/public/locales/fr/settings-project.json b/frontend/public/locales/fr/settings-project.json deleted file mode 100644 index a5a3f1ee3..000000000 --- a/frontend/public/locales/fr/settings-project.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "Paramètres du Projet", - "description": "Ces paramètres ne s'appliquent qu'au Projet actuellement sélectionné.", - "danger-zone": "Zone de danger", - "delete-project": "Supprimer le Projet", - "project-to-delete": "Projet à Supprimer", - "danger-zone-note": "Dès que vous supprimez ce projet, vous ne pourrez plus revenir en arrière. Cela supprimera immédiatement toutes les clefs. Si vous voulez toujours le faire, veuillez saisir le nom du projet ci-dessous.", - "delete-project-note": "Remarque: Vous ne pouvez supprimer qu'un projet que si vous en avez plus d'un.", - "project-id-description": "Pour intégrer Infisical dans votre base de code et obtenir une injection automatique de variables d'environnement, vous devez utiliser l'ID du projet suivant.", - "project-id-description2": "Pour plus de conseils, y compris des extraits de code pour diverses langues et frameworks, voir ", - "auto-generated": "Ceci est l'identifiant unique généré automatiquement pour votre projet. Il ne peut pas être modifié.", - "docs": "Documentation Infisical" -} diff --git a/frontend/public/locales/fr/signup.json b/frontend/public/locales/fr/signup.json deleted file mode 100644 index 63d869193..000000000 --- a/frontend/public/locales/fr/signup.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "S'inscrire", - "og-title": "Remplacez les fichiers .env par 1 ligne de code. Inscrivez-vous à Infisical en 3 minutes.", - "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer des clefs API et des variables d'environnement. Fonctionne avec Node.js, Next.js, Gatsby, Nest.js ...", - "signup": "S'inscrire", - "already-have-account": "Déjà inscris? Se connecter", - "forgot-password": "Mot de passe oublié?", - "verify": "Vérifier", - "step1-start": "Bon, on commence!", - "step1-privacy": "En créant votre compte, vous acceptez nos conditions et avez lu et reconnu notre politique de confidentialité.", - "step1-submit": "C'est parti", - "step2-message": "Nous avons envoyé un email de vérification à", - "step2-code-error": "Oops. Votre code est faux. Veuillez réessayer.", - "step2-resend-alert": "Vous ne voyez pas le code?", - "step2-resend-submit": "Renvoyer", - "step2-resend-progress": "Envoie en cours...", - "step2-spam-alert": "Assurez-vous de vérifier vos spams.", - "step3-message": "Nous y sommes presque!", - "step4-message": "Enregistrez votre kit d'urgence", - "step4-description1": "Si vous n'arrivez plus à vous connecter à votre compte, votre kit d'urgence est le seul moyen d'y arriver.", - "step4-description2": "Nous vous recommandons de le télécharger et de le garder en sécurité.", - "step4-description3": "Il contient votre clef secrète que nous ne pouvons pas récupérer pour vous si vous la perdez.", - "step4-download": "Téléchargez le PDF", - "step5-send-invites": "Envoyer les invitations", - "step5-invite-team": "Invitez votre équipe", - "step5-subtitle": "Infisical a pour but d'être utilisé avec vos coéquipiers. Invitez-les à le tester.", - "step5-skip": "Passer" -} diff --git a/frontend/public/locales/fr/translations.json b/frontend/public/locales/fr/translations.json new file mode 100644 index 000000000..6914e7ea1 --- /dev/null +++ b/frontend/public/locales/fr/translations.json @@ -0,0 +1,299 @@ +{ + "activity": { + "title": "Journaux d'activité", + "subtitle": "Historique des événements pour ce projet Infisical.", + "event": { + "readSecrets": "Secrets Visualisés", + "updateSecrets": "Secrets Mis à jour", + "addSecrets": "Secrets Ajoutés", + "deleteSecrets": "Secrets Supprimés" + }, + "ip-address": "Adresse IP" + }, + "billing": { + "title": "Utilisation et Facturation", + "description": "Voir et gérer l'abonnement de votre organisation ici", + "subscription": "Abonnement", + "starter": { + "name": "Starter", + "price-explanation": "jusqu'à 5 membres de l'équipe", + "text": "Gérez n'importe quel projet jusqu'à 5 membres gratuitement!", + "subtext": "$5 par membre / mois par la suite." + }, + "professional": { + "name": "Professionnel", + "price-explanation": "/membre/mois", + "subtext": "Comprend des projets et des membres illimités.", + "text": "Suivez la gestion clé à mesure que vous grandissez." + }, + "enterprise": { + "name": "Entreprise", + "text": "Suivez la gestion clé à mesure que vous grandissez." + }, + "current-usage": "Utilisation actuelle", + "free": "Gratuit", + "downgrade": "Rétrograder", + "upgrade": "Améliorer", + "learn-more": "En savoir plus", + "custom-pricing": "Prix personnalisés", + "schedule-demo": "Planifier une démo" + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "Un projet avec ce nom existe déjà.", + "no-mobile": " Pour utiliser Infisical, veuillez vous connecter avec un appareil avec des dimensions plus grandes. ", + "email": "Email", + "password": "Mot de passe", + "first-name": "Prénom", + "last-name": "Nom", + "logout": "Déconnexion", + "validate-required": "Veuillez saisir votre {{name}}", + "maintenance-alert": "Nous rencontrons des difficultés techniques mineures. Nous travaillons sur leurs résolution dès maintenant. Revenez dans quelques minutes.", + "click-to-copy": "Cliquez pour copiez", + "project-id": "Identifiant du Projet", + "save-changes": "Sauvegarder les modifications", + "saved": "Enregistrée", + "drop-zone": "Glissez et déposez un fichier .env ou .yml ici.", + "drop-zone-keys": "Glissez et déposez un fichier .env ou .yml ici pour ajouter plus de clés.", + "role": "Rôle", + "role_admin": "administrateur", + "display-name": "Nom d'affichage", + "environment": "Environnement", + "expired-in": "Expire dans", + "language": "Langue", + "search": "Recherche...", + "note": "Note", + "view-more": "Voir plus", + "end-of-history": "Fin de l'historique", + "select-event": "Sélectionnez un événement", + "event": "Événement", + "user": "Utilisateur", + "source": "Source", + "time": "Heure", + "timestamp": "Horodatage" + }, + "dashboard": { + "title": "Secrets", + "og-title": "Gérez vos fichiers .env rapidement", + "og-description": "Infisical une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer leurs fichiers .env.", + "search-keys": "Recherche les clefs...", + "add-key": "Ajouter une clef", + "personal": "Personnel", + "personal-description": "Les clés personnelles ne sont visibles que pour vous", + "shared": "Partagé", + "shared-description": "Les clés partagées sont visibles à toute votre équipe", + "make-shared": "Rendre Partagé", + "make-personal": "Rendre Personnel", + "add-secret": "Ajouter un nouveau secret", + "check-docs": { + "button": "Vérifier la documentation", + "title": "Bon travail!", + "line1": "Félicitations pour avoir ajouté plus de secrets.", + "line2": "Voici comment les connecter à votre base de code." + }, + "sidebar": { + "secret": "Secret", + "key": "Clef", + "value": "Valeur", + "override": "Remplacer la valeur avec une valeur personnelle", + "version-history": "Historique des versions", + "comments": "Commentaires & Notes", + "personal-explanation": "Ce secret est personnel. Il n'est partagé avec aucun de vos coéquipiers.", + "generate-random-hex": "Générer un Hex aléatoire", + "digits": "chiffres", + "delete-key-dialog": { + "title": "Supprimer la clef", + "confirm-delete-message": "Êtes-vous sûr de vouloir supprimer ce secret? Cela ne peut pas être annulé." + } + } + }, + "integrations": { + "title": "Intégrations de Projet", + "description": "Gérez vos intégrations d'Infisical avec des services tiers.", + "no-integrations1": "Vous n'avez pas encore d'intégration. Quand vous en aurez, elles apparaîtront ici.", + "no-integrations2": "Pour commencer, cliquez sur l'une des options ci-dessous. La configuration se fait en 5 clics.", + "available": "Intégrations de plate-forme et cloud", + "available-text1": "Cliquez sur l'intégration que vous souhaitez connecter. Cela permettra à vos variables d'environnement de circuler automatiquement dans les services tiers sélectionnés.", + "available-text2": "Remarque: Lors d'une intégration avec Heroku, pour des raisons de sécurité, il est impossible de maintenir le chiffrage de bout en bout. En théorie, cela permet à Infisical de déchiffrer les variables d'environnement. En pratique, nous pouvons vous assurer que cela ne sera jamais fait, et cela nous permet de protéger vos secrets des mauvais acteurs en ligne. Le service Infisical de base restera toujours chiffré de bout en bout. Pour toutes vos intérogations, contactez support@infisical.com.", + "cloud-integrations": "Intégrations Cloud", + "framework-integrations": "Intégrations Framework", + "click-to-start": "Cliquez sur une intégration pour commencer à synchroniser les secrets avec elle.", + "click-to-setup": "Cliquez sur un framework pour obtenir les instructions de configuration.", + "grant-access-to-secrets": "Accordez un accès Infisical à vos secrets", + "why-infisical-needs-access": "La plupart des intégrations cloud nécessitent qu'Infisical puisse déchiffrer vos secrets afin qu'ils puissent être transmis.", + "grant-access-button": "Autoriser l'accès" + }, + "login": { + "title": "Connexion", + "og-title": "Connectez-vous à Infisical", + "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout permettant aux équipes de synchroniser et de gérer leurs fichiers .env.", + "login": "Se connecter", + "need-account": "Besoin d'un compte Infisical?", + "create-account": "Créer un compte", + "forgot-password": "Mot de passe oublié?", + "error-login": "Mauvais identifiants." + }, + "mfa": { + "title": "S'inscrire", + "og-title": "Remplacez les fichiers .env par 1 ligne de code. Inscrivez-vous à Infisical en 3 minutes.", + "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer des clefs API et des variables d'environnement. Fonctionne avec Node.js, Next.js, Gatsby, Nest.js ...", + "signup": "S'inscrire", + "already-have-account": "Déjà inscris? Se connecter", + "forgot-password": "Mot de passe oublié?", + "verify": "Vérifier", + "step1-start": "Bon, on commence!", + "step1-privacy": "En créant votre compte, vous acceptez nos conditions et avez lu et reconnu notre politique de confidentialité.", + "step1-submit": "C'est parti", + "step2-message": "Nous avons envoyé un email de vérification à", + "step2-code-error": "Oops. Votre code est faux. Essais restants:", + "step2-resend-alert": "Vous ne voyez pas le code?", + "step2-resend-submit": "Renvoyer", + "step2-resend-progress": "Envoie en cours...", + "step2-spam-alert": "Assurez-vous de vérifier vos spams.", + "step3-message": "Nous y sommes presque!", + "step4-message": "Enregistrez votre kit d'urgence", + "step4-description1": "Si vous n'arrivez plus à vous connecter à votre compte, votre kit d'urgence est le seul moyen d'y arriver.", + "step4-description2": "Nous vous recommandons de le télécharger et de le garder en sécurité.", + "step4-description3": "Il contient votre clef secrète que nous ne pouvons pas récupérer pour vous si vous la perdez.", + "step4-download": "Téléchargez le PDF", + "step5-send-invites": "Envoyer les invitations", + "step5-invite-team": "Invitez votre équipe", + "step5-subtitle": "Infisical a pour but d'être utilisé avec vos coéquipiers. Invitez-les à le tester.", + "step5-skip": "Passer" + }, + "nav": { + "support": { + "slack": "[NEW] Rejoignez le forum Slack", + "docs": "Lire les documentations", + "issue": "Ouvrir une issue Github", + "email": "Envoyez-nous un email" + }, + "user": { + "signed-in-as": "CONNECTÉ EN TANT QUE", + "current-organization": "ORGANISATION ACTUELLE", + "usage-billing": "Utilisation & Facturation", + "invite": "Inviter des membres", + "other-organizations": "AUTRE ORGANISATION" + }, + "menu": { + "project": "PROJET", + "secrets": "Secrets", + "members": "Membres", + "integrations": "Intégrations", + "project-settings": "Paramètres du Projet" + } + }, + "section": { + "incident": { + "incident-contacts": "Contacts Incidents", + "incident-contacts-description": "Ces contacts seront informés dans le cas improbable d'un incident grave.", + "no-incident-contacts": "Aucun contact incident trouvé.", + "add-contact": "Ajouter un contact", + "add-dialog": { + "title": "Ajouter un contact incident", + "description": "Ce contact sera informé dans le cas improbable d'un incident grave.", + "add-incident": "Ajouter un contact incident" + } + }, + "members": { + "add-member": "Ajouter un Membre", + "org-members": "Membres de l'organisation", + "org-members-description": "Gérer les membres de votre organisation. Ces utilisateurs pourraient ensuite être répartis en projets.", + "search-members": "Recherche des membres...", + "add-dialog": { + "add-member-to-project": "Ajoutez un membre à votre projet", + "already-all-invited": "Tous les utilisateurs de votre organisation sont déjà invités.", + "add-user-org-first": "Ajoutez d'abord plus d'utilisateurs à l'organisation.", + "user-will-email": "L'utilisateur recevra un email avec les instructions.", + "looking-add": "<0>Si vous cherchez à ajouter des utilisateurs à votre organisation,<1>cliquez ici", + "add-user-to-org": "Ajouter des Utilisateurs à l'Organisation" + } + }, + "password": { + "password": "Mot de passe", + "change": "Changer le mot de passe", + "current": "Mot de passe actuel", + "current-wrong": "Le mot de passe actuel peut être érroné", + "new": "Nouveau mot de passe", + "validate-base": "Le mot de passe doit contenir au moins:", + "validate-length": "14 caractères", + "validate-case": "1 caractère miniscule", + "validate-number": "1 chiffre" + }, + "token": { + "service-tokens": "Jetons de service", + "service-tokens-description": "Chaque jeton de service vous est spécifique, à un certain projet et à un certain environnement dans ce projet.", + "add-new": "Ajouter un nouveau jeton", + "add-dialog": { + "title": "Ajouter un jeton de service pour {{target}}", + "description": "Spécifiez le nom, l'environnement et la période d'expiration. Lorsqu'un jeton est généré, vous ne pourrez le voir qu'une seule fois avant qu'il ne disparaisse. Assurez-vous de le sauvegarder quelque part.", + "name": "Nom du jeton de service", + "add": "Ajouter un jeton de service", + "copy-service-token": "Copiez votre jeton de service", + "copy-service-token-description": "Une fois que vous aurez fermé cette fenêtre, vous ne reverrez plus jamais votre jeton de service" + } + } + }, + "settings": { + "members": { + "title": "Membres du projet", + "description": "Cette page affiche les membres du projet sélectionné." + }, + "org": { + "title": "Paramètres d'Organisation", + "description": "Gérer les membres de votre organisation. Ces utilisateurs pourraient ensuite être répartis en projets." + }, + "personal": { + "title": "Paramètres Personnels", + "description": "Consultez et gérez vos informations personnelles ici.", + "emergency": { + "name": "Kit d'urgence", + "text1": "Votre kit d'urgence contient les informations dont vous aurez besoin pour vous connecter à votre compte Infisical.", + "text2": "Seul le dernier kit d'urgence émis reste valide. Pour obtenir un nouveau kit d'urgence, vérifiez votre mot de passe.", + "download": "Télécharger le kit d'urgence" + }, + "change-language": "Changer de langue" + }, + "project": { + "title": "Paramètres du Projet", + "description": "Ces paramètres ne s'appliquent qu'au Projet actuellement sélectionné.", + "danger-zone": "Zone de danger", + "delete-project": "Supprimer le Projet", + "project-to-delete": "Projet à Supprimer", + "danger-zone-note": "Dès que vous supprimez ce projet, vous ne pourrez plus revenir en arrière. Cela supprimera immédiatement toutes les clefs. Si vous voulez toujours le faire, veuillez saisir le nom du projet ci-dessous.", + "delete-project-note": "Remarque: Vous ne pouvez supprimer qu'un projet que si vous en avez plus d'un.", + "project-id-description": "Pour intégrer Infisical dans votre base de code et obtenir une injection automatique de variables d'environnement, vous devez utiliser l'ID du projet suivant.", + "project-id-description2": "Pour plus de conseils, y compris des extraits de code pour diverses langues et frameworks, voir ", + "auto-generated": "Ceci est l'identifiant unique généré automatiquement pour votre projet. Il ne peut pas être modifié.", + "docs": "Documentation Infisical" + } + }, + "signup": { + "title": "S'inscrire", + "og-title": "Remplacez les fichiers .env par 1 ligne de code. Inscrivez-vous à Infisical en 3 minutes.", + "og-description": "Infisical, une plate-forme simple et chiffré de bout en bout qui permet aux équipes de synchroniser et de gérer des clefs API et des variables d'environnement. Fonctionne avec Node.js, Next.js, Gatsby, Nest.js ...", + "signup": "S'inscrire", + "already-have-account": "Déjà inscris? Se connecter", + "forgot-password": "Mot de passe oublié?", + "verify": "Vérifier", + "step1-start": "Bon, on commence!", + "step1-privacy": "En créant votre compte, vous acceptez nos conditions et avez lu et reconnu notre politique de confidentialité.", + "step1-submit": "C'est parti", + "step2-message": "Nous avons envoyé un email de vérification à", + "step2-code-error": "Oops. Votre code est faux. Veuillez réessayer.", + "step2-resend-alert": "Vous ne voyez pas le code?", + "step2-resend-submit": "Renvoyer", + "step2-resend-progress": "Envoie en cours...", + "step2-spam-alert": "Assurez-vous de vérifier vos spams.", + "step3-message": "Nous y sommes presque!", + "step4-message": "Enregistrez votre kit d'urgence", + "step4-description1": "Si vous n'arrivez plus à vous connecter à votre compte, votre kit d'urgence est le seul moyen d'y arriver.", + "step4-description2": "Nous vous recommandons de le télécharger et de le garder en sécurité.", + "step4-description3": "Il contient votre clef secrète que nous ne pouvons pas récupérer pour vous si vous la perdez.", + "step4-download": "Téléchargez le PDF", + "step5-send-invites": "Envoyer les invitations", + "step5-invite-team": "Invitez votre équipe", + "step5-subtitle": "Infisical a pour but d'être utilisé avec vos coéquipiers. Invitez-les à le tester.", + "step5-skip": "Passer" + } +} \ No newline at end of file diff --git a/frontend/public/locales/ko/billing.json b/frontend/public/locales/ko/billing.json deleted file mode 100644 index 788afa8e4..000000000 --- a/frontend/public/locales/ko/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "요금제 & 결제", - "description": "이곳에서 조직의 구독을 확인하고 관리할 수 있어요.", - "subscription": "구독", - "starter": { - "name": "스타터", - "price-explanation": "5명의 팀 맴버까지", - "text": "어떤 프로젝트든 다섯명의 맴버까지 무료로 이용할 수 있어요!", - "subtext": "$5명/달 로 바뀔 예정입니다." - }, - "professional": { - "name": "전문가", - "price-explanation": "/맴버/달", - "subtext": "무제한의 프로젝트와 맴버", - "text": "조직의 성장에 따라 유연하게 시크릿을 관리하세요." - }, - "enterprise": { - "name": "엔터프라이즈", - "text": "조직의 성장에 따라 유연하게 시크릿을 관리하세요." - }, - "current-usage": "현재 요금제", - "free": "무료", - "downgrade": "다운그레이드", - "upgrade": "업그레이드", - "learn-more": "자세히 알아보기", - "custom-pricing": "커스텀 가격", - "schedule-demo": "데모 예약하기" -} diff --git a/frontend/public/locales/ko/common.json b/frontend/public/locales/ko/common.json deleted file mode 100644 index f0692ebf7..000000000 --- a/frontend/public/locales/ko/common.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "동일한 이름을 가진 프로젝트가 이미 존재해요.", - "no-mobile": " Infisical을 사용하려면, 큰 화면을 가진 디바이스로 로그인하여 주세요.", - "email": "메일", - "password": "비밀번호", - "first-name": "이름", - "last-name": "성", - "logout": "로그아웃", - "validate-required": "{{name}} 을/를 입력하세요.", - "maintenance-alert": "We are experiencing minor technical difficulties. We are working on solving it right now. Please come back in a few minutes.", - "click-to-copy": "클릭하여 복사하기", - "project-id": "프로젝트 ID", - "save-changes": "변경사항 저장하기", - "saved": "저장됨", - "drop-zone": ".env 파일을 이곳에 드래그 & 드롭 하세요.", - "drop-zone-keys": "이곳에 .env 파일을 드래그 & 드롭 하여 더 많은 키들을 추가하세요.", - "role": "Role", - "role_admin": "admin", - "display-name": "표시 이름", - "environment": "환경", - "expired-in": "만료 기한:", - "language": "언어", - "search": "검색하기...", - "note": "Note" -} \ No newline at end of file diff --git a/frontend/public/locales/ko/dashboard.json b/frontend/public/locales/ko/dashboard.json deleted file mode 100644 index 73fcf155b..000000000 --- a/frontend/public/locales/ko/dashboard.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "title": "시크릿", - "og-title": "빠르게 .env 파일을 관리하세요", - "og-description": "Infisical은 팀원과 .env파일을 공유할 수 있는 심플한 end-to-end 암호화 플렛폼입니다.", - "search-keys": "키 검색하기...", - "add-key": "키 추가하기", - "personal": "개인", - "personal-description": "개인 키는 오직 본인만 볼 수 있어요", - "shared": "공유", - "shared-description": "공유 키는 팀 전체가 볼 수 있어요", - "make-shared": "공유로 만들기", - "make-personal": "개인으로 만들기", - "check-docs": { - "button": "문서 확인하기", - "title": "좋았어요!", - "line1": "더 많은 시크릿들을 추가한 것을 축하합니다.", - "line2": "코드와 연결하는 사용하는 방법을 한번 알아보지 않을래요?" - }, - "sidebar": { - "secret": "Secret", - "key": "Key", - "value": "Value", - "override": "Override value with a personal value", - "version-history": "Version History", - "comments": "Comments & Notes", - "personal-explanation": "This secret is personal. It is not shared with any of your teammates.", - "generate-random-hex": "Generate Random Hex", - "digits": "digits" - } -} diff --git a/frontend/public/locales/ko/integrations.json b/frontend/public/locales/ko/integrations.json deleted file mode 100644 index 7431831ae..000000000 --- a/frontend/public/locales/ko/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "available": "사용 가능한 연동", - "available-text1": "연결하고 싶은 서비스를 클릭하세요. 환경 변수가 선택한 외부 서비스와 자동으로 연동됩니다.", - "available-text2": "참고: Heroku와의 연동에서는 보안상의 이유로 End-To-End 암호화를 유지하는 것이 불가능합니다. 이론적으로는 Infisical이 시크릿을 읽는것이 가능하지만, 절대 그러지 않는다고 확신할 수 있습니다. 핵심 Infisical 서비스는 항상 End-To-End 암호화 상태를 유지합니다. 질문이 있으면 support@infisical.com으로 문의하세요.", - "description": "외부 서비스와 함께 Infisical을 연동하고 관리하세요", - "no-integrations1": "연동된 서비스가 없어요. 연동하게 된다면 이곳에서 표시돼요.", - "no-integrations2": "시작하려면, 아래의 옵션을 클릭하세요. 대체로 5분 이내로 가능해요.", - "title": "프로젝트 연동", - "cloud-integrations": "Cloud Integrations", - "framework-integrations": "Framework Integrations", - "click-to-start": "Click on an integration to begin syncing secrets to it.", - "click-to-setup": "Click on a framework to get the setup instructions.", - "grant-access-to-secrets": "Grant Infisical access to your secrets", - "why-infisical-needs-access": "Most cloud integrations require Infisical to be able to decrypt your secrets so they can be forwarded over.", - "grant-access-button": "Grant access" -} diff --git a/frontend/public/locales/ko/login.json b/frontend/public/locales/ko/login.json deleted file mode 100644 index 70a77d69f..000000000 --- a/frontend/public/locales/ko/login.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "title": "로그인", - "og-title": "Infisical에 로그인하기", - "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", - "login": "로그인", - "need-account": "Infisical계정이 필요하신가요?", - "create-account": "회원가입 하기" -} diff --git a/frontend/public/locales/ko/mfa.json b/frontend/public/locales/ko/mfa.json deleted file mode 100644 index 6c17a68cf..000000000 --- a/frontend/public/locales/ko/mfa.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "title": "회원가입", - "og-title": "한줄의 코드르 .env파일을 교체하세요. 3분이면 가입할 수 있어요.", - "og-description": "Infisical은 팀원과 .env파일을 공유하고 연동할 수 있는 심플한 end-to-end 암호화 플렛폼입니다. Node.js, Next.js, Gatsby, Nest.js 와 같은 다양한 플렛폼에서 작동해요.", - "signup": "회원가입", - "already-have-account": "이미 계정이 있나요? 로그인하기", - "forgot-password": "비밀번호를 잊으셨나요?", - "verify": "인증", - "step1-start": "시작하기", - "step1-privacy": "회원가입시 약관과 개인 정보 보호 정책을 읽고 동의한 것으로 간주합니다.", - "step1-submit": "시작하기", - "step2-message": "{{email}}로 인증 메일을 전송하였습니다{{email}}", - "step2-code-error": "코드가 잘못된 것 같아요. 남은 시도:", - "step2-spam-alert": "스팸함에 메일이 있지는 않은지 확인하세요", - "step3-message": "거의다 끝났어요!", - "step4-message": "긴급복구 키트 저장하기", - "step4-description1": "계정이 잠겼을 경우 비상 키트를 사용하여 로그인할 수 있어요.", - "step4-description2": "다운로드 후 안전한 곳에 보관하는 것을 추천합니다.", - "step4-description3": "분실시 접근하거나 복구할 수 없는 시크릿 키가 포함되어 있어요.", - "step4-download": "PDF 다운로드" -} diff --git a/frontend/public/locales/ko/nav.json b/frontend/public/locales/ko/nav.json deleted file mode 100644 index b07510ff4..000000000 --- a/frontend/public/locales/ko/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "[NEW] 슬랙 포럼에 가입하기", - "docs": "문서 보기", - "issue": "깃허브 이슈 열기", - "email": "Infisical팀에게 메일 보내기" - }, - "user": { - "signed-in-as": "다음으로 로그인됨", - "current-organization": "현재 조직", - "usage-billing": "요금제 & 결제", - "invite": "맴버 초대하기", - "other-organizations": "다른 조직" - }, - "menu": { - "project": "프로젝트", - "secrets": "시크릿", - "members": "맴버", - "integrations": "연동", - "project-settings": "프로젝트 설정" - } -} diff --git a/frontend/public/locales/ko/section-incident.json b/frontend/public/locales/ko/section-incident.json deleted file mode 100644 index cbafc5ecb..000000000 --- a/frontend/public/locales/ko/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "add-contact": "연락처 추가하기", - "add-dialog": { - "add-incident": "비상 연락처 추가하기", - "description": "중대한 일이 생길 경우, 이 연락처로 알림이 전송됩니다.", - "title": "비상 연락처 추가하기" - }, - "incident-contacts": "비상 연락망", - "incident-contacts-description": "중대한 일이 생길 경우, 아래의 연락처로 알림이 전송됩니다.", - "no-incident-contacts": "비상 연락망이 존재하지 않아요." -} diff --git a/frontend/public/locales/ko/section-members.json b/frontend/public/locales/ko/section-members.json deleted file mode 100644 index 848574aff..000000000 --- a/frontend/public/locales/ko/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "맴버 추가하기", - "org-members": "조직 맴버", - "search-members": "맴버를 검색하기...", - "add-dialog": { - "add-member-to-project": "프로젝트에 맴버 추가하기", - "already-all-invited": "조직의 모든 유저가 이미 초대되었습니다.", - "add-user-org-first": "유저를 먼저 조직에 추가해 주세요.", - "user-will-email": "유저는 안내가 포함된 메일을 받게 됩니다.", - "looking-add": "<0>조직에 유저를 추가하고 싶다면,<1>여기를 클릭하세요", - "add-user-to-org": "조직에 유저 추가하기" - }, - "org-members-description": "조직의 맴버들을 관리하세요." -} diff --git a/frontend/public/locales/ko/section-password.json b/frontend/public/locales/ko/section-password.json deleted file mode 100644 index e7c6a6b74..000000000 --- a/frontend/public/locales/ko/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "비밀번호", - "change": "비밀번호 변경", - "current": "현재 비밀번호", - "new": "새 비밀번호", - "current-wrong": "현재 비밀번호가 잘못되었어요", - "validate-base": "비밀번호는 다음 조건을 만족해야 합니다:", - "validate-length": "14 글자 이상", - "validate-case": "1개 이상의 소문자", - "validate-number": "1개 이상의 숫자" -} diff --git a/frontend/public/locales/ko/section-token.json b/frontend/public/locales/ko/section-token.json deleted file mode 100644 index 936c6066c..000000000 --- a/frontend/public/locales/ko/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "add-dialog": { - "add": "서비스 토큰 추가하기", - "copy-service-token": "서비스 토큰 복사하기", - "copy-service-token-description": "팝업을 닫을 시 다시는 토큰을 확인할 수 없어요.", - "description": "이름, 환경, 만료일을 지정하세요. 토큰이 생성되면 최초 한번만 볼 수 있어요. 안전한 곳에 저장하세요.", - "name": "서비스 토큰 이름", - "title": "{{target}}의 토큰 추가하기" - }, - "add-new": "새 토큰 추가하기", - "service-tokens": "서비스 토큰", - "service-tokens-description": "모든 서비스 토큰은 프로젝트 및 환경에 따라 다릅니다." -} diff --git a/frontend/public/locales/ko/settings-members.json b/frontend/public/locales/ko/settings-members.json deleted file mode 100644 index 5954b2bb5..000000000 --- a/frontend/public/locales/ko/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "맴버 설정", - "description": "선택한 프로젝트의 맴버를 확인하세요." -} diff --git a/frontend/public/locales/ko/settings-org.json b/frontend/public/locales/ko/settings-org.json deleted file mode 100644 index 64b5e5e3e..000000000 --- a/frontend/public/locales/ko/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "조직 설정", - "description": "조직의 맴버를 관리하세요." -} diff --git a/frontend/public/locales/ko/settings-personal.json b/frontend/public/locales/ko/settings-personal.json deleted file mode 100644 index 2234272e4..000000000 --- a/frontend/public/locales/ko/settings-personal.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "개인 설정", - "description": "계정 및 기본적인 설정을 확인하고 변경하세요.", - "emergency": { - "name": "긴급복구 키트", - "text1": "긴급복구 키트는 Infisical계정에 로그인 할 수 있는 정보를 가지고 있어요.", - "text2": "오직 마지막으로 발급한 긴급복구 키트만 사용 가능해요. 새로운 긴급복구 키트를 받으려면, 비밀번호를 입력하세요.", - "download": "긴급복구 키트 다운로드" - }, - "change-language": "언어 변경하기" -} diff --git a/frontend/public/locales/ko/settings-project.json b/frontend/public/locales/ko/settings-project.json deleted file mode 100644 index 8dca5941c..000000000 --- a/frontend/public/locales/ko/settings-project.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "프로젝트 설정", - "description": "현재 선택한 프로젝트에 대해서 설정해요.", - "auto-generated": "자동으로 생성된 고유한 키 입니다. 변경할 수 없어요.", - "danger-zone": "위험존", - "danger-zone-note": "프로젝트를 삭제한다면 모든 키가 즉시 삭제되며 다시는 되돌릴 수 없어요. 삭제를 원한다면 프로젝트 이름을 아래에 적어주세요.", - "delete-project": "프로젝트 삭제", - "delete-project-note": "노트: 최소 한개 이상의 프로젝트는 조직에 존재해야 해요.", - "docs": "Infisical 문서", - "project-id-description": "다른 코드에서 Infisical과 환경변수를 연동하기 위해서는 프로젝트 ID가 필요해요.", - "project-id-description2": "다양한 언어 및 프레임워크에 대한 가이드를 확인하고 싶다면, 다음을 확인하세요. ", - "project-to-delete": "삭제할 프로젝트" -} diff --git a/frontend/public/locales/ko/signup.json b/frontend/public/locales/ko/signup.json deleted file mode 100644 index 3b4576963..000000000 --- a/frontend/public/locales/ko/signup.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "title": "회원가입", - "og-title": "한줄의 코드르 .env파일을 교체하세요. 3분이면 가입할 수 있어요.", - "og-description": "Infisical은 팀원과 .env파일을 공유하고 연동할 수 있는 심플한 end-to-end 암호화 플렛폼입니다. Node.js, Next.js, Gatsby, Nest.js 와 같은 다양한 플렛폼에서 작동해요.", - "signup": "회원가입", - "already-have-account": "이미 계정이 있나요? 로그인하기", - "forgot-password": "비밀번호를 잊으셨나요?", - "verify": "인증", - "step1-start": "시작하기", - "step1-privacy": "회원가입시 약관과 개인 정보 보호 정책을 읽고 동의한 것으로 간주합니다.", - "step1-submit": "시작하기", - "step2-message": "{{email}}로 인증 메일을 전송하였습니다{{email}}", - "step2-code-error": "코드가 잘못된 것 같아요. 다시 시도해주세요.", - "step2-spam-alert": "스팸함에 메일이 있지는 않은지 확인하세요", - "step3-message": "거의다 끝났어요!", - "step4-message": "긴급복구 키트 저장하기", - "step4-description1": "계정이 잠겼을 경우 비상 키트를 사용하여 로그인할 수 있어요.", - "step4-description2": "다운로드 후 안전한 곳에 보관하는 것을 추천합니다.", - "step4-description3": "분실시 접근하거나 복구할 수 없는 시크릿 키가 포함되어 있어요.", - "step4-download": "PDF 다운로드" -} diff --git a/frontend/public/locales/ko/translations.json b/frontend/public/locales/ko/translations.json new file mode 100644 index 000000000..eea81f37e --- /dev/null +++ b/frontend/public/locales/ko/translations.json @@ -0,0 +1,259 @@ +{ + "billing": { + "title": "요금제 & 결제", + "description": "이곳에서 조직의 구독을 확인하고 관리할 수 있어요.", + "subscription": "구독", + "starter": { + "name": "스타터", + "price-explanation": "5명의 팀 맴버까지", + "text": "어떤 프로젝트든 다섯명의 맴버까지 무료로 이용할 수 있어요!", + "subtext": "$5명/달 로 바뀔 예정입니다." + }, + "professional": { + "name": "전문가", + "price-explanation": "/맴버/달", + "subtext": "무제한의 프로젝트와 맴버", + "text": "조직의 성장에 따라 유연하게 시크릿을 관리하세요." + }, + "enterprise": { + "name": "엔터프라이즈", + "text": "조직의 성장에 따라 유연하게 시크릿을 관리하세요." + }, + "current-usage": "현재 요금제", + "free": "무료", + "downgrade": "다운그레이드", + "upgrade": "업그레이드", + "learn-more": "자세히 알아보기", + "custom-pricing": "커스텀 가격", + "schedule-demo": "데모 예약하기" + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "동일한 이름을 가진 프로젝트가 이미 존재해요.", + "no-mobile": " Infisical을 사용하려면, 큰 화면을 가진 디바이스로 로그인하여 주세요.", + "email": "메일", + "password": "비밀번호", + "first-name": "이름", + "last-name": "성", + "logout": "로그아웃", + "validate-required": "{{name}} 을/를 입력하세요.", + "maintenance-alert": "We are experiencing minor technical difficulties. We are working on solving it right now. Please come back in a few minutes.", + "click-to-copy": "클릭하여 복사하기", + "project-id": "프로젝트 ID", + "save-changes": "변경사항 저장하기", + "saved": "저장됨", + "drop-zone": ".env 파일을 이곳에 드래그 & 드롭 하세요.", + "drop-zone-keys": "이곳에 .env 파일을 드래그 & 드롭 하여 더 많은 키들을 추가하세요.", + "role": "Role", + "role_admin": "admin", + "display-name": "표시 이름", + "environment": "환경", + "expired-in": "만료 기한:", + "language": "언어", + "search": "검색하기...", + "note": "Note" + }, + "dashboard": { + "title": "시크릿", + "og-title": "빠르게 .env 파일을 관리하세요", + "og-description": "Infisical은 팀원과 .env파일을 공유할 수 있는 심플한 end-to-end 암호화 플렛폼입니다.", + "search-keys": "키 검색하기...", + "add-key": "키 추가하기", + "personal": "개인", + "personal-description": "개인 키는 오직 본인만 볼 수 있어요", + "shared": "공유", + "shared-description": "공유 키는 팀 전체가 볼 수 있어요", + "make-shared": "공유로 만들기", + "make-personal": "개인으로 만들기", + "check-docs": { + "button": "문서 확인하기", + "title": "좋았어요!", + "line1": "더 많은 시크릿들을 추가한 것을 축하합니다.", + "line2": "코드와 연결하는 사용하는 방법을 한번 알아보지 않을래요?" + }, + "sidebar": { + "secret": "Secret", + "key": "Key", + "value": "Value", + "override": "Override value with a personal value", + "version-history": "Version History", + "comments": "Comments & Notes", + "personal-explanation": "This secret is personal. It is not shared with any of your teammates.", + "generate-random-hex": "Generate Random Hex", + "digits": "digits" + } + }, + "integrations": { + "available": "사용 가능한 연동", + "available-text1": "연결하고 싶은 서비스를 클릭하세요. 환경 변수가 선택한 외부 서비스와 자동으로 연동됩니다.", + "available-text2": "참고: Heroku와의 연동에서는 보안상의 이유로 End-To-End 암호화를 유지하는 것이 불가능합니다. 이론적으로는 Infisical이 시크릿을 읽는것이 가능하지만, 절대 그러지 않는다고 확신할 수 있습니다. 핵심 Infisical 서비스는 항상 End-To-End 암호화 상태를 유지합니다. 질문이 있으면 support@infisical.com으로 문의하세요.", + "description": "외부 서비스와 함께 Infisical을 연동하고 관리하세요", + "no-integrations1": "연동된 서비스가 없어요. 연동하게 된다면 이곳에서 표시돼요.", + "no-integrations2": "시작하려면, 아래의 옵션을 클릭하세요. 대체로 5분 이내로 가능해요.", + "title": "프로젝트 연동", + "cloud-integrations": "Cloud Integrations", + "framework-integrations": "Framework Integrations", + "click-to-start": "Click on an integration to begin syncing secrets to it.", + "click-to-setup": "Click on a framework to get the setup instructions.", + "grant-access-to-secrets": "Grant Infisical access to your secrets", + "why-infisical-needs-access": "Most cloud integrations require Infisical to be able to decrypt your secrets so they can be forwarded over.", + "grant-access-button": "Grant access" + }, + "login": { + "title": "로그인", + "og-title": "Infisical에 로그인하기", + "og-description": "Infisical a simple end-to-end encrypted platform that enables teams to sync and manage their .env files.", + "login": "로그인", + "need-account": "Infisical계정이 필요하신가요?", + "create-account": "회원가입 하기" + }, + "mfa": { + "title": "회원가입", + "og-title": "한줄의 코드르 .env파일을 교체하세요. 3분이면 가입할 수 있어요.", + "og-description": "Infisical은 팀원과 .env파일을 공유하고 연동할 수 있는 심플한 end-to-end 암호화 플렛폼입니다. Node.js, Next.js, Gatsby, Nest.js 와 같은 다양한 플렛폼에서 작동해요.", + "signup": "회원가입", + "already-have-account": "이미 계정이 있나요? 로그인하기", + "forgot-password": "비밀번호를 잊으셨나요?", + "verify": "인증", + "step1-start": "시작하기", + "step1-privacy": "회원가입시 약관과 개인 정보 보호 정책을 읽고 동의한 것으로 간주합니다.", + "step1-submit": "시작하기", + "step2-message": "{{email}}로 인증 메일을 전송하였습니다{{email}}", + "step2-code-error": "코드가 잘못된 것 같아요. 남은 시도:", + "step2-spam-alert": "스팸함에 메일이 있지는 않은지 확인하세요", + "step3-message": "거의다 끝났어요!", + "step4-message": "긴급복구 키트 저장하기", + "step4-description1": "계정이 잠겼을 경우 비상 키트를 사용하여 로그인할 수 있어요.", + "step4-description2": "다운로드 후 안전한 곳에 보관하는 것을 추천합니다.", + "step4-description3": "분실시 접근하거나 복구할 수 없는 시크릿 키가 포함되어 있어요.", + "step4-download": "PDF 다운로드" + }, + "nav": { + "support": { + "slack": "[NEW] 슬랙 포럼에 가입하기", + "docs": "문서 보기", + "issue": "깃허브 이슈 열기", + "email": "Infisical팀에게 메일 보내기" + }, + "user": { + "signed-in-as": "다음으로 로그인됨", + "current-organization": "현재 조직", + "usage-billing": "요금제 & 결제", + "invite": "맴버 초대하기", + "other-organizations": "다른 조직" + }, + "menu": { + "project": "프로젝트", + "secrets": "시크릿", + "members": "맴버", + "integrations": "연동", + "project-settings": "프로젝트 설정" + } + }, + "section": { + "incident": { + "add-contact": "연락처 추가하기", + "add-dialog": { + "add-incident": "비상 연락처 추가하기", + "description": "중대한 일이 생길 경우, 이 연락처로 알림이 전송됩니다.", + "title": "비상 연락처 추가하기" + }, + "incident-contacts": "비상 연락망", + "incident-contacts-description": "중대한 일이 생길 경우, 아래의 연락처로 알림이 전송됩니다.", + "no-incident-contacts": "비상 연락망이 존재하지 않아요." + }, + "members": { + "add-member": "맴버 추가하기", + "org-members": "조직 맴버", + "search-members": "맴버를 검색하기...", + "add-dialog": { + "add-member-to-project": "프로젝트에 맴버 추가하기", + "already-all-invited": "조직의 모든 유저가 이미 초대되었습니다.", + "add-user-org-first": "유저를 먼저 조직에 추가해 주세요.", + "user-will-email": "유저는 안내가 포함된 메일을 받게 됩니다.", + "looking-add": "<0>조직에 유저를 추가하고 싶다면,<1>여기를 클릭하세요", + "add-user-to-org": "조직에 유저 추가하기" + }, + "org-members-description": "조직의 맴버들을 관리하세요." + }, + "password": { + "password": "비밀번호", + "change": "비밀번호 변경", + "current": "현재 비밀번호", + "new": "새 비밀번호", + "current-wrong": "현재 비밀번호가 잘못되었어요", + "validate-base": "비밀번호는 다음 조건을 만족해야 합니다:", + "validate-length": "14 글자 이상", + "validate-case": "1개 이상의 소문자", + "validate-number": "1개 이상의 숫자" + }, + "token": { + "add-dialog": { + "add": "서비스 토큰 추가하기", + "copy-service-token": "서비스 토큰 복사하기", + "copy-service-token-description": "팝업을 닫을 시 다시는 토큰을 확인할 수 없어요.", + "description": "이름, 환경, 만료일을 지정하세요. 토큰이 생성되면 최초 한번만 볼 수 있어요. 안전한 곳에 저장하세요.", + "name": "서비스 토큰 이름", + "title": "{{target}}의 토큰 추가하기" + }, + "add-new": "새 토큰 추가하기", + "service-tokens": "서비스 토큰", + "service-tokens-description": "모든 서비스 토큰은 프로젝트 및 환경에 따라 다릅니다." + } + }, + "settings": { + "members": { + "title": "맴버 설정", + "description": "선택한 프로젝트의 맴버를 확인하세요." + }, + "org": { + "title": "조직 설정", + "description": "조직의 맴버를 관리하세요." + }, + "personal": { + "title": "개인 설정", + "description": "계정 및 기본적인 설정을 확인하고 변경하세요.", + "emergency": { + "name": "긴급복구 키트", + "text1": "긴급복구 키트는 Infisical계정에 로그인 할 수 있는 정보를 가지고 있어요.", + "text2": "오직 마지막으로 발급한 긴급복구 키트만 사용 가능해요. 새로운 긴급복구 키트를 받으려면, 비밀번호를 입력하세요.", + "download": "긴급복구 키트 다운로드" + }, + "change-language": "언어 변경하기" + }, + "project": { + "title": "프로젝트 설정", + "description": "현재 선택한 프로젝트에 대해서 설정해요.", + "auto-generated": "자동으로 생성된 고유한 키 입니다. 변경할 수 없어요.", + "danger-zone": "위험존", + "danger-zone-note": "프로젝트를 삭제한다면 모든 키가 즉시 삭제되며 다시는 되돌릴 수 없어요. 삭제를 원한다면 프로젝트 이름을 아래에 적어주세요.", + "delete-project": "프로젝트 삭제", + "delete-project-note": "노트: 최소 한개 이상의 프로젝트는 조직에 존재해야 해요.", + "docs": "Infisical 문서", + "project-id-description": "다른 코드에서 Infisical과 환경변수를 연동하기 위해서는 프로젝트 ID가 필요해요.", + "project-id-description2": "다양한 언어 및 프레임워크에 대한 가이드를 확인하고 싶다면, 다음을 확인하세요. ", + "project-to-delete": "삭제할 프로젝트" + } + }, + "signup": { + "title": "회원가입", + "og-title": "한줄의 코드르 .env파일을 교체하세요. 3분이면 가입할 수 있어요.", + "og-description": "Infisical은 팀원과 .env파일을 공유하고 연동할 수 있는 심플한 end-to-end 암호화 플렛폼입니다. Node.js, Next.js, Gatsby, Nest.js 와 같은 다양한 플렛폼에서 작동해요.", + "signup": "회원가입", + "already-have-account": "이미 계정이 있나요? 로그인하기", + "forgot-password": "비밀번호를 잊으셨나요?", + "verify": "인증", + "step1-start": "시작하기", + "step1-privacy": "회원가입시 약관과 개인 정보 보호 정책을 읽고 동의한 것으로 간주합니다.", + "step1-submit": "시작하기", + "step2-message": "{{email}}로 인증 메일을 전송하였습니다{{email}}", + "step2-code-error": "코드가 잘못된 것 같아요. 다시 시도해주세요.", + "step2-spam-alert": "스팸함에 메일이 있지는 않은지 확인하세요", + "step3-message": "거의다 끝났어요!", + "step4-message": "긴급복구 키트 저장하기", + "step4-description1": "계정이 잠겼을 경우 비상 키트를 사용하여 로그인할 수 있어요.", + "step4-description2": "다운로드 후 안전한 곳에 보관하는 것을 추천합니다.", + "step4-description3": "분실시 접근하거나 복구할 수 없는 시크릿 키가 포함되어 있어요.", + "step4-download": "PDF 다운로드" + } +} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/activity.json b/frontend/public/locales/pt-BR/activity.json deleted file mode 100644 index 9ffdf766d..000000000 --- a/frontend/public/locales/pt-BR/activity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Registro de Atividade", - "subtitle": "Histórico de eventos para esse projeto Infisical.", - "event": { - "readSecrets": "Segredos Visualizados", - "updateSecrets": "Segredos Atualizados", - "addSecrets": "Segredos Adicionados", - "deleteSecrets": "Segredos Excluídos" - }, - "ip-address": "Endereço IP" -} diff --git a/frontend/public/locales/pt-BR/billing.json b/frontend/public/locales/pt-BR/billing.json deleted file mode 100644 index db784ab2d..000000000 --- a/frontend/public/locales/pt-BR/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Uso & Faturamento", - "description": "Visualize e gerencie a assinatura da sua organização aqui", - "subscription": "Inscrição", - "starter": { - "name": "Base", - "price-explanation": "Até 5 membros de equipe", - "text": "Gerencie qualquer projeto com 5 membros gratuitamente!", - "subtext": "$5 por membro adicional / mês." - }, - "professional": { - "name": "Profissional", - "price-explanation": "/membro/mês", - "subtext": "Inclui projetos e membros ilimitados.", - "text": "Acompanhe o gerenciamento de chaves à medida que você cresce." - }, - "enterprise": { - "name": "Empreendimento", - "text": "Acompanhe o gerenciamento de chaves à medida que você cresce." - }, - "current-usage": "Uso atual", - "free": "Grátis", - "downgrade": "Reduzir", - "upgrade": "Melhorar", - "learn-more": "Saber Mais", - "custom-pricing": "Preço Personalizado", - "schedule-demo": "Agende uma Demonstração" -} diff --git a/frontend/public/locales/pt-BR/common.json b/frontend/public/locales/pt-BR/common.json deleted file mode 100644 index 05b0b87fa..000000000 --- a/frontend/public/locales/pt-BR/common.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "Já exite um projeto com este nome.", - "no-mobile": "Para usar o Infisical, faça o login através de um dispositivo com dimensões maiores.", - "email": "Email", - "password": "Senha", - "first-name": "Primeiro Nome", - "last-name": "Ultimo Nome", - "logout": "Sair", - "validate-required": "Por favor insira o seu {{name}}", - "maintenance-alert": "Estamos passando por pequenas dificuldades técnicas. Estamos trabalhando para resolvê-las agora. Por favor, volte dentro de alguns minutos.", - "click-to-copy": "Clique para copiar", - "project-id": "ID do Projeto", - "save-changes": "Salvar Alterações", - "saved": "Salvou", - "drop-zone": "Arraste e solte seu arquivo .env aqui.", - "drop-zone-keys": "Arraste e solte seu arquivo .env aqui para adicionar mais chaves.", - "role": "Role", - "role_admin": "admin", - "display-name": "Nome de exibição", - "environment": "Ambiente", - "expired-in": "Expira em", - "language": "Idioma", - "search": "Procurar...", - "note": "Note", - "view-more": "Ver mais", - "end-of-history": "Fim do Histórico", - "select-event": "Selecione um evento", - "event": "Evento", - "user": "Usuário", - "source": "Fonte", - "time": "Data/Hora", - "timestamp": "Timestamp" -} diff --git a/frontend/public/locales/pt-BR/dashboard.json b/frontend/public/locales/pt-BR/dashboard.json deleted file mode 100644 index 4f4474237..000000000 --- a/frontend/public/locales/pt-BR/dashboard.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "title": "Segredos", - "og-title": "Gerencie seus arquivos .env em segundos", - "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem seus arquivos .env.", - "search-keys": "Pesquisar chaves...", - "add-key": "Adicionar Chave", - "personal": "Pessoal", - "personal-description": "As chaves pessoais são visíveis apenas para você", - "shared": "Compartilhado", - "shared-description": "As chaves compartilhadas ficam visíveis para toda a sua equipe", - "make-shared": "Tornar Compartilhado", - "make-personal": "Tornar Pessoal", - "check-docs": { - "button": "Checkar Documentação", - "title": "Bom trabalho!!", - "line1": "Parabéns por adicionar mais segredos.", - "line2": "Veja como conectá-los à sua base de código." - }, - "sidebar": { - "secret": "Segredo", - "key": "Chave", - "value": "Valor", - "override": "Substitua o valor por um valor pessoal", - "version-history": "Histórico da versão", - "comments": "Comentários e Notas", - "personal-explanation": "Este segredo é pessoal. Não é compartilhado com nenhum de seus colegas de equipe.", - "generate-random-hex": "Gerar HEX Aleatório", - "digits": "dígitos", - "delete-key-dialog": { - "title": "Excluir Chave", - "confirm-delete-message": "Você tem certeza que deseja excluir esta chave? Essa ação não pode ser desfeita." - } - } -} diff --git a/frontend/public/locales/pt-BR/integrations.json b/frontend/public/locales/pt-BR/integrations.json deleted file mode 100644 index 21c20db5c..000000000 --- a/frontend/public/locales/pt-BR/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Integrações de Projetos", - "description": "Gerencie suas integrações da Infisical com serviços de terceiros.", - "no-integrations1": "Você ainda não tem integrações configuradas. Quando você fizer isso, elas aparecerão aqui.", - "no-integrations2": "Para começar, clique em qualquer uma das opções abaixo. Leva 5 cliques para configurar.", - "available": "Integrações de Plataforma e em Nuvem", - "available-text1": "Clique na integração que deseja conectar. Isso permitirá que suas variáveis de ambiente fluam automaticamente para serviços de terceiros selecionados.", - "available-text2": "Observação: durante uma integração com o Heroku, por questões de segurança, é impossível manter a criptografia de ponta a ponta. Em teoria, isso permite que o Infisical descriptografe suas variáveis de ambiente. Na prática, podemos garantir que isso nunca será feito e nos permite proteger seus segredos de pessoas mal-intencionadas online. O serviço básico da Infisical sempre permanecerá criptografado de ponta a ponta. Em caso de dúvidas, entre em contato com support@infisical.com.", - "cloud-integrations": "Integrações em Nuvem", - "framework-integrations": "Integrações com framework", - "click-to-start": "Clique em uma integração para começar a sincronizar segredos com ela.", - "click-to-setup": "Clique em uma estrutura para obter as instruções de configuração.", - "grant-access-to-secrets": "Conceda acesso Infisical aos seus segredos", - "why-infisical-needs-access": "A maioria das integrações em Nuvem exige que o Infisical seja capaz de descriptografar seus segredos para que possam ser encaminhados.", - "grant-access-button": "Garantir acesso" -} diff --git a/frontend/public/locales/pt-BR/login.json b/frontend/public/locales/pt-BR/login.json deleted file mode 100644 index e06a59acd..000000000 --- a/frontend/public/locales/pt-BR/login.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "title": "Entrar", - "og-title": "Entrar no Infisical", - "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem seus arquivos .env.", - "login": "Entrar", - "need-account": "Precisa de uma conta Infisical?", - "forgot-password": "Esqueceu sua senha?", - "create-account": "Criar uma conta" -} diff --git a/frontend/public/locales/pt-BR/mfa.json b/frontend/public/locales/pt-BR/mfa.json deleted file mode 100644 index a2a87b322..000000000 --- a/frontend/public/locales/pt-BR/mfa.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "title": "Criar uma conta", - "og-title": "Substitua os arquivos .env por 1 linha de código. Cadastre-se no Infisical em 3 minutos.", - "og-description": "Infisical é uma plataforma criptografada de ponta a ponta simples que permite que as equipes sincronizem e gerenciem chaves de API e variáveis ambientais. Funciona com Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Criar uma conta", - "already-have-account": "Possui uma conta? Conecte-se", - "forgot-password": "Esqueceu sua senha?", - "verify": "Verificar", - "step1-start": "Vamos começar", - "step1-privacy": "Ao criar uma conta, você concorda com nossos Termos e leu a Política de Privacidade.", - "step1-submit": "Começar", - "step2-message": "Enviamos um e-mail de verificação para{{email}}", - "step2-code-error": "Ops. Seu código está errado. Tentativas restantes:", - "step2-spam-alert": "Lembre-se de verificar sua caixa de entrada de spam.", - "step3-message": "Quase lá!", - "step4-message": "Guarde o seu Kit de Emergência", - "step4-description1": "Se sua conta for bloqueada, seu Kit de emergência é a única maneira de fazer login.", - "step4-description2": "Recomendamos que você faça o download e guarde-o em algum lugar seguro.", - "step4-description3": "Ele contém sua chave secreta que não podemos acessar ou recuperar para você se você a perder.", - "step4-download": "Baixar PDF", - "step5-send-invites": "Enviar convites", - "step5-invite-team": "Convide sua equipe", - "step5-subtitle": "Infisical foi feito para ser usado com seus colegas. Convide-os para eles testarem também.", - "step5-skip": "Pular" -} diff --git a/frontend/public/locales/pt-BR/nav.json b/frontend/public/locales/pt-BR/nav.json deleted file mode 100644 index 7922312dd..000000000 --- a/frontend/public/locales/pt-BR/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "[NEW] Participe do fórum do Slack", - "docs": "Leia a Documentação", - "issue": "Abra uma Issue no Github", - "email": "Envie-nos um e-mail" - }, - "user": { - "signed-in-as": "ASSINADO COMO", - "current-organization": "ORGANIZAÇÃO ATUAL", - "usage-billing": "Uso & Faturamento", - "invite": "Convide Membros", - "other-organizations": "OUTRA ORGANIZAÇÃO" - }, - "menu": { - "project": "PROJETO", - "secrets": "Segredos", - "members": "Membros", - "integrations": "Integrações", - "project-settings": "Configurações do Projeto" - } -} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/section-incident.json b/frontend/public/locales/pt-BR/section-incident.json deleted file mode 100644 index cbe902783..000000000 --- a/frontend/public/locales/pt-BR/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "incident-contacts": "Contatos de Emergência", - "incident-contacts-description": "Esses contatos serão notificados no caso improvável de um incidente grave.", - "no-incident-contacts": "Nenhum contato de emergência encontrado.", - "add-contact": "Adicionar contato", - "add-dialog": { - "title": "Adicionar um contato de emergência", - "description": "Este contato será notificado no caso improvável de um incidente grave.", - "add-incident": "Adicionar contato de emergência" - } -} diff --git a/frontend/public/locales/pt-BR/section-members.json b/frontend/public/locales/pt-BR/section-members.json deleted file mode 100644 index c8ee1d2a9..000000000 --- a/frontend/public/locales/pt-BR/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "Adicionar membro", - "org-members": "Membros da Organização", - "org-members-description": "Gerencie os membros da sua organização. Esses usuários poderiam posteriormente ser associados a projetos.", - "search-members": "Pesquisar membros...", - "add-dialog": { - "add-member-to-project": "Adicionar um membro ao seu projeto", - "already-all-invited": "Todos os usuários da sua organização já foram convidados.", - "add-user-org-first": "Adicione mais usuários à organização primeiro.", - "user-will-email": "O usuário receberá um e-mail com as instruções.", - "looking-add": "<0>Se você deseja adicionar usuários à sua organização,<1>clique aqui", - "add-user-to-org": "Adicionar usuários à organização" - } -} diff --git a/frontend/public/locales/pt-BR/section-password.json b/frontend/public/locales/pt-BR/section-password.json deleted file mode 100644 index 771581768..000000000 --- a/frontend/public/locales/pt-BR/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "Senha", - "change": "Mudar senha", - "current": "Senha atual", - "current-wrong": "A senha atual pode estar errada", - "new": "Nova Senha", - "validate-base": "A senha deve conter pelo menos:", - "validate-length": "14 caracteres", - "validate-case": "1 caractere minúsculo", - "validate-number": "1 número" -} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/section-token.json b/frontend/public/locales/pt-BR/section-token.json deleted file mode 100644 index 1713f8118..000000000 --- a/frontend/public/locales/pt-BR/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "service-tokens": "Tokens de Serviço", - "service-tokens-description": "Cada token de serviço é específico para você, um determinado projeto e um determinado ambiente dentro deste projeto.", - "add-new": "Adicionar novo token", - "add-dialog": { - "title": "Adicione um token de serviço para {{target}}", - "description": "Especifique o nome, o ambiente e o período de expiração. Quando um token é gerado, você só poderá vê-lo uma vez antes que ele desapareça. Certifique-se de salvá-lo em algum lugar.", - "name": "Nome do token de serviço", - "add": "Adicionar token de serviço", - "copy-service-token": "Copie seu token de serviço", - "copy-service-token-description": "Depois de fechar este pop-up, você nunca mais verá seu token de serviço" - } -} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/settings-members.json b/frontend/public/locales/pt-BR/settings-members.json deleted file mode 100644 index f48913547..000000000 --- a/frontend/public/locales/pt-BR/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Membros do Projeto", - "description": "Esta página mostra os membros do projeto selecionado." -} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/settings-org.json b/frontend/public/locales/pt-BR/settings-org.json deleted file mode 100644 index 458a8ac09..000000000 --- a/frontend/public/locales/pt-BR/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Configurações da organização", - "description": "Gerencie os membros da sua organização. Esses usuários poderiam posteriormente ser associados a projetos." -} diff --git a/frontend/public/locales/pt-BR/settings-personal.json b/frontend/public/locales/pt-BR/settings-personal.json deleted file mode 100644 index 9d5dd7f50..000000000 --- a/frontend/public/locales/pt-BR/settings-personal.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Configurações Pessoais", - "description": "Visualize e gerencie suas informações pessoais aqui.", - "emergency": { - "name": "Kit de emergência", - "text1": "Seu Kit de Emergência contém as informações necessárias para acessar sua conta Infisical.", - "text2": "Apenas o último kit de emergência emitido permanece válido. Para obter um novo Kit de emergência, verifique sua senha.", - "download": "Baixe o kit de emergência" - }, - "change-language": "Mudar idioma" -} \ No newline at end of file diff --git a/frontend/public/locales/pt-BR/settings-project.json b/frontend/public/locales/pt-BR/settings-project.json deleted file mode 100644 index acd88a5d0..000000000 --- a/frontend/public/locales/pt-BR/settings-project.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "title": "Configurações do Projeto", - "description": "Essas configurações se aplicam apenas ao projeto atualmente selecionado.", - "danger-zone": "Zona de perigo", - "delete-project": "Excluir projeto", - "project-to-delete": "Projeto a ser deletado", - "danger-zone-note": "Assim que você excluir este projeto, não poderá desfazê-lo. Isso removerá imediatamente todas as chaves. Se você ainda quiser fazer isso, digite o nome do projeto abaixo.", - "delete-project-note": "Observação: você só pode excluir um projeto caso tenha mais de um", - "project-id-description": "Para integrar Infisical em sua base de código e obter injeção automática de variáveis de ambiente, você deve usar o seguinte ID do projeto.", - "project-id-description2": "Para obter mais orientações, incluindo trechos de código para várias linguagens e frameworks, consulte ", - "auto-generated": "Este é o identificador exclusivo - gerado automaticamente - do seu projeto. Não pode ser alterado.", - "docs": "Documentação do Infisical", - "auto-capitalization": "Converter em caixa alta automaticamente", - "auto-capitalization-description": "Por padrão, Infisical converte automaticamente as chaves em caixa alta. Se você quiser desativar essa funcionalidade, pode fazê-lo aqui." -} diff --git a/frontend/public/locales/pt-BR/signup.json b/frontend/public/locales/pt-BR/signup.json deleted file mode 100644 index c08ffea7c..000000000 --- a/frontend/public/locales/pt-BR/signup.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "title": "Inscrever-se", - "og-title": "Substitua os arquivos .env por 1 linha de código. Cadastre-se no Infisical em 3 minutos.", - "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem chaves de API e variáveis de ambiente. Funciona com Node.js, Next.js, Gatsby, Nest.js...", - "signup": "Inscrever-se", - "already-have-account": "Possui uma conta? Conecte-se", - "forgot-password": "Esqueceu sua senha?", - "verify": "Verificar", - "step1-start": "Vamos começar", - "step1-privacy": "Ao criar uma conta, você concorda com nossos Termos e leu e reconheceu a Política de Privacidade.", - "step1-submit": "Iniciar", - "step2-message": "Enviamos um e-mail de verificação para{{email}}", - "step2-code-error": "Ops. Seu código está errado. Por favor, tente novamente.", - "step2-spam-alert": "Certifique-se de verificar sua caixa de entrada de spam.", - "step3-message": "Quase lá!", - "step4-message": "Guarde o seu Kit de Emergência", - "step4-description1": "Se sua conta for bloqueada, seu Kit de emergência é a única maneira de fazer login.", - "step4-description2": "Recomendamos que você faça o download e guarde-o em algum lugar seguro.", - "step4-description3": "Ele contém sua chave secreta que não podemos acessar ou recuperar para você se você a perder.", - "step4-download": "Baixar PDF", - "step5-send-invites": "Enviar convites", - "step5-invite-team": "Convide sua equipe", - "step5-subtitle": "Infisical foi feito para ser usado com seus colegas. Convide-os para testar também.", - "step5-skip": "Pular" -} diff --git a/frontend/public/locales/pt-BR/translations.json b/frontend/public/locales/pt-BR/translations.json new file mode 100644 index 000000000..5b53ce503 --- /dev/null +++ b/frontend/public/locales/pt-BR/translations.json @@ -0,0 +1,293 @@ +{ + "activity": { + "title": "Registro de Atividade", + "subtitle": "Histórico de eventos para esse projeto Infisical.", + "event": { + "readSecrets": "Segredos Visualizados", + "updateSecrets": "Segredos Atualizados", + "addSecrets": "Segredos Adicionados", + "deleteSecrets": "Segredos Excluídos" + }, + "ip-address": "Endereço IP" + }, + "billing": { + "title": "Uso & Faturamento", + "description": "Visualize e gerencie a assinatura da sua organização aqui", + "subscription": "Inscrição", + "starter": { + "name": "Base", + "price-explanation": "Até 5 membros de equipe", + "text": "Gerencie qualquer projeto com 5 membros gratuitamente!", + "subtext": "$5 por membro adicional / mês." + }, + "professional": { + "name": "Profissional", + "price-explanation": "/membro/mês", + "subtext": "Inclui projetos e membros ilimitados.", + "text": "Acompanhe o gerenciamento de chaves à medida que você cresce." + }, + "enterprise": { + "name": "Empreendimento", + "text": "Acompanhe o gerenciamento de chaves à medida que você cresce." + }, + "current-usage": "Uso atual", + "free": "Grátis", + "downgrade": "Reduzir", + "upgrade": "Melhorar", + "learn-more": "Saber Mais", + "custom-pricing": "Preço Personalizado", + "schedule-demo": "Agende uma Demonstração" + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "Já exite um projeto com este nome.", + "no-mobile": "Para usar o Infisical, faça o login através de um dispositivo com dimensões maiores.", + "email": "Email", + "password": "Senha", + "first-name": "Primeiro Nome", + "last-name": "Ultimo Nome", + "logout": "Sair", + "validate-required": "Por favor insira o seu {{name}}", + "maintenance-alert": "Estamos passando por pequenas dificuldades técnicas. Estamos trabalhando para resolvê-las agora. Por favor, volte dentro de alguns minutos.", + "click-to-copy": "Clique para copiar", + "project-id": "ID do Projeto", + "save-changes": "Salvar Alterações", + "saved": "Salvou", + "drop-zone": "Arraste e solte seu arquivo .env aqui.", + "drop-zone-keys": "Arraste e solte seu arquivo .env aqui para adicionar mais chaves.", + "role": "Role", + "role_admin": "admin", + "display-name": "Nome de exibição", + "environment": "Ambiente", + "expired-in": "Expira em", + "language": "Idioma", + "search": "Procurar...", + "note": "Note", + "view-more": "Ver mais", + "end-of-history": "Fim do Histórico", + "select-event": "Selecione um evento", + "event": "Evento", + "user": "Usuário", + "source": "Fonte", + "time": "Data/Hora", + "timestamp": "Timestamp" + }, + "dashboard": { + "title": "Segredos", + "og-title": "Gerencie seus arquivos .env em segundos", + "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem seus arquivos .env.", + "search-keys": "Pesquisar chaves...", + "add-key": "Adicionar Chave", + "personal": "Pessoal", + "personal-description": "As chaves pessoais são visíveis apenas para você", + "shared": "Compartilhado", + "shared-description": "As chaves compartilhadas ficam visíveis para toda a sua equipe", + "make-shared": "Tornar Compartilhado", + "make-personal": "Tornar Pessoal", + "check-docs": { + "button": "Checkar Documentação", + "title": "Bom trabalho!!", + "line1": "Parabéns por adicionar mais segredos.", + "line2": "Veja como conectá-los à sua base de código." + }, + "sidebar": { + "secret": "Segredo", + "key": "Chave", + "value": "Valor", + "override": "Substitua o valor por um valor pessoal", + "version-history": "Histórico da versão", + "comments": "Comentários e Notas", + "personal-explanation": "Este segredo é pessoal. Não é compartilhado com nenhum de seus colegas de equipe.", + "generate-random-hex": "Gerar HEX Aleatório", + "digits": "dígitos", + "delete-key-dialog": { + "title": "Excluir Chave", + "confirm-delete-message": "Você tem certeza que deseja excluir esta chave? Essa ação não pode ser desfeita." + } + } + }, + "integrations": { + "title": "Integrações de Projetos", + "description": "Gerencie suas integrações da Infisical com serviços de terceiros.", + "no-integrations1": "Você ainda não tem integrações configuradas. Quando você fizer isso, elas aparecerão aqui.", + "no-integrations2": "Para começar, clique em qualquer uma das opções abaixo. Leva 5 cliques para configurar.", + "available": "Integrações de Plataforma e em Nuvem", + "available-text1": "Clique na integração que deseja conectar. Isso permitirá que suas variáveis de ambiente fluam automaticamente para serviços de terceiros selecionados.", + "available-text2": "Observação: durante uma integração com o Heroku, por questões de segurança, é impossível manter a criptografia de ponta a ponta. Em teoria, isso permite que o Infisical descriptografe suas variáveis de ambiente. Na prática, podemos garantir que isso nunca será feito e nos permite proteger seus segredos de pessoas mal-intencionadas online. O serviço básico da Infisical sempre permanecerá criptografado de ponta a ponta. Em caso de dúvidas, entre em contato com support@infisical.com.", + "cloud-integrations": "Integrações em Nuvem", + "framework-integrations": "Integrações com framework", + "click-to-start": "Clique em uma integração para começar a sincronizar segredos com ela.", + "click-to-setup": "Clique em uma estrutura para obter as instruções de configuração.", + "grant-access-to-secrets": "Conceda acesso Infisical aos seus segredos", + "why-infisical-needs-access": "A maioria das integrações em Nuvem exige que o Infisical seja capaz de descriptografar seus segredos para que possam ser encaminhados.", + "grant-access-button": "Garantir acesso" + }, + "login": { + "title": "Entrar", + "og-title": "Entrar no Infisical", + "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem seus arquivos .env.", + "login": "Entrar", + "need-account": "Precisa de uma conta Infisical?", + "forgot-password": "Esqueceu sua senha?", + "create-account": "Criar uma conta" + }, + "mfa": { + "title": "Criar uma conta", + "og-title": "Substitua os arquivos .env por 1 linha de código. Cadastre-se no Infisical em 3 minutos.", + "og-description": "Infisical é uma plataforma criptografada de ponta a ponta simples que permite que as equipes sincronizem e gerenciem chaves de API e variáveis ambientais. Funciona com Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Criar uma conta", + "already-have-account": "Possui uma conta? Conecte-se", + "forgot-password": "Esqueceu sua senha?", + "verify": "Verificar", + "step1-start": "Vamos começar", + "step1-privacy": "Ao criar uma conta, você concorda com nossos Termos e leu a Política de Privacidade.", + "step1-submit": "Começar", + "step2-message": "Enviamos um e-mail de verificação para{{email}}", + "step2-code-error": "Ops. Seu código está errado. Tentativas restantes:", + "step2-spam-alert": "Lembre-se de verificar sua caixa de entrada de spam.", + "step3-message": "Quase lá!", + "step4-message": "Guarde o seu Kit de Emergência", + "step4-description1": "Se sua conta for bloqueada, seu Kit de emergência é a única maneira de fazer login.", + "step4-description2": "Recomendamos que você faça o download e guarde-o em algum lugar seguro.", + "step4-description3": "Ele contém sua chave secreta que não podemos acessar ou recuperar para você se você a perder.", + "step4-download": "Baixar PDF", + "step5-send-invites": "Enviar convites", + "step5-invite-team": "Convide sua equipe", + "step5-subtitle": "Infisical foi feito para ser usado com seus colegas. Convide-os para eles testarem também.", + "step5-skip": "Pular" + }, + "nav": { + "support": { + "slack": "[NEW] Participe do fórum do Slack", + "docs": "Leia a Documentação", + "issue": "Abra uma Issue no Github", + "email": "Envie-nos um e-mail" + }, + "user": { + "signed-in-as": "ASSINADO COMO", + "current-organization": "ORGANIZAÇÃO ATUAL", + "usage-billing": "Uso & Faturamento", + "invite": "Convide Membros", + "other-organizations": "OUTRA ORGANIZAÇÃO" + }, + "menu": { + "project": "PROJETO", + "secrets": "Segredos", + "members": "Membros", + "integrations": "Integrações", + "project-settings": "Configurações do Projeto" + } + }, + "section": { + "incident": { + "incident-contacts": "Contatos de Emergência", + "incident-contacts-description": "Esses contatos serão notificados no caso improvável de um incidente grave.", + "no-incident-contacts": "Nenhum contato de emergência encontrado.", + "add-contact": "Adicionar contato", + "add-dialog": { + "title": "Adicionar um contato de emergência", + "description": "Este contato será notificado no caso improvável de um incidente grave.", + "add-incident": "Adicionar contato de emergência" + } + }, + "members": { + "add-member": "Adicionar membro", + "org-members": "Membros da Organização", + "org-members-description": "Gerencie os membros da sua organização. Esses usuários poderiam posteriormente ser associados a projetos.", + "search-members": "Pesquisar membros...", + "add-dialog": { + "add-member-to-project": "Adicionar um membro ao seu projeto", + "already-all-invited": "Todos os usuários da sua organização já foram convidados.", + "add-user-org-first": "Adicione mais usuários à organização primeiro.", + "user-will-email": "O usuário receberá um e-mail com as instruções.", + "looking-add": "<0>Se você deseja adicionar usuários à sua organização,<1>clique aqui", + "add-user-to-org": "Adicionar usuários à organização" + } + }, + "password": { + "password": "Senha", + "change": "Mudar senha", + "current": "Senha atual", + "current-wrong": "A senha atual pode estar errada", + "new": "Nova Senha", + "validate-base": "A senha deve conter pelo menos:", + "validate-length": "14 caracteres", + "validate-case": "1 caractere minúsculo", + "validate-number": "1 número" + }, + "token": { + "service-tokens": "Tokens de Serviço", + "service-tokens-description": "Cada token de serviço é específico para você, um determinado projeto e um determinado ambiente dentro deste projeto.", + "add-new": "Adicionar novo token", + "add-dialog": { + "title": "Adicione um token de serviço para {{target}}", + "description": "Especifique o nome, o ambiente e o período de expiração. Quando um token é gerado, você só poderá vê-lo uma vez antes que ele desapareça. Certifique-se de salvá-lo em algum lugar.", + "name": "Nome do token de serviço", + "add": "Adicionar token de serviço", + "copy-service-token": "Copie seu token de serviço", + "copy-service-token-description": "Depois de fechar este pop-up, você nunca mais verá seu token de serviço" + } + } + }, + "settings": { + "members": { + "title": "Membros do Projeto", + "description": "Esta página mostra os membros do projeto selecionado." + }, + "org": { + "title": "Configurações da organização", + "description": "Gerencie os membros da sua organização. Esses usuários poderiam posteriormente ser associados a projetos." + }, + "personal": { + "title": "Configurações Pessoais", + "description": "Visualize e gerencie suas informações pessoais aqui.", + "emergency": { + "name": "Kit de emergência", + "text1": "Seu Kit de Emergência contém as informações necessárias para acessar sua conta Infisical.", + "text2": "Apenas o último kit de emergência emitido permanece válido. Para obter um novo Kit de emergência, verifique sua senha.", + "download": "Baixe o kit de emergência" + }, + "change-language": "Mudar idioma" + }, + "project": { + "title": "Configurações do Projeto", + "description": "Essas configurações se aplicam apenas ao projeto atualmente selecionado.", + "danger-zone": "Zona de perigo", + "delete-project": "Excluir projeto", + "project-to-delete": "Projeto a ser deletado", + "danger-zone-note": "Assim que você excluir este projeto, não poderá desfazê-lo. Isso removerá imediatamente todas as chaves. Se você ainda quiser fazer isso, digite o nome do projeto abaixo.", + "delete-project-note": "Observação: você só pode excluir um projeto caso tenha mais de um", + "project-id-description": "Para integrar Infisical em sua base de código e obter injeção automática de variáveis de ambiente, você deve usar o seguinte ID do projeto.", + "project-id-description2": "Para obter mais orientações, incluindo trechos de código para várias linguagens e frameworks, consulte ", + "auto-generated": "Este é o identificador exclusivo - gerado automaticamente - do seu projeto. Não pode ser alterado.", + "docs": "Documentação do Infisical", + "auto-capitalization": "Converter em caixa alta automaticamente", + "auto-capitalization-description": "Por padrão, Infisical converte automaticamente as chaves em caixa alta. Se você quiser desativar essa funcionalidade, pode fazê-lo aqui." + } + }, + "signup": { + "title": "Inscrever-se", + "og-title": "Substitua os arquivos .env por 1 linha de código. Cadastre-se no Infisical em 3 minutos.", + "og-description": "Infisical é uma plataforma simples e criptografada de ponta a ponta que permite que as equipes sincronizem e gerenciem chaves de API e variáveis de ambiente. Funciona com Node.js, Next.js, Gatsby, Nest.js...", + "signup": "Inscrever-se", + "already-have-account": "Possui uma conta? Conecte-se", + "forgot-password": "Esqueceu sua senha?", + "verify": "Verificar", + "step1-start": "Vamos começar", + "step1-privacy": "Ao criar uma conta, você concorda com nossos Termos e leu e reconheceu a Política de Privacidade.", + "step1-submit": "Iniciar", + "step2-message": "Enviamos um e-mail de verificação para{{email}}", + "step2-code-error": "Ops. Seu código está errado. Por favor, tente novamente.", + "step2-spam-alert": "Certifique-se de verificar sua caixa de entrada de spam.", + "step3-message": "Quase lá!", + "step4-message": "Guarde o seu Kit de Emergência", + "step4-description1": "Se sua conta for bloqueada, seu Kit de emergência é a única maneira de fazer login.", + "step4-description2": "Recomendamos que você faça o download e guarde-o em algum lugar seguro.", + "step4-description3": "Ele contém sua chave secreta que não podemos acessar ou recuperar para você se você a perder.", + "step4-download": "Baixar PDF", + "step5-send-invites": "Enviar convites", + "step5-invite-team": "Convide sua equipe", + "step5-subtitle": "Infisical foi feito para ser usado com seus colegas. Convide-os para testar também.", + "step5-skip": "Pular" + } +} \ No newline at end of file diff --git a/frontend/public/locales/tr/activity.json b/frontend/public/locales/tr/activity.json deleted file mode 100644 index 80ac8f90d..000000000 --- a/frontend/public/locales/tr/activity.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "title": "Aktivite Günlükleri", - "subtitle": "Bu Infisical projesi için Olay Geçmişi.", - "event": { - "readSecrets": "Sırlar Görüntülendi", - "updateSecrets": "Sırlar Güncellendi", - "addSecrets": "Sırlar Eklendi", - "deleteSecrets": "Sırlar Silindi" - }, - "ip-address": "IP Addresi" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/billing.json b/frontend/public/locales/tr/billing.json deleted file mode 100644 index d27ddc976..000000000 --- a/frontend/public/locales/tr/billing.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Planlar & Fiyatlandırma", - "description": "Kuruluşunuzun aboneliğini buradan görüntüleyin ve yönetin", - "subscription": "Abonelik", - "starter": { - "name": "Başlangıç", - "price-explanation": "5 takım üyesine kadar", - "text": "5 kişiyle herhangi bir projeyi ücretsiz yönet!", - "subtext": "Sonrasında aylık her üye başına 5$." - }, - "professional": { - "name": "Profesyonel", - "price-explanation": "/üye/ay", - "subtext": "Sınırsız miktarda üye ve proje dahildir.", - "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun.." - }, - "enterprise": { - "name": "Kurumsal", - "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun." - }, - "current-usage": "Mevcut Plan", - "free": "Ücretsiz", - "downgrade": "Düşürün", - "upgrade": "Yükseltin", - "learn-more": "Daha fazlasını öğrenim", - "custom-pricing": "Özel Fiyatlandırma", - "schedule-demo": "Bir Deneme Sürümü Planlayın " -} \ No newline at end of file diff --git a/frontend/public/locales/tr/common.json b/frontend/public/locales/tr/common.json deleted file mode 100644 index 38d54b476..000000000 --- a/frontend/public/locales/tr/common.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "head-title": "{{title}} | Infisical", - "error_project-already-exists": "Bu isimle bir proje zaten mevcut.", - "no-mobile": " Infisical'ı kullanmak için, lütfen daha büyük boyutlara sahip bir cihaz üzerinden giriş yapın. ", - "email": "Email", - "password": "Şifre", - "first-name": "Adınız", - "last-name": "Soyadınız", - "logout": "Çıkış Yap", - "validate-required": "Lütfen girin, sahip olduğunuz {{name}}", - "maintenance-alert": "Ufak teknik problemler yaşıyoruz. Sorunu çözmek üzere çalışıyoruz. Lütfen birkaç dakika içerisinde yeniden deneyin.", - "click-to-copy": "Kopyala", - "project-id": "Project ID", - "save-changes": "Değişiklikleri Kaydet", - "saved": "Kaydedildi", - "drop-zone": ".env yada .yaml dosyasını buraya sürükleyin", - "drop-zone-keys": "Daha çok anahatar eklemek için bir .env yada .yaml dosyasını sürükleyin.", - "role": "Rol", - "role_admin": "yönetici", - "display-name": "Ekran Adı", - "environment": "Environment", - "expired-in": "Süresi geçicek", - "language": "Dil", - "search": "Ara...", - "note": "Not", - "view-more": "Daha Fazla Göster", - "end-of-history": "Geçmişin Sonu", - "select-event": "Bir olay seçin", - "event": "Olay", - "user": "Kullanıcı", - "source": "Kaynak", - "time": "Zaman", - "timestamp": "Zaman Damgası" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/dashboard.json b/frontend/public/locales/tr/dashboard.json deleted file mode 100644 index c480ba18b..000000000 --- a/frontend/public/locales/tr/dashboard.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "title": "Sırlar", - "og-title": "Saniyeler içerisinde .env dosyalarınızı yönetin", - "og-description": "Infisical takımların .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", - "search-keys": "Anahtarları ara...", - "add-key": "Anahtar Ekle", - "personal": "Kişisel", - "personal-description": "Kişisel anahtarlar sadece sana görünür", - "shared": "Paylaşılan", - "shared-description": "Paylaşılan anahatarlar tüm takımına görünür", - "make-shared": "Paylaşılan Yap", - "make-personal": "Kişisel Yap", - "add-secret": "Yeni bir sır ekle", - "check-docs": { - "button": "Dokümanları Kontrol Et", - "title": "İyi iş!", - "line1": "Tebrikler, yeni anahtarlar eklediniz.", - "line2": "Bunları kendi Codebase' inize nasıl bağlarsınız, işte böyle." - }, - "sidebar": { - "secret": "Sır", - "key": "Anahtar", - "value": "Değer", - "override": "Bu değerin üzerine bir kişisel değer yazın ", - "version-history": "Versiyon Geçmişi", - "comments": "Yorumlar & Notlar", - "personal-explanation": "Bu bir kişisel sır. Herhangi bir takım üyesi ile paylaşılmaz.", - "generate-random-hex": "Rastegele hex oluştur", - "digits": "basamak", - "delete-key-dialog": { - "title": "Anahtarı Sil", - "confirm-delete-message": "Bu sırrı silmek istediğinden emin misin? Bu işlem geri alınamaz." - } - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/integrations.json b/frontend/public/locales/tr/integrations.json deleted file mode 100644 index b8fe599f4..000000000 --- a/frontend/public/locales/tr/integrations.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Proje Entegrasyonları", - "description": "Infisical'ın üçüncü taraf hizmetlerle olan entegrasyonlarınızı yönetin.", - "no-integrations1": "Henüz ayarlanmış bir entegrasyonunuz yok. Oluşturduğunuz zaman, burada görünecekler.", - "no-integrations2": "Başlamak için aşağıdaki seçeneklerden herhangi birine tıklayın. Sadece 5 tıklama ile kurulumu halledin.", - "available": "Platform & Cloud Entegrasyonları", - "available-text1": "Bağlanmak istediğiniz entegrasyona tıklayın. Bu, ortam değişkenlerinizin seçilen üçüncü taraf hizmetlere otomatik olarak akmasını sağlar.", - "available-text2": "Not: Heroku ile entegrasyon sırasında güvenlik nedenleriyle uçtan uca şifrelemenin sürdürülmesi mümkün değildir. Teorik olarak bu, Infisical'ın ortam değişkenlerinin şifresini çözmesine izin verir. Pratikte biz bunun asla yapılmayacağının garantisini verebiliriz ve bu durum sırlarınızı çevrimiçi kötü niyetlilerden korumamıza olanak tanır. Çekirdek Infisical hizmeti her zaman uçtan uca şifreli kalacaktır. Sorularınız için support@infisical.com adresine ulaşın.", - "cloud-integrations": "Cloud Entegrasyonları", - "framework-integrations": "Framework Entegrasyonları", - "click-to-start": "Sırlarınızı senkronize etmeye başlamak için bir entegrasyona tıklayın.", - "click-to-setup": "Kurulum talimatlarını almak için bir frameworke tıklayın.", - "grant-access-to-secrets": "Infisical'a sırlarınıza erişim izni verin", - "why-infisical-needs-access": "Çoğu cloud entegrasyonu, Infisical'ın sırlarınızı aktarabilmek için sırlarınızı deşifre etmesini gerektirir.", - "grant-access-button": "Erişim izni ver" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/login.json b/frontend/public/locales/tr/login.json deleted file mode 100644 index f42551188..000000000 --- a/frontend/public/locales/tr/login.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "title": "Giriş Yap", - "og-title": "Infisical'a Giriş Yap", - "og-description": "Infisical ekiplerin .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", - "login": "Giriş Yap", - "need-account": "Bir Infisical hesabına mı ihtiyacınız var?", - "create-account": "Hesap oluşturun", - "forgot-password": "Şifrenizi mi unuttunuz?", - "error-login": "Kimlik bilgileri yanlış." -} \ No newline at end of file diff --git a/frontend/public/locales/tr/mfa.json b/frontend/public/locales/tr/mfa.json deleted file mode 100644 index fe4eb1654..000000000 --- a/frontend/public/locales/tr/mfa.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Kayıt olun", - "og-title": "Tek satır kodla .env dosyalarını değiştirin. 3 dakika içerinde Infisical'a kayıt olun.", - "og-description": "Infisical takımların API anahtarlarını ve ortam değişkenlerini yönetmelerini ve senkronize etmelerini sağlayan basit, uçtan uca şifrelenmiş bir platformdur. Node.js, Next.js, Gatsby, Nest.js ve daha fazlası ile çalışır.", - "signup": "Kayıt ol", - "already-have-account": "Hesabın var mı? Giriş yap", - "forgot-password": "Şifreni mi unuttun?", - "verify": "Doğrula", - "step1-start": "Hadi başlayalım", - "step1-privacy": "Hesap oluşturarak, Şartlarımızı ve Gizlilik Politikasını okuyup kabul etmiş olursunuz.", - "step1-submit": "Başla", - "step2-message": "Şu adrese bir doğrulama maili yolladık", - "step2-code-error": "Tüh. Kodun hatalı. Kalan denemeler:", - "step2-resend-alert": "Kodu ulaşamadı mı?", - "step2-resend-submit": "Tekrar Yolla", - "step2-resend-progress": "Tekrar yollanıyor...", - "step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.", - "step3-message": "Çok az kaldı!", - "step4-message": "Acil Durum Kitinizi kayıt edin", - "step4-description1": "Eğer hesabınıza erişemezseniz, Acil Durum Kitiniz giriş yapmanın tek yoludur.", - "step4-description2": "Bunu indirmenizi ve güvenli bir ortamda saklamanızı öneriyoruz.", - "step4-description3": "Kaybetmeniz durumunda bizim dahi erişemeyeceğimiz veya kurtaramayacağımız Gizli Anahtarınızı barındırır.", - "step4-download": "PDF'yi indir", - "step5-send-invites": "Davetleri yolla", - "step5-invite-team": "Takımını davet et", - "step5-subtitle": "Infisical takım arkadaşlarınız ile kullanılmak üzere yapılmıştır. Birlikte test etmek için onları davet edin.", - "step5-skip": "Atla" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/nav.json b/frontend/public/locales/tr/nav.json deleted file mode 100644 index aa6ea2df4..000000000 --- a/frontend/public/locales/tr/nav.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "support": { - "slack": "[YENİ] Slack Foruma katılın", - "docs": "Dokümanları okuyun", - "issue": "Bir Github Issue açın", - "email": "Bize mail yollayın" - }, - "user": { - "signed-in-as": "ŞU HESABA GİRİŞ YAPILDI", - "current-organization": "MEVZUT ORGANİZASYON", - "usage-billing": "Plan & Fiyatlandırma", - "invite": "Üyeleri Davet Et", - "other-organizations": "DİĞER ORGANİZASYONLAR" - }, - "menu": { - "project": "PROJE", - "secrets": "Sırlar", - "members": "Üyeler", - "integrations": "Entegrasyonlar", - "project-settings": "Proje Ayarları" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-api-key.json b/frontend/public/locales/tr/section-api-key.json deleted file mode 100644 index 0c768ded6..000000000 --- a/frontend/public/locales/tr/section-api-key.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "api-keys": "Servis Belirteçleri", - "api-keys-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", - "add-new": "Yeni Belirteç Ekleyin", - "add-dialog": { - "title": "Bir API Anahtarı Ekleyin", - "description": "Adını ve son kullanma süresini belirleyin. Bir API anahtarı oluşturulduğunda, kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", - "name": "API Anahtarı Adı", - "add": "API Anahtarı Ekleyin", - "copy-service-token": "API Anahtarızı kopyalayın", - "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, API anahtarınızı bir daha asla görmeyeceksiniz" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-incident.json b/frontend/public/locales/tr/section-incident.json deleted file mode 100644 index 776c71c63..000000000 --- a/frontend/public/locales/tr/section-incident.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "incident-contacts": "Özel Durum İletişim Adresleri", - "incident-contacts-description": "Bu adresler olası olmayan ciddi bir olay durumunda bilgilendirilecek.", - "no-incident-contacts": "Hiçbir Özel Durum İletişim Adresi bulunamadı.", - "add-contact": "İletişim Adresi Ekle", - "add-dialog": { - "title": "Bir Özel Durum İletişim Adresi Ekleyin", - "description": "Bu kişi, olası olmayan ciddi bir olay durumunda bilgilendirilecektir..", - "add-incident": "Özel Durum İletişim Adresi Ekle" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-members.json b/frontend/public/locales/tr/section-members.json deleted file mode 100644 index b4a0c0ec7..000000000 --- a/frontend/public/locales/tr/section-members.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "add-member": "Üye Ekle", - "org-members": "Kuruluş Üyeleri", - "org-members-description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir..", - "search-members": "Üyeleri arayın...", - "add-dialog": { - "add-member-to-project": "Projenize bir üye ekleyin", - "already-all-invited": "Kuruluşunuzdaki tüm kullanıcılar zaten davet edildi.", - "add-user-org-first": "Önce kuruluşa daha fazla kullanıcı ekleyin.", - "user-will-email": "Kullanıcı, talimatları içeren bir e-posta alacak.", - "looking-add": "<0>Kuruluşunuza kullanıcı eklemek istiyorsanız,<1>buraya tıklayın", - "add-user-to-org": "Kuruluşa Kullanıcı Ekleyin" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-password.json b/frontend/public/locales/tr/section-password.json deleted file mode 100644 index 07e26ba58..000000000 --- a/frontend/public/locales/tr/section-password.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "password": "Şifre", - "change": "Şifreyi değiştir", - "current": "Mevcut şifre", - "current-wrong": "Mevcut şifre yanlış olabilir", - "new": "Yeni şifre", - "validate-base": "Şifre en az şunları içermelidir:", - "validate-length": "14 karakter", - "validate-case": "1 küçük harf", - "validate-number": "1 rakam" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/section-token.json b/frontend/public/locales/tr/section-token.json deleted file mode 100644 index aceaba6dd..000000000 --- a/frontend/public/locales/tr/section-token.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "service-tokens": "Servis Belirteçleri", - "service-tokens-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", - "add-new": "Yeni Belirteç Ekle", - "add-dialog": { - "title": "{{target}} için bir servis belirteci ekleyin", - "description": "Adı, ortamı ve son kullanma süresini belirtin. Bir belirteç oluşturulduğunda, onu kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", - "name": "Servis Belirteci Adı", - "add": "Servis Belirteci Ekle", - "copy-service-token": "Service belirtecinizi kopyalayın", - "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, servis belirtecinizi bir daha asla göremeyeceksiniz" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-members.json b/frontend/public/locales/tr/settings-members.json deleted file mode 100644 index c4a7441b7..000000000 --- a/frontend/public/locales/tr/settings-members.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Proje Üyeleri", - "description": "Bu sayfa seçilen projenin üyelerini gösterir." -} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-org.json b/frontend/public/locales/tr/settings-org.json deleted file mode 100644 index 3cc5c0d82..000000000 --- a/frontend/public/locales/tr/settings-org.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "title": "Kuruluş Ayarları", - "description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir.." -} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-personal.json b/frontend/public/locales/tr/settings-personal.json deleted file mode 100644 index 31c858efb..000000000 --- a/frontend/public/locales/tr/settings-personal.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "title": "Kişisel Ayarlar", - "description": "Kişisel bilgilerinizi burada görüntüleyin ve yönetin.", - "emergency": { - "name": "Acil Durum Kiti", - "text1": "Acil Durum Kitiniz, Infisical hesabınızda oturum açmak için ihtiyaç duyacağınız bilgileri içerir.", - "text2": "Yalnızca en son yayınlanan Acil Durum Kiti geçerliliğini korur. Yeni bir Acil Durum Kiti almak için parolanızı doğrulayın.", - "download": "Acil Durum Kitini İndir" - }, - "change-language": "Dili Değiştir", - "api-keys": { - "title": "API Anahtarları", - "description": "Infisical API'ye erişmek için kişisel API Anahtarlarınızı yönetin", - "add-new": "Ekle yeni" - } -} \ No newline at end of file diff --git a/frontend/public/locales/tr/settings-project.json b/frontend/public/locales/tr/settings-project.json deleted file mode 100644 index 41f9f3001..000000000 --- a/frontend/public/locales/tr/settings-project.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "title": "Proje Ayarları", - "description": "Bu ayarlar yalnızca mevcut seçili projeye uygulanacak.", - "danger-zone": "Tehlikeli Bölge", - "delete-project": "Projeyi Sil", - "project-to-delete": "Silinmek Üzere Olan Proje", - "danger-zone-note": "Bu projeyi sildiğiniz anda geri alamayacaksınız. Bu, tüm anahtarları hemen kaldıracaktır. Bunu hala yapmak istiyorsanız, lütfen aşağıya projenin adını girin.", - "delete-project-note": "Not: Yalnızca birden fazla projeniz olması durumunda, bir projeyi silebilirsiniz.", - "project-id-description": "Infisical'ı kod tabanınıza entegre etmek ve çevresel değişkenlerin otomatik enjeksiyonunu almak için aşağıdaki Proje Kimliğini kullanmalısınız.", - "project-id-description2": "Çeşitli diller ve çerçeveler için kod parçaları da dahil olmak üzere daha fazla rehberlik için bkz.", - "auto-generated": "Bu, projenizin otomatik olarak oluşturulan benzersiz tanımlayıcısıdır. Değiştirilemez..", - "docs": "Infisical Dokümanları" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/signup.json b/frontend/public/locales/tr/signup.json deleted file mode 100644 index 663b6b72b..000000000 --- a/frontend/public/locales/tr/signup.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "title": "Kayıt olun", - "og-title": "Tek satır kodla .env dosyalarını değiştirin. 3 dakika içerinde Infisical'a kayıt olun.", - "og-description": "Infisical takımların API anahtarlarını ve ortam değişkenlerini yönetmelerini ve senkronize etmelerini sağlayan basit, uçtan uca şifrelenmiş bir platformdur. Node.js, Next.js, Gatsby, Nest.js ve daha fazlası ile çalışır.", - "signup": "Kayıt ol", - "already-have-account": "Hesabın var mı? Giriş yap", - "forgot-password": "Şifreni mi unuttun?", - "verify": "Doğrula", - "step1-start": "Hadi başlayalım", - "step1-privacy": "Hesap oluşturarak, Şartlarımızı ve Gizlilik Politikasını okuyup kabul etmiş olursunuz.", - "step1-submit": "Başla", - "step2-message": "Şu adrese bir doğrulama maili yolladık", - "step2-code-error": "Tüh. Kodun hatalı. Lütfen tekrar dene.", - "step2-resend-alert": "Kodu ulaşamadı mı?", - "step2-resend-submit": "Tekrar Yolla", - "step2-resend-progress": "Tekrar yollanıyor...", - "step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.", - "step3-message": "Çok az kaldı!", - "step4-message": "Acil Durum Kitinizi kayıt edin", - "step4-description1": "Eğer hesabınıza erişemezseniz, Acil Durum Kitiniz giriş yapmanın tek yoludur.", - "step4-description2": "Bunu indirmenizi ve güvenli bir ortamda saklamanızı öneriyoruz.", - "step4-description3": "Kaybetmeniz durumunda bizim dahi erişemeyeceğimiz veya kurtaramayacağımız Gizli Anahtarınızı barındırır.", - "step4-download": "PDF'yi indir", - "step5-send-invites": "Davetleri yolla", - "step5-invite-team": "Takımını davet et", - "step5-subtitle": "Infisical takım arkadaşlarınız ile kullanılmak üzere yapılmıştır. Birlikte test etmek için onları davet edin.", - "step5-skip": "Atla" -} \ No newline at end of file diff --git a/frontend/public/locales/tr/translations.json b/frontend/public/locales/tr/translations.json new file mode 100644 index 000000000..706998495 --- /dev/null +++ b/frontend/public/locales/tr/translations.json @@ -0,0 +1,317 @@ +{ + "activity": { + "title": "Aktivite Günlükleri", + "subtitle": "Bu Infisical projesi için Olay Geçmişi.", + "event": { + "readSecrets": "Sırlar Görüntülendi", + "updateSecrets": "Sırlar Güncellendi", + "addSecrets": "Sırlar Eklendi", + "deleteSecrets": "Sırlar Silindi" + }, + "ip-address": "IP Addresi" + }, + "billing": { + "title": "Planlar & Fiyatlandırma", + "description": "Kuruluşunuzun aboneliğini buradan görüntüleyin ve yönetin", + "subscription": "Abonelik", + "starter": { + "name": "Başlangıç", + "price-explanation": "5 takım üyesine kadar", + "text": "5 kişiyle herhangi bir projeyi ücretsiz yönet!", + "subtext": "Sonrasında aylık her üye başına 5$." + }, + "professional": { + "name": "Profesyonel", + "price-explanation": "/üye/ay", + "subtext": "Sınırsız miktarda üye ve proje dahildir.", + "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun.." + }, + "enterprise": { + "name": "Kurumsal", + "text": "Anahtar yönetimine siz büyüdükçe ayak uydurun." + }, + "current-usage": "Mevcut Plan", + "free": "Ücretsiz", + "downgrade": "Düşürün", + "upgrade": "Yükseltin", + "learn-more": "Daha fazlasını öğrenim", + "custom-pricing": "Özel Fiyatlandırma", + "schedule-demo": "Bir Deneme Sürümü Planlayın " + }, + "common": { + "head-title": "{{title}} | Infisical", + "error_project-already-exists": "Bu isimle bir proje zaten mevcut.", + "no-mobile": " Infisical'ı kullanmak için, lütfen daha büyük boyutlara sahip bir cihaz üzerinden giriş yapın. ", + "email": "Email", + "password": "Şifre", + "first-name": "Adınız", + "last-name": "Soyadınız", + "logout": "Çıkış Yap", + "validate-required": "Lütfen girin, sahip olduğunuz {{name}}", + "maintenance-alert": "Ufak teknik problemler yaşıyoruz. Sorunu çözmek üzere çalışıyoruz. Lütfen birkaç dakika içerisinde yeniden deneyin.", + "click-to-copy": "Kopyala", + "project-id": "Project ID", + "save-changes": "Değişiklikleri Kaydet", + "saved": "Kaydedildi", + "drop-zone": ".env yada .yaml dosyasını buraya sürükleyin", + "drop-zone-keys": "Daha çok anahatar eklemek için bir .env yada .yaml dosyasını sürükleyin.", + "role": "Rol", + "role_admin": "yönetici", + "display-name": "Ekran Adı", + "environment": "Environment", + "expired-in": "Süresi geçicek", + "language": "Dil", + "search": "Ara...", + "note": "Not", + "view-more": "Daha Fazla Göster", + "end-of-history": "Geçmişin Sonu", + "select-event": "Bir olay seçin", + "event": "Olay", + "user": "Kullanıcı", + "source": "Kaynak", + "time": "Zaman", + "timestamp": "Zaman Damgası" + }, + "dashboard": { + "title": "Sırlar", + "og-title": "Saniyeler içerisinde .env dosyalarınızı yönetin", + "og-description": "Infisical takımların .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", + "search-keys": "Anahtarları ara...", + "add-key": "Anahtar Ekle", + "personal": "Kişisel", + "personal-description": "Kişisel anahtarlar sadece sana görünür", + "shared": "Paylaşılan", + "shared-description": "Paylaşılan anahatarlar tüm takımına görünür", + "make-shared": "Paylaşılan Yap", + "make-personal": "Kişisel Yap", + "add-secret": "Yeni bir sır ekle", + "check-docs": { + "button": "Dokümanları Kontrol Et", + "title": "İyi iş!", + "line1": "Tebrikler, yeni anahtarlar eklediniz.", + "line2": "Bunları kendi Codebase' inize nasıl bağlarsınız, işte böyle." + }, + "sidebar": { + "secret": "Sır", + "key": "Anahtar", + "value": "Değer", + "override": "Bu değerin üzerine bir kişisel değer yazın ", + "version-history": "Versiyon Geçmişi", + "comments": "Yorumlar & Notlar", + "personal-explanation": "Bu bir kişisel sır. Herhangi bir takım üyesi ile paylaşılmaz.", + "generate-random-hex": "Rastegele hex oluştur", + "digits": "basamak", + "delete-key-dialog": { + "title": "Anahtarı Sil", + "confirm-delete-message": "Bu sırrı silmek istediğinden emin misin? Bu işlem geri alınamaz." + } + } + }, + "integrations": { + "title": "Proje Entegrasyonları", + "description": "Infisical'ın üçüncü taraf hizmetlerle olan entegrasyonlarınızı yönetin.", + "no-integrations1": "Henüz ayarlanmış bir entegrasyonunuz yok. Oluşturduğunuz zaman, burada görünecekler.", + "no-integrations2": "Başlamak için aşağıdaki seçeneklerden herhangi birine tıklayın. Sadece 5 tıklama ile kurulumu halledin.", + "available": "Platform & Cloud Entegrasyonları", + "available-text1": "Bağlanmak istediğiniz entegrasyona tıklayın. Bu, ortam değişkenlerinizin seçilen üçüncü taraf hizmetlere otomatik olarak akmasını sağlar.", + "available-text2": "Not: Heroku ile entegrasyon sırasında güvenlik nedenleriyle uçtan uca şifrelemenin sürdürülmesi mümkün değildir. Teorik olarak bu, Infisical'ın ortam değişkenlerinin şifresini çözmesine izin verir. Pratikte biz bunun asla yapılmayacağının garantisini verebiliriz ve bu durum sırlarınızı çevrimiçi kötü niyetlilerden korumamıza olanak tanır. Çekirdek Infisical hizmeti her zaman uçtan uca şifreli kalacaktır. Sorularınız için support@infisical.com adresine ulaşın.", + "cloud-integrations": "Cloud Entegrasyonları", + "framework-integrations": "Framework Entegrasyonları", + "click-to-start": "Sırlarınızı senkronize etmeye başlamak için bir entegrasyona tıklayın.", + "click-to-setup": "Kurulum talimatlarını almak için bir frameworke tıklayın.", + "grant-access-to-secrets": "Infisical'a sırlarınıza erişim izni verin", + "why-infisical-needs-access": "Çoğu cloud entegrasyonu, Infisical'ın sırlarınızı aktarabilmek için sırlarınızı deşifre etmesini gerektirir.", + "grant-access-button": "Erişim izni ver" + }, + "login": { + "title": "Giriş Yap", + "og-title": "Infisical'a Giriş Yap", + "og-description": "Infisical ekiplerin .env dosyalarını senkronize etmelerini ve yönetmelerini sağlayan uçtan uca şifrelenmiş basit bir platformdur", + "login": "Giriş Yap", + "need-account": "Bir Infisical hesabına mı ihtiyacınız var?", + "create-account": "Hesap oluşturun", + "forgot-password": "Şifrenizi mi unuttunuz?", + "error-login": "Kimlik bilgileri yanlış." + }, + "mfa": { + "title": "Kayıt olun", + "og-title": "Tek satır kodla .env dosyalarını değiştirin. 3 dakika içerinde Infisical'a kayıt olun.", + "og-description": "Infisical takımların API anahtarlarını ve ortam değişkenlerini yönetmelerini ve senkronize etmelerini sağlayan basit, uçtan uca şifrelenmiş bir platformdur. Node.js, Next.js, Gatsby, Nest.js ve daha fazlası ile çalışır.", + "signup": "Kayıt ol", + "already-have-account": "Hesabın var mı? Giriş yap", + "forgot-password": "Şifreni mi unuttun?", + "verify": "Doğrula", + "step1-start": "Hadi başlayalım", + "step1-privacy": "Hesap oluşturarak, Şartlarımızı ve Gizlilik Politikasını okuyup kabul etmiş olursunuz.", + "step1-submit": "Başla", + "step2-message": "Şu adrese bir doğrulama maili yolladık", + "step2-code-error": "Tüh. Kodun hatalı. Kalan denemeler:", + "step2-resend-alert": "Kodu ulaşamadı mı?", + "step2-resend-submit": "Tekrar Yolla", + "step2-resend-progress": "Tekrar yollanıyor...", + "step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.", + "step3-message": "Çok az kaldı!", + "step4-message": "Acil Durum Kitinizi kayıt edin", + "step4-description1": "Eğer hesabınıza erişemezseniz, Acil Durum Kitiniz giriş yapmanın tek yoludur.", + "step4-description2": "Bunu indirmenizi ve güvenli bir ortamda saklamanızı öneriyoruz.", + "step4-description3": "Kaybetmeniz durumunda bizim dahi erişemeyeceğimiz veya kurtaramayacağımız Gizli Anahtarınızı barındırır.", + "step4-download": "PDF'yi indir", + "step5-send-invites": "Davetleri yolla", + "step5-invite-team": "Takımını davet et", + "step5-subtitle": "Infisical takım arkadaşlarınız ile kullanılmak üzere yapılmıştır. Birlikte test etmek için onları davet edin.", + "step5-skip": "Atla" + }, + "nav": { + "support": { + "slack": "[YENİ] Slack Foruma katılın", + "docs": "Dokümanları okuyun", + "issue": "Bir Github Issue açın", + "email": "Bize mail yollayın" + }, + "user": { + "signed-in-as": "ŞU HESABA GİRİŞ YAPILDI", + "current-organization": "MEVZUT ORGANİZASYON", + "usage-billing": "Plan & Fiyatlandırma", + "invite": "Üyeleri Davet Et", + "other-organizations": "DİĞER ORGANİZASYONLAR" + }, + "menu": { + "project": "PROJE", + "secrets": "Sırlar", + "members": "Üyeler", + "integrations": "Entegrasyonlar", + "project-settings": "Proje Ayarları" + } + }, + "section": { + "api-key": { + "api-keys": "Servis Belirteçleri", + "api-keys-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", + "add-new": "Yeni Belirteç Ekleyin", + "add-dialog": { + "title": "Bir API Anahtarı Ekleyin", + "description": "Adını ve son kullanma süresini belirleyin. Bir API anahtarı oluşturulduğunda, kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", + "name": "API Anahtarı Adı", + "add": "API Anahtarı Ekleyin", + "copy-service-token": "API Anahtarızı kopyalayın", + "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, API anahtarınızı bir daha asla görmeyeceksiniz" + } + }, + "incident": { + "incident-contacts": "Özel Durum İletişim Adresleri", + "incident-contacts-description": "Bu adresler olası olmayan ciddi bir olay durumunda bilgilendirilecek.", + "no-incident-contacts": "Hiçbir Özel Durum İletişim Adresi bulunamadı.", + "add-contact": "İletişim Adresi Ekle", + "add-dialog": { + "title": "Bir Özel Durum İletişim Adresi Ekleyin", + "description": "Bu kişi, olası olmayan ciddi bir olay durumunda bilgilendirilecektir..", + "add-incident": "Özel Durum İletişim Adresi Ekle" + } + }, + "members": { + "add-member": "Üye Ekle", + "org-members": "Kuruluş Üyeleri", + "org-members-description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir..", + "search-members": "Üyeleri arayın...", + "add-dialog": { + "add-member-to-project": "Projenize bir üye ekleyin", + "already-all-invited": "Kuruluşunuzdaki tüm kullanıcılar zaten davet edildi.", + "add-user-org-first": "Önce kuruluşa daha fazla kullanıcı ekleyin.", + "user-will-email": "Kullanıcı, talimatları içeren bir e-posta alacak.", + "looking-add": "<0>Kuruluşunuza kullanıcı eklemek istiyorsanız,<1>buraya tıklayın", + "add-user-to-org": "Kuruluşa Kullanıcı Ekleyin" + } + }, + "password": { + "password": "Şifre", + "change": "Şifreyi değiştir", + "current": "Mevcut şifre", + "current-wrong": "Mevcut şifre yanlış olabilir", + "new": "Yeni şifre", + "validate-base": "Şifre en az şunları içermelidir:", + "validate-length": "14 karakter", + "validate-case": "1 küçük harf", + "validate-number": "1 rakam" + }, + "token": { + "service-tokens": "Servis Belirteçleri", + "service-tokens-description": "Her servis belirteci size, belirli bir projeye ve o proje içindeki belirli bir ortama özeldir.", + "add-new": "Yeni Belirteç Ekle", + "add-dialog": { + "title": "{{target}} için bir servis belirteci ekleyin", + "description": "Adı, ortamı ve son kullanma süresini belirtin. Bir belirteç oluşturulduğunda, onu kaybolmadan önce yalnızca bir kez görebileceksiniz. Bir yere kaydettiğinizden emin olun.", + "name": "Servis Belirteci Adı", + "add": "Servis Belirteci Ekle", + "copy-service-token": "Service belirtecinizi kopyalayın", + "copy-service-token-description": "Bu açılır pencereyi kapattığınızda, servis belirtecinizi bir daha asla göremeyeceksiniz" + } + } + }, + "settings": { + "members": { + "title": "Proje Üyeleri", + "description": "Bu sayfa seçilen projenin üyelerini gösterir." + }, + "org": { + "title": "Kuruluş Ayarları", + "description": "Kuruluşunuzun üyelerini yönetin. Bu kullanıcılar daha sonra projelere yönlendirilebilir.." + }, + "personal": { + "title": "Kişisel Ayarlar", + "description": "Kişisel bilgilerinizi burada görüntüleyin ve yönetin.", + "emergency": { + "name": "Acil Durum Kiti", + "text1": "Acil Durum Kitiniz, Infisical hesabınızda oturum açmak için ihtiyaç duyacağınız bilgileri içerir.", + "text2": "Yalnızca en son yayınlanan Acil Durum Kiti geçerliliğini korur. Yeni bir Acil Durum Kiti almak için parolanızı doğrulayın.", + "download": "Acil Durum Kitini İndir" + }, + "change-language": "Dili Değiştir", + "api-keys": { + "title": "API Anahtarları", + "description": "Infisical API'ye erişmek için kişisel API Anahtarlarınızı yönetin", + "add-new": "Ekle yeni" + } + }, + "project": { + "title": "Proje Ayarları", + "description": "Bu ayarlar yalnızca mevcut seçili projeye uygulanacak.", + "danger-zone": "Tehlikeli Bölge", + "delete-project": "Projeyi Sil", + "project-to-delete": "Silinmek Üzere Olan Proje", + "danger-zone-note": "Bu projeyi sildiğiniz anda geri alamayacaksınız. Bu, tüm anahtarları hemen kaldıracaktır. Bunu hala yapmak istiyorsanız, lütfen aşağıya projenin adını girin.", + "delete-project-note": "Not: Yalnızca birden fazla projeniz olması durumunda, bir projeyi silebilirsiniz.", + "project-id-description": "Infisical'ı kod tabanınıza entegre etmek ve çevresel değişkenlerin otomatik enjeksiyonunu almak için aşağıdaki Proje Kimliğini kullanmalısınız.", + "project-id-description2": "Çeşitli diller ve çerçeveler için kod parçaları da dahil olmak üzere daha fazla rehberlik için bkz.", + "auto-generated": "Bu, projenizin otomatik olarak oluşturulan benzersiz tanımlayıcısıdır. Değiştirilemez..", + "docs": "Infisical Dokümanları" + } + }, + "signup": { + "title": "Kayıt olun", + "og-title": "Tek satır kodla .env dosyalarını değiştirin. 3 dakika içerinde Infisical'a kayıt olun.", + "og-description": "Infisical takımların API anahtarlarını ve ortam değişkenlerini yönetmelerini ve senkronize etmelerini sağlayan basit, uçtan uca şifrelenmiş bir platformdur. Node.js, Next.js, Gatsby, Nest.js ve daha fazlası ile çalışır.", + "signup": "Kayıt ol", + "already-have-account": "Hesabın var mı? Giriş yap", + "forgot-password": "Şifreni mi unuttun?", + "verify": "Doğrula", + "step1-start": "Hadi başlayalım", + "step1-privacy": "Hesap oluşturarak, Şartlarımızı ve Gizlilik Politikasını okuyup kabul etmiş olursunuz.", + "step1-submit": "Başla", + "step2-message": "Şu adrese bir doğrulama maili yolladık", + "step2-code-error": "Tüh. Kodun hatalı. Lütfen tekrar dene.", + "step2-resend-alert": "Kodu ulaşamadı mı?", + "step2-resend-submit": "Tekrar Yolla", + "step2-resend-progress": "Tekrar yollanıyor...", + "step2-spam-alert": "Spam kutunuzu kontrol ettiğinizden emin olun.", + "step3-message": "Çok az kaldı!", + "step4-message": "Acil Durum Kitinizi kayıt edin", + "step4-description1": "Eğer hesabınıza erişemezseniz, Acil Durum Kitiniz giriş yapmanın tek yoludur.", + "step4-description2": "Bunu indirmenizi ve güvenli bir ortamda saklamanızı öneriyoruz.", + "step4-description3": "Kaybetmeniz durumunda bizim dahi erişemeyeceğimiz veya kurtaramayacağımız Gizli Anahtarınızı barındırır.", + "step4-download": "PDF'yi indir", + "step5-send-invites": "Davetleri yolla", + "step5-invite-team": "Takımını davet et", + "step5-subtitle": "Infisical takım arkadaşlarınız ile kullanılmak üzere yapılmıştır. Birlikte test etmek için onları davet edin.", + "step5-skip": "Atla" + } +} diff --git a/frontend/public/lotties/system-outline-109-slider-toggle-settings.json b/frontend/public/lotties/system-outline-109-slider-toggle-settings.json new file mode 100644 index 000000000..ba9609bc3 --- /dev/null +++ b/frontend/public/lotties/system-outline-109-slider-toggle-settings.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":31,"w":500,"h":500,"nm":"109-slider-toggle-settings-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-slider","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":[249.998,250.654,0],"ix":2,"l":2},"a":{"a":0,"k":[249.998,250.654,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":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"o":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"v":[[61.63,31.225],[30.405,0],[61.63,-31.225],[92.854,0]],"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.644,0],[0,0],[29.074,0],[6.965,-26.928],[0,0],[0,-8.643],[-8.644,0],[0,0],[-29.074,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-29.074,0],[0,0],[-8.644,0],[0,8.643],[0,0],[6.965,26.928],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[170.998,-15.65],[122.171,-15.65],[61.63,-62.525],[1.088,-15.65],[-170.998,-15.65],[-186.648,0],[-170.998,15.65],[1.088,15.65],[61.63,62.525],[122.171,15.65],[170.998,15.65],[186.648,0]],"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('109-slider-toggle-settings-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.874,249.998],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[17.218,0],[0,17.217],[-17.218,0],[0,-17.218]],"o":[[-17.218,0],[0,-17.218],[17.218,0],[0,17.217]],"v":[[-124.781,31.225],[-156.005,0],[-124.781,-31.225],[-93.556,0]],"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.644,0],[0,0],[29.074,0],[0,-34.477],[-34.477,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0],[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0]],"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('109-slider-toggle-settings-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":[249.779,376.306],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"o":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"v":[[-124.781,-31.225],[-93.556,0],[-124.781,31.225],[-156.005,0]],"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":[[-34.477,0],[-6.965,26.928],[0,0],[0,8.643],[8.644,0],[0,0],[29.074,0],[0,-34.477]],"o":[[29.074,0],[0,0],[8.644,0],[0,-8.643],[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477]],"v":[[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0],[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0]],"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('109-slider-toggle-settings-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":[249.784,125.002],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":28,"op":224,"st":28,"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":[249.779,376.306,0],"ix":2,"l":2},"a":{"a":0,"k":[249.779,376.306,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.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[183.081,0],[183.132,0]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[30.132,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"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('109-slider-toggle-settings-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":[296.868,376.306],"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":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,-1.533],[1.533,0],[0,1.533],[-1.533,0]],"o":[[0,1.533],[-1.533,0],[0,-1.533],[1.533,0]],"v":[[354.977,0],[352.201,2.775],[349.426,0],[352.201,-2.775]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0,-33.661],[33.661,0],[0,33.661],[-33.661,0]],"o":[[0,33.661],[-33.661,0],[0,-33.661],[33.661,0]],"v":[[201.445,0],[140.497,60.949],[79.548,0],[140.497,-60.949]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.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('109-slider-toggle-settings-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":[124.998,376.306],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":28,"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":0,"k":0,"ix":10},"p":{"a":0,"k":[250.874,249.998,0],"ix":2,"l":2},"a":{"a":0,"k":[250.874,249.998,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.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-367.376,0],[-367.753,0]],"c":false}]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":11,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-175.524,0],[-44.7,0]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":16,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-104.053,0],[33.32,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-31.247,0],[31.247,0]],"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('109-slider-toggle-settings-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":[390.626,249.998],"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":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-149.212,0],[-149.288,0]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":11,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-123.604,0],[-89.161,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[90.712,0]],"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('109-slider-toggle-settings-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":[170.589,249.998],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,-0.55],[-0.55,0],[0,0.55],[0.55,0]],"o":[[0,0.55],[0.55,0],[0,-0.55],[-0.55,0]],"v":[[-291.246,0],[-290.25,0.996],[-289.254,0],[-290.25,-0.996]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":11,"s":[{"i":[[0,-35.345],[-35.345,0],[0,35.345],[35.345,0]],"o":[[0,35.345],[35.345,0],[0,-35.345],[-35.345,0]],"v":[[-225.398,0],[-161.4,63.998],[-97.402,0],[-161.4,-63.998]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[-46.875,0],[0,46.875],[46.875,0],[0,-46.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('109-slider-toggle-settings-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":[312.504,249.998],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":4,"op":28,"st":0,"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":0,"k":[249.784,125.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.784,125.002,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.833},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[185.113,0.001],[185.127,0.001]],"c":false}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":14,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[29.127,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"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('109-slider-toggle-settings-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":[296.873,125.002],"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":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":7,"s":[{"i":[[0,-0.431],[0.43,0],[0,0.431],[-0.431,0]],"o":[[0,0.431],[-0.43,0],[0,-0.431],[0.431,0]],"v":[[356.99,0.001],[356.21,0.78],[355.431,0.001],[356.21,-0.779]],"c":true}]},{"i":{"x":0.4,"y":1},"o":{"x":0.167,"y":0.167},"t":14,"s":[{"i":[[0,-33.109],[33.109,0],[0,33.109],[-33.108,0]],"o":[[0,33.109],[-33.109,0],[0,-33.109],[33.108,0]],"v":[[200.45,0],[140.501,59.949],[80.553,0],[140.501,-59.948]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.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('109-slider-toggle-settings-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":[125.003,125.002],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":7,"op":28,"st":0,"bm":0}]},{"id":"comp_1","nm":"hover-slider","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":[249.998,250.654,0],"ix":2,"l":2},"a":{"a":0,"k":[249.998,250.654,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":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"o":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"v":[[61.63,31.225],[30.405,0],[61.63,-31.225],[92.854,0]],"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.644,0],[0,0],[29.074,0],[6.965,-26.928],[0,0],[0,-8.643],[-8.644,0],[0,0],[-29.074,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-29.074,0],[0,0],[-8.644,0],[0,8.643],[0,0],[6.965,26.928],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[170.998,-15.65],[122.171,-15.65],[61.63,-62.525],[1.088,-15.65],[-170.998,-15.65],[-186.648,0],[-170.998,15.65],[1.088,15.65],[61.63,62.525],[122.171,15.65],[170.998,15.65],[186.648,0]],"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('109-slider-toggle-settings-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.874,249.998],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[17.218,0],[0,17.217],[-17.218,0],[0,-17.218]],"o":[[-17.218,0],[0,-17.218],[17.218,0],[0,17.217]],"v":[[-124.781,31.225],[-156.005,0],[-124.781,-31.225],[-93.556,0]],"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.644,0],[0,0],[29.074,0],[0,-34.477],[-34.477,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0],[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0]],"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('109-slider-toggle-settings-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":[249.779,376.306],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"o":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"v":[[-124.781,-31.225],[-93.556,0],[-124.781,31.225],[-156.005,0]],"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":[[-34.477,0],[-6.965,26.928],[0,0],[0,8.643],[8.644,0],[0,0],[29.074,0],[0,-34.477]],"o":[[29.074,0],[0,0],[8.644,0],[0,-8.643],[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477]],"v":[[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0],[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0]],"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('109-slider-toggle-settings-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":[249.784,125.002],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":29,"op":238,"st":0,"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":[249.998,250.654,0],"ix":2,"l":2},"a":{"a":0,"k":[249.998,250.654,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":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"o":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"v":[[61.63,31.225],[30.405,0],[61.63,-31.225],[92.854,0]],"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.644,0],[0,0],[29.074,0],[6.965,-26.928],[0,0],[0,-8.643],[-8.644,0],[0,0],[-29.074,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-29.074,0],[0,0],[-8.644,0],[0,8.643],[0,0],[6.965,26.928],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[170.998,-15.65],[122.171,-15.65],[61.63,-62.525],[1.088,-15.65],[-170.998,-15.65],[-186.648,0],[-170.998,15.65],[1.088,15.65],[61.63,62.525],[122.171,15.65],[170.998,15.65],[186.648,0]],"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('109-slider-toggle-settings-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.874,249.998],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[17.218,0],[0,17.217],[-17.218,0],[0,-17.218]],"o":[[-17.218,0],[0,-17.218],[17.218,0],[0,17.217]],"v":[[-124.781,31.225],[-156.005,0],[-124.781,-31.225],[-93.556,0]],"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.644,0],[0,0],[29.074,0],[0,-34.477],[-34.477,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0],[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0]],"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('109-slider-toggle-settings-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":[249.779,376.306],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"o":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"v":[[-124.781,-31.225],[-93.556,0],[-124.781,31.225],[-156.005,0]],"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":[[-34.477,0],[-6.965,26.928],[0,0],[0,8.643],[8.644,0],[0,0],[29.074,0],[0,-34.477]],"o":[[29.074,0],[0,0],[8.644,0],[0,-8.643],[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477]],"v":[[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0],[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0]],"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('109-slider-toggle-settings-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":[249.784,125.002],"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 3","np":3,"cix":2,"bm":0,"ix":3,"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":0,"k":0,"ix":10},"p":{"a":0,"k":[249.779,376.306,0],"ix":2,"l":2},"a":{"a":0,"k":[249.779,376.306,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]],"o":[[0,0],[0,0]],"v":[[326.5,376.25],[78.5,376.25]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[68.292]},{"t":30,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15,"s":[100]},{"t":30,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('109-slider-toggle-settings-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":"Shape 1","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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-45.297,0]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"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('109-slider-toggle-settings-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":[296.868,376.306],"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":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[126.145,0],[79.27,46.875],[32.394,0],[79.27,-46.875]],"c":true}]},{"t":30,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.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('109-slider-toggle-settings-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":[124.998,376.306],"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":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":29,"st":0,"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":0,"k":[250.874,249.998,0],"ix":2,"l":2},"a":{"a":0,"k":[250.874,249.998,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.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-31.247,0],[31.247,0]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[24.753,0],[31.247,0]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-31.247,0],[31.247,0]],"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('109-slider-toggle-settings-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":[390.626,249.998],"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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[90.712,0]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[146.712,0]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[90.712,0]],"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('109-slider-toggle-settings-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":[170.589,249.998],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[-46.875,0],[0,46.875],[46.875,0],[0,-46.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":13,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[9.125,0],[56,46.875],[102.875,0],[56,-46.875]],"c":true}]},{"t":30,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[-46.875,0],[0,46.875],[46.875,0],[0,-46.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('109-slider-toggle-settings-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":[312.504,249.998],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":29,"st":0,"bm":0},{"ddd":0,"ind":5,"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":[249.784,125.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.784,125.002,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.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[29.714,0]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"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('109-slider-toggle-settings-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":[296.873,125.002],"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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.875]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":16,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[201.156,0],[154.28,46.876],[107.405,0],[154.28,-46.875]],"c":true}]},{"t":30,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.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('109-slider-toggle-settings-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":[125.003,125.002],"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":2,"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]],"o":[[0,0],[0,0]],"v":[[326.5,125.25],[78.5,125.25]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[40.292]},{"t":30,"s":[100]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[100]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[100]},{"t":30,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('109-slider-toggle-settings-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":"Shape 1","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":29,"st":0,"bm":0}]},{"id":"comp_2","nm":"morph-slider","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":180,"ix":10},"p":{"a":0,"k":[249.998,250.654,0],"ix":2,"l":2},"a":{"a":0,"k":[249.998,250.654,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":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"o":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"v":[[61.255,32.163],[30.03,0.937],[61.255,-30.288],[92.479,0.937]],"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.644,0],[0,0],[29.074,0],[6.965,-26.928],[0,0],[0,-8.643],[-8.644,0],[0,0],[-29.074,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-29.074,0],[0,0],[-8.644,0],[0,8.643],[0,0],[6.965,26.928],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[170.061,-14.713],[121.796,-14.713],[61.255,-61.588],[0.713,-14.713],[-172.123,-14.713],[-187.773,0.937],[-172.123,16.587],[0.713,16.587],[61.255,63.463],[121.796,16.587],[170.061,16.587],[185.711,0.937]],"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('109-slider-toggle-settings-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.874,249.998],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[17.218,0],[0,17.217],[-17.218,0],[0,-17.218]],"o":[[-17.218,0],[0,-17.218],[17.218,0],[0,17.217]],"v":[[-124.781,31.225],[-156.005,0],[-124.781,-31.225],[-93.556,0]],"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.644,0],[0,0],[29.074,0],[0,-34.477],[-34.477,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0],[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0]],"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('109-slider-toggle-settings-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":[249.779,376.306],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"o":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"v":[[-124.781,-31.225],[-93.556,0],[-124.781,31.225],[-156.005,0]],"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":[[-34.477,0],[-6.965,26.928],[0,0],[0,8.643],[8.644,0],[0,0],[29.074,0],[0,-34.477]],"o":[[29.074,0],[0,0],[8.644,0],[0,-8.643],[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477]],"v":[[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0],[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0]],"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('109-slider-toggle-settings-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":[249.784,125.002],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":28,"op":238,"st":0,"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":[249.998,250.654,0],"ix":2,"l":2},"a":{"a":0,"k":[249.998,250.654,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":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"o":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"v":[[61.63,31.225],[30.405,0],[61.63,-31.225],[92.854,0]],"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.644,0],[0,0],[29.074,0],[6.965,-26.928],[0,0],[0,-8.643],[-8.644,0],[0,0],[-29.074,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-29.074,0],[0,0],[-8.644,0],[0,8.643],[0,0],[6.965,26.928],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[170.998,-15.65],[122.171,-15.65],[61.63,-62.525],[1.088,-15.65],[-170.998,-15.65],[-186.648,0],[-170.998,15.65],[1.088,15.65],[61.63,62.525],[122.171,15.65],[170.998,15.65],[186.648,0]],"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('109-slider-toggle-settings-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.874,249.998],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[17.218,0],[0,17.217],[-17.218,0],[0,-17.218]],"o":[[-17.218,0],[0,-17.218],[17.218,0],[0,17.217]],"v":[[-124.781,31.225],[-156.005,0],[-124.781,-31.225],[-93.556,0]],"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.644,0],[0,0],[29.074,0],[0,-34.477],[-34.477,0],[-6.965,26.928],[0,0],[0,8.643]],"o":[[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477],[29.074,0],[0,0],[8.644,0],[0,-8.643]],"v":[[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0],[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0]],"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('109-slider-toggle-settings-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":[249.779,376.306],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-17.218,0],[0,-17.217],[17.218,0],[0,17.218]],"o":[[17.218,0],[0,17.218],[-17.218,0],[0,-17.217]],"v":[[-124.781,-31.225],[-93.556,0],[-124.781,31.225],[-156.005,0]],"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":[[-34.477,0],[-6.965,26.928],[0,0],[0,8.643],[8.644,0],[0,0],[29.074,0],[0,-34.477]],"o":[[29.074,0],[0,0],[8.644,0],[0,-8.643],[0,0],[-6.965,-26.928],[-34.477,0],[0,34.477]],"v":[[-124.781,62.525],[-64.239,15.65],[171.656,15.65],[187.306,0],[171.656,-15.65],[-64.239,-15.65],[-124.781,-62.525],[-187.306,0]],"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('109-slider-toggle-settings-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":[249.784,125.002],"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 3","np":3,"cix":2,"bm":0,"ix":3,"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":0,"k":0,"ix":10},"p":{"a":0,"k":[250.874,249.998,0],"ix":2,"l":2},"a":{"a":0,"k":[250.874,249.998,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.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-31.247,0],[31.247,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-156.247,0],[31.247,0]],"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('109-slider-toggle-settings-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":[390.626,249.998],"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":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[90.712,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[-90.712,0],[-34.288,0]],"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('109-slider-toggle-settings-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":[170.589,249.998],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[-46.875,0],[0,46.875],[46.875,0],[0,-46.875]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[-25.888,0],[0,25.888],[25.888,0]],"o":[[0,25.888],[25.888,0],[0,-25.888],[-25.888,0]],"v":[[-171.875,0],[-125,46.875],[-78.125,0],[-125,-46.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('109-slider-toggle-settings-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":[312.504,249.998],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":28,"st":0,"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":0,"k":[249.779,376.306,0],"ix":2,"l":2},"a":{"a":0,"k":[249.779,376.306,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]],"o":[[0,0],[0,0]],"v":[[326.5,376.25],[78.5,376.25]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":1,"s":[100]},{"t":28,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":1,"s":[100]},{"t":28,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('109-slider-toggle-settings-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":"Shape 1","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":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[125.433,0]],"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('109-slider-toggle-settings-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":[296.868,376.306],"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":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.875]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[296.875,0],[250,46.875],[203.125,0],[250,-46.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('109-slider-toggle-settings-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":[124.998,376.306],"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":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":28,"st":0,"bm":0},{"ddd":0,"ind":5,"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":[249.784,125.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.784,125.002,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.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[-124.567,0]],"c":false}]},{"t":28,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[124.567,0],[125.433,0]],"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('109-slider-toggle-settings-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":[296.873,125.002],"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":1,"k":[{"i":{"x":0.4,"y":1},"o":{"x":0.6,"y":0},"t":1,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[46.875,0],[0,46.875],[-46.875,0],[0,-46.875]],"c":true}]},{"t":28,"s":[{"i":[[0,-25.888],[25.888,0],[0,25.888],[-25.888,0]],"o":[[0,25.888],[-25.888,0],[0,-25.888],[25.888,0]],"v":[[296.875,0],[250,46.876],[203.125,0],[250,-46.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('109-slider-toggle-settings-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":[125.003,125.002],"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":2,"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]],"o":[[0,0],[0,0]],"v":[[326.5,125.25],[78.5,125.25]],"c":false},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":1,"s":[100]},{"t":28,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.6],"y":[0]},"t":1,"s":[100]},{"t":28,"s":[100]}],"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('109-slider-toggle-settings-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":"Shape 1","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":28,"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":0,"ix":1}}]},{"ty":5,"nm":"State-Morph","np":3,"mn":"ADBE Slider Control","ix":6,"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-slider","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":41,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"hover-slider","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":41,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"morph-slider","parent":3,"refId":"comp_2","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-Morph')('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":41,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lotties/system-outline-168-view-headline.json b/frontend/public/lotties/system-outline-168-view-headline.json new file mode 100644 index 000000000..3d511470b --- /dev/null +++ b/frontend/public/lotties/system-outline-168-view-headline.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":61,"w":500,"h":500,"nm":"168-view-headline-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-headline","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],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,385.421],"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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,114.586],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":56,"op":300,"st":0,"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":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[250.004,566.586,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":42,"s":[250.004,113.586,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.2,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[43.004,36.458],[-43.004,36.458],[-43.004,-36.458],[43.004,-36.458]],"c":true}]},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":56,"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":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.2,"y":1},"o":{"x":0.167,"y":0.167},"t":10,"s":[250.004,702.003,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":49,"s":[250.004,249.003,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.2,"y":1},"o":{"x":0.333,"y":0},"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[43.004,36.458],[-43.004,36.458],[-43.004,-36.458],[43.004,-36.458]],"c":true}]},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":56,"st":0,"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":20,"s":[250.004,837.42,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":56,"s":[250.004,384.42,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.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[43.004,36.458],[-43.004,36.458],[-43.004,-36.458],[43.004,-36.458]],"c":true}]},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":56,"st":0,"bm":0}]},{"id":"comp_1","nm":"hover-headline","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],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,385.421],"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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,114.586],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"st","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"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,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 4","np":1,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false}],"ip":59,"op":300,"st":0,"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],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,385.421],"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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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},{"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":[[156.226,20.808],[-156.226,20.808],[-156.226,-20.808],[156.226,-20.808]],"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.644,0],[0,0],[0,-8.643],[0,0],[-8.644,0],[0,0],[0,8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,8.643],[0,0],[8.644,0],[0,0],[0,-8.643]],"v":[[171.876,-52.108],[-171.876,-52.108],[-187.526,-36.458],[-187.526,36.458],[-171.876,52.108],[171.876,52.108],[187.526,36.458],[187.526,-36.458]],"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('168-view-headline-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,114.586],"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 3","np":3,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ty":"st","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":3,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"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,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 4","np":1,"cix":2,"bm":0,"ix":4,"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":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.333,"y":0},"t":1,"s":[250.004,114.586,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":21,"s":[250.004,-338.414,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"st":0,"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.833,"y":0.833},"o":{"x":0.333,"y":0},"t":3,"s":[250.004,250.003,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":29,"s":[250.004,-202.997,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"st":0,"bm":0},{"ddd":0,"ind":5,"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.833,"y":0.833},"o":{"x":0.333,"y":0},"t":5,"s":[250.004,385.42,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":37,"s":[250.004,-67.58,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"st":0,"bm":0},{"ddd":0,"ind":6,"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.333,"y":0},"t":15,"s":[250.004,566.586,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":51,"s":[250.004,113.586,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"st":0,"bm":0},{"ddd":0,"ind":7,"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.333,"y":0},"t":21,"s":[250.004,702.003,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":55,"s":[250.004,249.003,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"st":0,"bm":0},{"ddd":0,"ind":8,"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.333,"y":0},"t":28,"s":[250.004,837.42,0],"to":[0,-75.5,0],"ti":[0,75.5,0]},{"t":59,"s":[250.004,384.42,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],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[171.876,36.458],[-171.876,36.458],[-171.876,-36.458],[171.876,-36.458]],"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('168-view-headline-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":"gr","it":[{"ty":"fl","c":{"a":0,"k":[0.070588235294,0.074509803922,0.192156862745,1],"ix":4,"x":"var $bm_rt;\n$bm_rt = comp('168-view-headline-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":[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 2","np":1,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":59,"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-headline","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-headline","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/public/lotties/system-outline-82-extension.json b/frontend/public/lotties/system-outline-82-extension.json new file mode 100644 index 000000000..1a3f6b7d3 --- /dev/null +++ b/frontend/public/lotties/system-outline-82-extension.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":61,"w":500,"h":500,"nm":"82-extension-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-extension","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,250,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,2.81],[0,0],[0,0],[0,35.97],[-12.144,12.432],[-0.087,0.085],[-17.194,0],[0,0],[0,0],[2.81,0],[0,0],[0,8.643],[0,0],[7.854,7.698],[0.074,0.075],[11.159,0],[0,-22.961],[0,0],[8.644,0],[0,0],[0,-2.81],[0,0],[8.644,0],[0,0],[7.697,-7.854],[0.075,-0.074],[0,-11.159],[-22.962,0],[0,0],[0,-8.643],[0,0],[-2.81,0],[0,0],[0,0],[-35.97,0],[-12.431,-12.143],[-0.085,-0.087],[0,-17.191]],"o":[[0,0],[2.81,0],[0,0],[0,0],[-35.97,0],[0,-17.19],[0.084,-0.086],[12.563,-12.279],[0,0],[0,0],[0,-2.81],[0,0],[-8.644,0],[0,0],[0,-11.158],[-0.075,-0.073],[-7.696,-7.854],[-22.962,0],[0,0],[0,8.643],[0,0],[-2.81,0],[0,0],[0,8.643],[0,0],[-11.158,0],[-0.073,0.075],[-7.854,7.697],[0,22.961],[0,0],[8.644,0],[0,0],[0,2.81],[0,0],[0,0],[0,-35.855],[17.192,0],[0.087,0.085],[12.143,12.431],[0,0]],"v":[[96.279,156.229],[151.046,156.229],[156.229,151.045],[156.229,96.486],[148.546,96.486],[83.312,31.253],[102.143,-14.683],[102.399,-14.939],[148.546,-33.98],[156.229,-33.98],[156.229,-88.539],[151.046,-93.723],[88.546,-93.723],[72.896,-109.372],[72.896,-135.414],[60.717,-164.655],[60.493,-164.878],[31.254,-177.057],[-10.388,-135.414],[-10.388,-109.372],[-26.038,-93.723],[-88.538,-93.723],[-93.722,-88.539],[-93.722,-26.039],[-109.372,-10.389],[-135.414,-10.389],[-164.654,1.79],[-164.877,2.013],[-177.056,31.253],[-135.414,72.895],[-109.372,72.895],[-93.722,88.545],[-93.722,151.045],[-88.538,156.229],[-33.98,156.229],[-33.98,148.337],[31.254,83.312],[77.19,102.142],[77.449,102.401],[96.279,148.337]],"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":[[20.117,0],[0,0],[0,8.643],[0,0],[6.315,6.532],[8.909,0],[0,-18.596],[0,0],[8.644,0],[0,0],[0,20.117],[0,0],[0,0],[0,40.22],[-13.837,13.621],[-19.586,0],[0,0],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[-13.62,-13.838],[0,-19.586],[0,0],[0,0],[0,-20.117],[0,0],[8.644,0],[0,0],[6.662,-6.449],[0,-8.91],[-18.711,0],[0,0],[0,-8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-8.909],[-6.531,-6.316],[-18.711,0],[0,0],[0,8.643],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[0,-19.584],[13.622,-13.841],[0,0],[0,0],[0,-20.117],[0,0],[0,0],[0,-40.22],[19.585,0],[13.841,13.622],[0,0],[0,0],[20.117,0],[0,0],[0,8.643],[0,0],[-8.911,0],[-6.318,6.533],[0,18.711],[0,0],[8.644,0],[0,0],[0,20.117]],"v":[[151.046,187.528],[80.629,187.528],[64.979,171.879],[64.979,148.337],[55.188,124.405],[31.254,114.611],[-2.68,148.337],[-2.68,171.879],[-18.33,187.528],[-88.538,187.528],[-125.022,151.045],[-125.022,104.195],[-135.414,104.195],[-208.356,31.253],[-186.9,-20.228],[-135.414,-41.689],[-125.022,-41.689],[-125.022,-88.539],[-88.538,-125.022],[-41.688,-125.022],[-41.688,-135.414],[31.254,-208.356],[82.735,-186.9],[104.196,-135.414],[104.196,-125.022],[151.046,-125.022],[187.53,-88.539],[187.53,-18.33],[171.88,-2.681],[148.546,-2.681],[124.408,7.317],[114.612,31.253],[148.546,65.187],[171.88,65.187],[187.53,80.837],[187.53,151.045]],"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('82-extension-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":[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":60,"op":300,"st":0,"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":1,"k":[{"i":{"x":[0.235],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":18,"s":[0]},{"i":{"x":[0.5],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":30,"s":[-90]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.5],"y":[0]},"t":42,"s":[-90]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":53,"s":[13]},{"t":60,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.235,"y":1},"o":{"x":0.5,"y":0},"t":18,"s":[250,250,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.5,"y":0.5},"o":{"x":0.333,"y":0.333},"t":30,"s":[291.748,250,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.268,"y":1},"o":{"x":0.5,"y":0},"t":42,"s":[291.748,250,0],"to":[0,0,0],"ti":[0,0,0]},{"t":53,"s":[281.647,281.334,0]}],"ix":2,"l":2},"a":{"a":0,"k":[42.06,41.748,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,"y":1},"o":{"x":0.167,"y":0.167},"t":-1,"s":[{"i":[[0.001,-0.001],[0,-0.002],[0,0],[-0.001,0],[0,0],[0,0],[0.081,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,-0.001],[0,0],[0,0],[0,0.081],[0,0],[0,0],[0,0.001],[0,0],[-0.001,0.001],[-0.001,0],[0,0],[0,0],[-0.081,0],[0,0],[0,0],[-0.001,0],[0,0],[0,0],[0,0],[0,0],[0,0],[0,-0.081],[0,0],[0,0]],"o":[[-0.001,0.001],[0,0],[0,0.001],[0,0],[0,0],[0,0.081],[0,0],[0,0],[0,0],[0,0],[0,0],[-0.001,0],[0,0],[0,0],[-0.081,0],[0,0],[0,0],[-0.001,0],[0,0],[0,-0.001],[0.001,-0.001],[0,0],[0,0],[0,-0.081],[0,0],[0,0],[0,-0.001],[0,0],[0,0],[0,0],[0,0],[0,0],[0.081,0],[0,0],[0,0],[-0.002,0]],"v":[[43.056,41.398],[43.055,41.401],[43.055,42.097],[43.057,42.099],[43.054,42.099],[43.054,42.597],[42.906,42.744],[42.407,42.744],[42.408,42.746],[42.408,42.745],[42.407,42.745],[41.708,42.745],[41.707,42.746],[41.706,42.744],[41.209,42.744],[41.061,42.597],[41.061,42.154],[41.062,42.154],[41.06,42.152],[41.06,41.345],[41.061,41.343],[41.064,41.342],[41.061,41.342],[41.061,40.899],[41.209,40.751],[41.651,40.751],[41.651,40.752],[41.653,40.75],[42.463,40.75],[42.463,40.75],[42.463,40.751],[42.464,40.751],[42.906,40.751],[43.054,40.899],[43.054,41.396],[43.06,41.396]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.333,"y":0},"t":15,"s":[{"i":[[0.146,-0.142],[0,-0.218],[0,-0.001],[-0.158,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[0.023,0.023],[0.036,0],[0.001,0],[0,-0.085],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0.002,0.163],[0,0.001],[-0.083,0.081],[-0.126,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.113,0.001],[0,0],[-0.008,-0.008],[0,-0.013],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-0.139,0.142],[0,0.002],[0.001,0.157],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-0.036],[-0.023,-0.023],[-0.001,0],[-0.085,0.002],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.163,0],[0,-0.001],[0,-0.126],[0.081,-0.083],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-0.113],[0.001,0],[0.013,0],[0.008,0.008],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-0.218,0]],"v":[[182.604,-7.728],[182.376,-7.172],[182.376,90.923],[182.663,91.207],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.115,182.503],[91.078,182.413],[90.988,182.376],[-7.69,182.382],[-7.844,182.539],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-98.745,99.004],[-99.042,98.71],[-99.043,-15.124],[-98.908,-15.446],[-98.587,-15.58],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.663,-98.836],[-15.459,-99.042],[98.875,-99.043],[98.907,-99.029],[98.921,-98.997],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[183.163,-7.96]],"c":true}]},{"i":{"x":0.235,"y":1},"o":{"x":0.5,"y":0},"t":18,"s":[{"i":[[0.146,-0.142],[0,-0.218],[0,-0.001],[-0.158,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[0.023,0.023],[0.036,0],[0.001,0],[0,-0.085],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0.002,0.163],[0,0.001],[-0.083,0.081],[-0.126,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.113,0.001],[0,0],[-0.008,-0.008],[0,-0.013],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-0.139,0.142],[0,0.002],[0.001,0.157],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-0.036],[-0.023,-0.023],[-0.001,0],[-0.085,0.002],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.163,0],[0,-0.001],[0,-0.126],[0.081,-0.083],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-0.113],[0.001,0],[0.013,0],[0.008,0.008],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-0.218,0]],"v":[[182.604,-7.728],[182.376,-7.172],[182.376,90.923],[182.663,91.207],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.115,182.503],[91.078,182.413],[90.988,182.376],[-7.69,182.382],[-7.844,182.539],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-98.745,99.004],[-99.042,98.71],[-99.043,-15.124],[-98.908,-15.446],[-98.587,-15.58],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.663,-98.836],[-15.459,-99.042],[98.875,-99.043],[98.907,-99.029],[98.921,-98.997],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[183.163,-7.96]],"c":true}]},{"i":{"x":0.5,"y":1},"o":{"x":0.333,"y":0},"t":30,"s":[{"i":[[0.146,-0.142],[0,-0.218],[0,-0.001],[-0.158,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[8.75,8.958],[13.749,0],[0.481,-0.014],[0,-26.807],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0.002,0.163],[0,0.001],[-0.083,0.081],[-0.126,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.437,0.267],[-0.166,0],[-10.208,-10.417],[0,-15.834],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-0.139,0.142],[0,0.002],[0.001,0.157],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-13.751],[-8.958,-8.751],[-0.484,0],[-26.628,0.765],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.163,0],[0,-0.001],[0,-0.126],[0.081,-0.083],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-31.501],[0.166,-0.001],[15.834,0],[10.417,10.208],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-0.218,0]],"v":[[182.604,-7.728],[182.376,-7.172],[182.376,90.923],[182.663,91.208],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.042,158.751],[76.667,123.751],[41.667,109.376],[40.218,109.396],[-7.917,158.751],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-98.745,99.004],[-99.042,98.71],[-99.043,-15.124],[-98.908,-15.446],[-98.587,-15.58],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.625,-125.001],[41.168,-182.29],[41.667,-182.293],[82.084,-165.418],[98.959,-125.001],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[183.163,-7.96]],"c":true}]},{"i":{"x":0.268,"y":1},"o":{"x":0.5,"y":0},"t":42,"s":[{"i":[[0.146,-0.142],[0,-0.218],[0,-0.001],[-0.158,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[8.75,8.958],[13.749,0],[0.481,-0.014],[0,-26.807],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0.002,0.163],[0,0.001],[-0.083,0.081],[-0.126,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.437,0.267],[-0.166,0],[-10.208,-10.417],[0,-15.834],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-0.139,0.142],[0,0.002],[0.001,0.157],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-13.751],[-8.958,-8.751],[-0.484,0],[-26.628,0.765],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-0.163,0],[0,-0.001],[0,-0.126],[0.081,-0.083],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-31.501],[0.166,-0.001],[15.834,0],[10.417,10.208],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-0.218,0]],"v":[[182.604,-7.728],[182.376,-7.172],[182.376,90.923],[182.663,91.208],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.042,158.751],[76.667,123.751],[41.667,109.376],[40.218,109.396],[-7.917,158.751],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-98.745,99.004],[-99.042,98.71],[-99.043,-15.124],[-98.908,-15.446],[-98.587,-15.58],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.625,-125.001],[41.168,-182.29],[41.667,-182.293],[82.084,-165.418],[98.959,-125.001],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[183.163,-7.96]],"c":true}]},{"t":53,"s":[{"i":[[9.167,-8.958],[0,-13.751],[-0.002,-0.163],[-27.336,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[8.75,8.958],[13.749,0],[0.481,-0.014],[0,-26.807],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0.316,31.394],[0,0.197],[-10.417,10.208],[-15.834,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.437,0.267],[-0.166,0],[-10.208,-10.417],[0,-15.834],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-8.75,8.958],[0,0.163],[0.262,27.069],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-13.751],[-8.958,-8.751],[-0.484,0],[-26.628,0.765],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.47,0],[-0.002,-0.196],[0,-15.834],[10.208,-10.417],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-31.501],[0.166,-0.001],[15.834,0],[10.417,10.208],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-13.751,0]],"v":[[123.751,6.667],[109.376,41.667],[109.378,42.156],[158.959,91.251],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.042,158.751],[76.667,123.751],[41.667,109.376],[40.218,109.396],[-7.917,158.751],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-125.001,98.959],[-182.29,42.257],[-182.293,41.667],[-165.418,1.25],[-125.001,-15.625],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.625,-125.001],[41.168,-182.29],[41.667,-182.293],[82.084,-165.418],[98.959,-125.001],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[158.959,-7.917]],"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('82-extension-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":0,"bm":0}]},{"id":"comp_1","nm":"hover-extension","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,250,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,2.81],[0,0],[0,0],[0,35.97],[-12.144,12.432],[-0.087,0.085],[-17.194,0],[0,0],[0,0],[2.81,0],[0,0],[0,8.643],[0,0],[7.854,7.698],[0.074,0.075],[11.159,0],[0,-22.961],[0,0],[8.644,0],[0,0],[0,-2.81],[0,0],[8.644,0],[0,0],[7.697,-7.854],[0.075,-0.074],[0,-11.159],[-22.962,0],[0,0],[0,-8.643],[0,0],[-2.81,0],[0,0],[0,0],[-35.97,0],[-12.431,-12.143],[-0.085,-0.087],[0,-17.191]],"o":[[0,0],[2.81,0],[0,0],[0,0],[-35.97,0],[0,-17.19],[0.084,-0.086],[12.563,-12.279],[0,0],[0,0],[0,-2.81],[0,0],[-8.644,0],[0,0],[0,-11.158],[-0.075,-0.073],[-7.696,-7.854],[-22.962,0],[0,0],[0,8.643],[0,0],[-2.81,0],[0,0],[0,8.643],[0,0],[-11.158,0],[-0.073,0.075],[-7.854,7.697],[0,22.961],[0,0],[8.644,0],[0,0],[0,2.81],[0,0],[0,0],[0,-35.855],[17.192,0],[0.087,0.085],[12.143,12.431],[0,0]],"v":[[96.279,156.229],[151.046,156.229],[156.229,151.045],[156.229,96.486],[148.546,96.486],[83.312,31.253],[102.143,-14.683],[102.399,-14.939],[148.546,-33.98],[156.229,-33.98],[156.229,-88.539],[151.046,-93.723],[88.546,-93.723],[72.896,-109.372],[72.896,-135.414],[60.717,-164.655],[60.493,-164.878],[31.254,-177.057],[-10.388,-135.414],[-10.388,-109.372],[-26.038,-93.723],[-88.538,-93.723],[-93.722,-88.539],[-93.722,-26.039],[-109.372,-10.389],[-135.414,-10.389],[-164.654,1.79],[-164.877,2.013],[-177.056,31.253],[-135.414,72.895],[-109.372,72.895],[-93.722,88.545],[-93.722,151.045],[-88.538,156.229],[-33.98,156.229],[-33.98,148.337],[31.254,83.312],[77.19,102.142],[77.449,102.401],[96.279,148.337]],"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":[[20.117,0],[0,0],[0,8.643],[0,0],[6.315,6.532],[8.909,0],[0,-18.596],[0,0],[8.644,0],[0,0],[0,20.117],[0,0],[0,0],[0,40.22],[-13.837,13.621],[-19.586,0],[0,0],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[-13.62,-13.838],[0,-19.586],[0,0],[0,0],[0,-20.117],[0,0],[8.644,0],[0,0],[6.662,-6.449],[0,-8.91],[-18.711,0],[0,0],[0,-8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-8.909],[-6.531,-6.316],[-18.711,0],[0,0],[0,8.643],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[0,-19.584],[13.622,-13.841],[0,0],[0,0],[0,-20.117],[0,0],[0,0],[0,-40.22],[19.585,0],[13.841,13.622],[0,0],[0,0],[20.117,0],[0,0],[0,8.643],[0,0],[-8.911,0],[-6.318,6.533],[0,18.711],[0,0],[8.644,0],[0,0],[0,20.117]],"v":[[151.046,187.528],[80.629,187.528],[64.979,171.879],[64.979,148.337],[55.188,124.405],[31.254,114.611],[-2.68,148.337],[-2.68,171.879],[-18.33,187.528],[-88.538,187.528],[-125.022,151.045],[-125.022,104.195],[-135.414,104.195],[-208.356,31.253],[-186.9,-20.228],[-135.414,-41.689],[-125.022,-41.689],[-125.022,-88.539],[-88.538,-125.022],[-41.688,-125.022],[-41.688,-135.414],[31.254,-208.356],[82.735,-186.9],[104.196,-135.414],[104.196,-125.022],[151.046,-125.022],[187.53,-88.539],[187.53,-18.33],[171.88,-2.681],[148.546,-2.681],[124.408,7.317],[114.612,31.253],[148.546,65.187],[171.88,65.187],[187.53,80.837],[187.53,151.045]],"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('82-extension-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":[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":60,"op":300,"st":0,"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,250,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,2.81],[0,0],[0,0],[0,35.97],[-12.144,12.432],[-0.087,0.085],[-17.194,0],[0,0],[0,0],[2.81,0],[0,0],[0,8.643],[0,0],[7.854,7.698],[0.074,0.075],[11.159,0],[0,-22.961],[0,0],[8.644,0],[0,0],[0,-2.81],[0,0],[8.644,0],[0,0],[7.697,-7.854],[0.075,-0.074],[0,-11.159],[-22.962,0],[0,0],[0,-8.643],[0,0],[-2.81,0],[0,0],[0,0],[-35.97,0],[-12.431,-12.143],[-0.085,-0.087],[0,-17.191]],"o":[[0,0],[2.81,0],[0,0],[0,0],[-35.97,0],[0,-17.19],[0.084,-0.086],[12.563,-12.279],[0,0],[0,0],[0,-2.81],[0,0],[-8.644,0],[0,0],[0,-11.158],[-0.075,-0.073],[-7.696,-7.854],[-22.962,0],[0,0],[0,8.643],[0,0],[-2.81,0],[0,0],[0,8.643],[0,0],[-11.158,0],[-0.073,0.075],[-7.854,7.697],[0,22.961],[0,0],[8.644,0],[0,0],[0,2.81],[0,0],[0,0],[0,-35.855],[17.192,0],[0.087,0.085],[12.143,12.431],[0,0]],"v":[[96.279,156.229],[151.046,156.229],[156.229,151.045],[156.229,96.486],[148.546,96.486],[83.312,31.253],[102.143,-14.683],[102.399,-14.939],[148.546,-33.98],[156.229,-33.98],[156.229,-88.539],[151.046,-93.723],[88.546,-93.723],[72.896,-109.372],[72.896,-135.414],[60.717,-164.655],[60.493,-164.878],[31.254,-177.057],[-10.388,-135.414],[-10.388,-109.372],[-26.038,-93.723],[-88.538,-93.723],[-93.722,-88.539],[-93.722,-26.039],[-109.372,-10.389],[-135.414,-10.389],[-164.654,1.79],[-164.877,2.013],[-177.056,31.253],[-135.414,72.895],[-109.372,72.895],[-93.722,88.545],[-93.722,151.045],[-88.538,156.229],[-33.98,156.229],[-33.98,148.337],[31.254,83.312],[77.19,102.142],[77.449,102.401],[96.279,148.337]],"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":[[20.117,0],[0,0],[0,8.643],[0,0],[6.315,6.532],[8.909,0],[0,-18.596],[0,0],[8.644,0],[0,0],[0,20.117],[0,0],[0,0],[0,40.22],[-13.837,13.621],[-19.586,0],[0,0],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[-13.62,-13.838],[0,-19.586],[0,0],[0,0],[0,-20.117],[0,0],[8.644,0],[0,0],[6.662,-6.449],[0,-8.91],[-18.711,0],[0,0],[0,-8.643],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-8.909],[-6.531,-6.316],[-18.711,0],[0,0],[0,8.643],[0,0],[-20.117,0],[0,0],[0,0],[-40.221,0],[0,-19.584],[13.622,-13.841],[0,0],[0,0],[0,-20.117],[0,0],[0,0],[0,-40.22],[19.585,0],[13.841,13.622],[0,0],[0,0],[20.117,0],[0,0],[0,8.643],[0,0],[-8.911,0],[-6.318,6.533],[0,18.711],[0,0],[8.644,0],[0,0],[0,20.117]],"v":[[151.046,187.528],[80.629,187.528],[64.979,171.879],[64.979,148.337],[55.188,124.405],[31.254,114.611],[-2.68,148.337],[-2.68,171.879],[-18.33,187.528],[-88.538,187.528],[-125.022,151.045],[-125.022,104.195],[-135.414,104.195],[-208.356,31.253],[-186.9,-20.228],[-135.414,-41.689],[-125.022,-41.689],[-125.022,-88.539],[-88.538,-125.022],[-41.688,-125.022],[-41.688,-135.414],[31.254,-208.356],[82.735,-186.9],[104.196,-135.414],[104.196,-125.022],[151.046,-125.022],[187.53,-88.539],[187.53,-18.33],[171.88,-2.681],[148.546,-2.681],[124.408,7.317],[114.612,31.253],[148.546,65.187],[171.88,65.187],[187.53,80.837],[187.53,151.045]],"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('82-extension-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":[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":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.22],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[0]},{"t":60,"s":[90]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.22,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[239.587,239.586,0],"to":[14,-0.167,0],"ti":[-14,0.167,0]},{"t":60,"s":[323.587,238.586,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.22,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[9.167,-8.958],[0,-13.751],[-27.5,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[8.75,8.958],[13.749,0],[0,-27.292],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,31.666],[-10.417,10.208],[-15.834,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.667,0],[-10.208,-10.417],[0,-15.834],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-8.75,8.958],[0,27.292],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,-13.751],[-8.958,-8.751],[-27.292,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.667,0],[0,-15.834],[10.208,-10.417],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,-31.667],[15.834,0],[10.417,10.208],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-13.751,0]],"v":[[123.751,6.667],[109.376,41.667],[158.959,91.251],[182.293,91.251],[182.293,161.459],[161.459,182.293],[91.042,182.293],[91.042,158.751],[76.667,123.751],[41.667,109.376],[-7.917,158.751],[-7.917,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-125.001,98.959],[-182.293,41.667],[-165.418,1.25],[-125.001,-15.625],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-15.625,-98.959],[-15.625,-125.001],[41.667,-182.293],[82.084,-165.418],[98.959,-125.001],[98.959,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[158.959,-7.917]],"c":true}]},{"t":60,"s":[{"i":[[9.167,-8.958],[0,-13.751],[-27.5,0],[0,0],[0,0],[11.458,0],[0,0],[0,0],[10.106,-10.233],[15.881,0],[0,31.176],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,31.666],[-10.417,10.208],[-15.834,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-27.5,0],[-8.865,9.068],[0,13.784],[0,0],[0,0],[0,-11.458],[0,0],[0,0]],"o":[[-8.75,8.958],[0,27.292],[0,0],[0,0],[0,11.458],[0,0],[0,0],[0,15.708],[-10.347,9.996],[-31.522,0],[0,0],[0,0],[-11.458,0],[0,0],[0,0],[-31.667,0],[0,-15.834],[10.208,-10.417],[0,0],[0,0],[0,-11.458],[0,0],[0,0],[0,27.568],[13.75,0],[9.046,-8.887],[0,0],[0,0],[11.458,0],[0,0],[0,0],[-13.751,0]],"v":[[123.751,6.667],[109.376,41.667],[158.959,91.251],[182.293,91.251],[182.293,161.459],[161.459,182.293],[98.711,182.293],[98.711,209.185],[82.108,249.166],[41.683,265.587],[-15.586,209.185],[-15.586,182.293],[-78.125,182.293],[-98.959,161.459],[-98.959,98.959],[-125.001,98.959],[-182.293,41.667],[-165.418,1.25],[-125.001,-15.625],[-98.959,-15.625],[-98.959,-78.125],[-78.125,-98.959],[-8.086,-98.959],[-8.086,-76.288],[41.667,-26.413],[76.765,-41.104],[91.42,-76.288],[91.42,-98.959],[161.459,-98.959],[182.293,-78.125],[182.293,-7.917],[158.959,-7.917]],"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('82-extension-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":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-extension","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-extension","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/public/lotties/system-outline-90-lock-closed.json b/frontend/public/lotties/system-outline-90-lock-closed.json new file mode 100644 index 000000000..0c17d8343 --- /dev/null +++ b/frontend/public/lotties/system-outline-90-lock-closed.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":31,"w":500,"h":500,"nm":"90-lock-closed-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-lock","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,250,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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0,0]],"v":[[135.388,151.044],[109.372,177.06],[-109.377,177.06],[-135.394,151.044],[-135.394,-10.393],[135.388,-10.393]],"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":[[0,0],[-48.809,0],[0,0],[0,-48.809],[0,0],[0,0]],"o":[[0,-48.809],[0,0],[48.809,0],[0,0],[0,0],[0,0]],"v":[[-93.727,-88.54],[-5.21,-177.057],[5.206,-177.057],[93.723,-88.54],[93.723,-41.693],[-93.727,-41.693]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[8.644,0],[0,0],[0,0],[66.067,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-66.067],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.038,-41.693],[125.023,-41.693],[125.023,-88.54],[5.206,-208.357],[-5.21,-208.357],[-125.027,-88.54],[-125.027,-41.693],[-151.044,-41.693],[-166.694,-26.043],[-166.694,151.044],[-109.377,208.36],[109.372,208.36],[166.688,151.044],[166.688,-26.043]],"c":true},"ix":2},"nm":"Path 3","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('90-lock-closed-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":[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":4,"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.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42],[-0.02,-0.42]],"o":[[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42],[0.03,0.42]],"v":[[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89],[-25.596,-17.63]],"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('90-lock-closed-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":[0,81],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":316,"st":30,"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":1,"k":[{"i":{"x":[0.318],"y":[1.007]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[0]},{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[-24]},{"t":30,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.318,"y":0.999},"o":{"x":0.167,"y":0.167},"t":1,"s":[311.997,439.333,0],"to":[-6.083,-89.417,0],"ti":[18.083,13.417,0]},{"i":{"x":0.186,"y":0.995},"o":{"x":0.333,"y":0},"t":13,"s":[223.997,307.333,0],"to":[8.167,6.833,0],"ti":[-2.75,-4.5,0]},{"t":27,"s":[249.997,333.333,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.997,333.333,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.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.183,22.836],[2.183,22.836]],"c":false}]},{"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,0],[0,0]],"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('90-lock-closed-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":51.25,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249.998,312.498],"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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.183,-3.642],[3.27,-3.448]],"c":false}]},{"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-26.478],[0,26.478]],"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('90-lock-closed-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":[250.005,333.768],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-149.003,-4.562],[-148.755,0.919],[-107.088,42.586],[111.66,42.586],[153.327,0.919],[153.079,-4.562]],"c":true}]},{"t":8,"s":[{"i":[[0,0],[0,0],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-151.041,-109.377],[-151.041,67.71],[-109.374,109.377],[109.374,109.377],[151.041,67.71],[151.041,-109.377]],"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('90-lock-closed-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":[249.997,333.333],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[140.623,321.957,0],"to":[0,-16.333,0],"ti":[0,16.333,0]},{"t":8,"s":[140.623,223.957,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-109.375,83.332,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.667,"y":1},"o":{"x":0.333,"y":0},"t":16.426,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,4.832],[109.375,5.835],[5.208,-98.332],[-5.208,-98.332],[-109.375,5.835],[-109.375,83.332]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":21.361,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.754,74.178],[5.587,-29.989],[-4.829,-29.989],[-108.996,74.178],[-109.375,83.332]],"c":false}]},{"t":30,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.1],"y":[1]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[100]},{"t":12.10546875,"s":[0]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('90-lock-closed-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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"bm":0}]},{"id":"comp_1","nm":"hover-lock","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,250,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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0,0]],"v":[[135.388,151.044],[109.372,177.06],[-109.377,177.06],[-135.394,151.044],[-135.394,-10.393],[135.388,-10.393]],"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":[[0,0],[-48.809,0],[0,0],[0,-48.809],[0,0],[0,0]],"o":[[0,-48.809],[0,0],[48.809,0],[0,0],[0,0],[0,0]],"v":[[-93.727,-88.54],[-5.21,-177.057],[5.206,-177.057],[93.723,-88.54],[93.723,-41.693],[-93.727,-41.693]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[8.644,0],[0,0],[0,0],[66.067,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-66.067],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.038,-41.693],[125.023,-41.693],[125.023,-88.54],[5.206,-208.357],[-5.21,-208.357],[-125.027,-88.54],[-125.027,-41.693],[-151.044,-41.693],[-166.694,-26.043],[-166.694,151.044],[-109.377,208.36],[109.372,208.36],[166.688,151.044],[166.688,-26.043]],"c":true},"ix":2},"nm":"Path 3","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('90-lock-closed-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":[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":4,"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.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42],[-0.02,-0.42]],"o":[[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42],[0.03,0.42]],"v":[[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89],[-25.596,-17.63]],"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('90-lock-closed-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":[0,81],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":30,"op":302,"st":-30,"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,250,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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0,0]],"v":[[135.388,151.044],[109.372,177.06],[-109.377,177.06],[-135.394,151.044],[-135.394,-10.393],[135.388,-10.393]],"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":[[0,0],[-48.809,0],[0,0],[0,-48.809],[0,0],[0,0]],"o":[[0,-48.809],[0,0],[48.809,0],[0,0],[0,0],[0,0]],"v":[[-93.727,-88.54],[-5.21,-177.057],[5.206,-177.057],[93.723,-88.54],[93.723,-41.693],[-93.727,-41.693]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[8.644,0],[0,0],[0,0],[66.067,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-66.067],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.038,-41.693],[125.023,-41.693],[125.023,-88.54],[5.206,-208.357],[-5.21,-208.357],[-125.027,-88.54],[-125.027,-41.693],[-151.044,-41.693],[-166.694,-26.043],[-166.694,151.044],[-109.377,208.36],[109.372,208.36],[166.688,151.044],[166.688,-26.043]],"c":true},"ix":2},"nm":"Path 3","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('90-lock-closed-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":[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":4,"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.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42],[-0.02,-0.42]],"o":[[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42],[0.03,0.42]],"v":[[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89],[-25.596,-17.63]],"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('90-lock-closed-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":[0,81],"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":2,"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.267],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15.096,"s":[-18]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[14]},{"t":31,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.267,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[249.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":11,"s":[192.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[273.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"t":29,"s":[249.997,333.333,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.997,333.333,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]],"o":[[0,0],[0,0]],"v":[[0,0],[0,0]],"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('90-lock-closed-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":51.25,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249.998,312.498],"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],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-26.478],[0,26.478]],"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('90-lock-closed-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":[250.005,333.768],"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":2,"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],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-151.041,-109.377],[-151.041,67.71],[-109.374,109.377],[109.374,109.377],[151.041,67.71],[151.041,-109.377]],"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('90-lock-closed-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":[249.997,333.333],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"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":[140.623,223.957,0],"ix":2,"l":2},"a":{"a":0,"k":[-109.375,83.332,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.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":6,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.375,40.835],[5.208,-63.332],[-5.208,-63.332],[-109.375,40.835],[-109.375,83.332]],"c":false}]},{"t":13.095703125,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"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('90-lock-closed-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":30,"st":0,"bm":0}]},{"id":"comp_2","nm":"morph-lock-unlock","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,250,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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0,0]],"v":[[135.388,151.044],[109.372,177.06],[-109.377,177.06],[-135.394,151.044],[-135.394,-10.393],[135.388,-10.393]],"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":[[0,0],[-48.809,0],[0,0],[0,-48.809],[0,0],[0,0]],"o":[[0,-48.809],[0,0],[48.809,0],[0,0],[0,0],[0,0]],"v":[[-93.727,-88.54],[-5.21,-177.057],[5.206,-177.057],[93.723,-88.54],[93.723,-41.693],[-93.727,-41.693]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[8.644,0],[0,0],[0,0],[66.067,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-66.067],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.038,-41.693],[125.023,-41.693],[125.023,-88.54],[5.206,-208.357],[-5.21,-208.357],[-125.027,-88.54],[-125.027,-41.693],[-151.044,-41.693],[-166.694,-26.043],[-166.694,151.044],[-109.377,208.36],[109.372,208.36],[166.688,151.044],[166.688,-26.043]],"c":true},"ix":2},"nm":"Path 3","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('90-lock-closed-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":[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":4,"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.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42],[-0.02,-0.42]],"o":[[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42],[0.03,0.42]],"v":[[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89],[-25.596,-17.63]],"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('90-lock-closed-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":[0,81],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1,"st":0,"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":[249.997,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.997,250.002,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.02,-0.42],[-0.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42]],"o":[[0.03,0.42],[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42]],"v":[[-25.596,-17.63],[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89]],"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('90-lock-closed-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":[249.995,331.386],"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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0],[-0.029,0],[-0.029,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0.029,0],[0.029,0],[0,0],[0,0]],"v":[[135.391,151.042],[109.375,177.058],[-109.374,177.058],[-135.391,151.042],[-135.391,-10.395],[-109.456,-10.395],[-109.369,-10.391],[-109.282,-10.395],[135.391,-10.395]],"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.644,0],[0,0],[0,0],[-48.809,0],[0,0],[-4.304,-45.367],[-8.61,0.821],[0.816,8.604],[21.928,20.01],[29.913,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-48.809],[0,0],[45.725,0],[0.816,8.604],[8.605,-0.816],[-2.795,-29.465],[-22.048,-20.119],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.041,-41.695],[-93.719,-41.695],[-93.719,-88.541],[-5.202,-177.058],[5.215,-177.058],[92.969,-97.48],[110.026,-83.378],[124.129,-100.436],[85.791,-177.159],[5.215,-208.358],[-5.202,-208.358],[-125.02,-88.541],[-125.02,-41.695],[-151.041,-41.695],[-166.691,-26.045],[-166.691,151.042],[-109.374,208.358],[109.375,208.358],[166.691,151.042],[166.691,-26.045]],"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('90-lock-closed-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":[249.997,250.002],"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":30,"op":302,"st":-30,"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.833],"y":[1]},"o":{"x":[0.51],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[1]},"o":{"x":[0.51],"y":[0]},"t":7,"s":[0]},{"i":{"x":[0.44],"y":[1]},"o":{"x":[0.51],"y":[0]},"t":17,"s":[0]},{"t":30,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":1},"o":{"x":0.51,"y":0},"t":0,"s":[249.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":1},"o":{"x":0.51,"y":0},"t":7,"s":[249.997,373.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.44,"y":1},"o":{"x":0.51,"y":0},"t":17,"s":[249.997,309.333,0],"to":[0,0,0],"ti":[0,0,0]},{"t":30,"s":[249.997,333.333,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.997,333.333,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]],"o":[[0,0],[0,0]],"v":[[0,0],[0,0]],"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('90-lock-closed-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":51.25,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249.998,312.498],"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],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-26.478],[0,26.478]],"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('90-lock-closed-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":[250.005,333.768],"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":2,"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],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-151.041,-109.377],[-151.041,67.71],[-109.374,109.377],[109.374,109.377],[151.041,67.71],[151.041,-109.377]],"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('90-lock-closed-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":[249.997,333.333],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"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":[140.623,223.957,0],"ix":2,"l":2},"a":{"a":0,"k":[-109.375,83.332,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.667,"y":1},"o":{"x":0.51,"y":0},"t":7,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.236,83.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":15.031,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,4.832],[109.375,5.835],[5.208,-98.332],[-5.208,-98.332],[-109.375,5.835],[-109.375,83.332]],"c":false}]},{"t":26,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,20.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.51],"y":[0]},"t":7,"s":[0]},{"t":15.03125,"s":[2.5]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","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('90-lock-closed-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":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"bm":0}]},{"id":"comp_3","nm":"in-unlock","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":[249.997,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.997,250.002,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.02,-0.42],[-0.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42]],"o":[[0.03,0.42],[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42]],"v":[[-25.596,-17.63],[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89]],"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('90-lock-closed-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":[249.995,331.386],"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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0],[-0.029,0],[-0.029,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0.029,0],[0.029,0],[0,0],[0,0]],"v":[[135.391,151.042],[109.375,177.058],[-109.374,177.058],[-135.391,151.042],[-135.391,-10.395],[-109.456,-10.395],[-109.369,-10.391],[-109.282,-10.395],[135.391,-10.395]],"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.644,0],[0,0],[0,0],[-48.809,0],[0,0],[-4.304,-45.367],[-8.61,0.821],[0.816,8.604],[21.928,20.01],[29.913,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-48.809],[0,0],[45.725,0],[0.816,8.604],[8.605,-0.816],[-2.795,-29.465],[-22.048,-20.119],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.041,-41.695],[-93.719,-41.695],[-93.719,-88.541],[-5.202,-177.058],[5.215,-177.058],[92.969,-97.48],[110.026,-83.378],[124.129,-100.436],[85.791,-177.159],[5.215,-208.358],[-5.202,-208.358],[-125.02,-88.541],[-125.02,-41.695],[-151.041,-41.695],[-166.691,-26.045],[-166.691,151.042],[-109.374,208.358],[109.375,208.358],[166.691,151.042],[166.691,-26.045]],"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('90-lock-closed-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":[249.997,250.002],"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":30,"op":302,"st":-30,"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":1,"k":[{"i":{"x":[0.318],"y":[1.007]},"o":{"x":[0.167],"y":[0.167]},"t":1,"s":[0]},{"i":{"x":[0.29],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":16,"s":[-24]},{"t":30,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.318,"y":0.999},"o":{"x":0.167,"y":0.167},"t":1,"s":[311.997,439.333,0],"to":[-6.083,-89.417,0],"ti":[18.083,13.417,0]},{"i":{"x":0.186,"y":0.995},"o":{"x":0.333,"y":0},"t":13,"s":[223.997,307.333,0],"to":[8.167,6.833,0],"ti":[-2.75,-4.5,0]},{"t":27,"s":[249.997,333.333,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.997,333.333,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.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.183,22.836],[2.183,22.836]],"c":false}]},{"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,0],[0,0]],"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('90-lock-closed-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":51.25,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249.998,312.498],"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":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[2.183,-3.642],[3.27,-3.448]],"c":false}]},{"t":8,"s":[{"i":[[0,0],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-26.478],[0,26.478]],"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('90-lock-closed-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":[250.005,333.768],"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":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-149.003,-4.562],[-148.755,0.919],[-107.088,42.586],[111.66,42.586],[153.327,0.919],[153.079,-4.562]],"c":true}]},{"t":8,"s":[{"i":[[0,0],[0,0],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-151.041,-109.377],[-151.041,67.71],[-109.374,109.377],[109.374,109.377],[151.041,67.71],[151.041,-109.377]],"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('90-lock-closed-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":[249.997,333.333],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","parent":2,"sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":13,"s":[0]},{"i":{"x":[0.4],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":19,"s":[-11]},{"t":30,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[140.623,321.957,0],"to":[0,-16.333,0],"ti":[0,16.333,0]},{"t":8,"s":[140.623,223.957,0]}],"ix":2,"l":2},"a":{"a":0,"k":[-109.375,83.332,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.985,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0,0],[0,0],[2.415,0],[0,0],[0,-2.6],[0,0]],"o":[[0,0],[0,-2.415],[0,0],[-2.6,0],[0,0],[0,0]],"v":[[109.375,83.332],[109.375,83.791],[105.002,79.418],[-104.668,79.418],[-109.375,84.125],[-109.375,83.332]],"c":false}]},{"t":16,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,20.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.985],"y":[1]},"o":{"x":[0.167],"y":[0]},"t":1,"s":[0]},{"t":16,"s":[4.5]}],"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('90-lock-closed-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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"bm":0}]},{"id":"comp_4","nm":"hover-unlock","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":[249.997,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.997,250.002,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.02,-0.42],[-0.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42]],"o":[[0.03,0.42],[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42]],"v":[[-25.596,-17.63],[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89]],"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('90-lock-closed-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":[249.995,331.386],"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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0],[-0.029,0],[-0.029,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0.029,0],[0.029,0],[0,0],[0,0]],"v":[[135.391,151.042],[109.375,177.058],[-109.374,177.058],[-135.391,151.042],[-135.391,-10.395],[-109.456,-10.395],[-109.369,-10.391],[-109.282,-10.395],[135.391,-10.395]],"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.644,0],[0,0],[0,0],[-48.809,0],[0,0],[-4.304,-45.367],[-8.61,0.821],[0.816,8.604],[21.928,20.01],[29.913,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-48.809],[0,0],[45.725,0],[0.816,8.604],[8.605,-0.816],[-2.795,-29.465],[-22.048,-20.119],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.041,-41.695],[-93.719,-41.695],[-93.719,-88.541],[-5.202,-177.058],[5.215,-177.058],[92.969,-97.48],[110.026,-83.378],[124.129,-100.436],[85.791,-177.159],[5.215,-208.358],[-5.202,-208.358],[-125.02,-88.541],[-125.02,-41.695],[-151.041,-41.695],[-166.691,-26.045],[-166.691,151.042],[-109.374,208.358],[109.375,208.358],[166.691,151.042],[166.691,-26.045]],"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('90-lock-closed-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":[249.997,250.002],"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":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":[249.997,250.002,0],"ix":2,"l":2},"a":{"a":0,"k":[249.997,250.002,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.02,-0.42],[-0.04,-0.42],[-0.07,-0.41],[-0.08,-0.41],[-0.24,-0.8],[-0.32,-0.77],[-0.4,-0.73],[-0.46,-0.7],[-0.24,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.3,-0.29],[-0.311,-0.28],[-0.33,-0.26],[-0.204,-0.157],[0,0],[-8.644,0],[0,8.643],[0,0],[-0.189,0.159],[-0.311,0.28],[-0.301,0.3],[-0.28,0.31],[-0.27,0.32],[-0.25,0.33],[-0.23,0.34],[-0.39,0.74],[-0.32,0.77],[-0.25,0.8],[-0.16,0.81],[-0.06,0.41],[-0.05,0.42],[-0.021,0.42],[0,0.42],[0.02,0.42],[0.04,0.42],[0.06,0.42],[0.08,0.41],[0.24,0.8],[0.319,0.77],[0.39,0.74],[0.46,0.69],[0.25,0.33],[0.26,0.33],[0.279,0.31],[0.29,0.3],[0.31,0.28],[0.329,0.26],[0.34,0.25],[0.35,0.23],[0.73,0.39],[0.77,0.32],[0.79,0.25],[0.819,0.16],[0.41,0.06],[0.41,0.04],[0.42,0.02],[0.829,-0.04],[0.42,-0.04],[0.41,-0.06],[0.409,-0.08],[0.8,-0.24],[0.77,-0.32],[0.73,-0.39],[0.7,-0.46],[0.34,-0.25],[0.319,-0.26],[0.31,-0.28],[0.29,-0.29],[0.28,-0.31],[0.261,-0.32],[0.25,-0.34],[0.23,-0.35],[0.39,-0.73],[0.31,-0.77],[0.239,-0.8],[0.17,-0.81],[0.06,-0.41],[0.04,-0.41],[0.03,-0.42],[0,-0.42]],"o":[[0.03,0.42],[0.04,0.42],[0.06,0.41],[0.17,0.81],[0.239,0.8],[0.31,0.77],[0.39,0.74],[0.23,0.34],[0.25,0.33],[0.261,0.32],[0.28,0.31],[0.29,0.3],[0.31,0.28],[0.195,0.165],[0,0],[0,8.643],[8.644,0],[0,0],[0.196,-0.153],[0.329,-0.26],[0.31,-0.28],[0.29,-0.29],[0.279,-0.31],[0.26,-0.32],[0.25,-0.34],[0.46,-0.7],[0.39,-0.73],[0.319,-0.77],[0.24,-0.8],[0.08,-0.41],[0.06,-0.41],[0.04,-0.42],[0.02,-0.42],[0,-0.42],[-0.021,-0.42],[-0.05,-0.41],[-0.06,-0.41],[-0.16,-0.81],[-0.25,-0.8],[-0.32,-0.77],[-0.39,-0.73],[-0.23,-0.35],[-0.25,-0.34],[-0.27,-0.32],[-0.28,-0.31],[-0.301,-0.29],[-0.311,-0.28],[-0.32,-0.26],[-0.33,-0.25],[-0.689,-0.46],[-0.739,-0.39],[-0.77,-0.32],[-0.8,-0.24],[-0.4,-0.08],[-0.42,-0.06],[-0.42,-0.04],[-0.84,-0.04],[-0.421,0.02],[-0.42,0.04],[-0.41,0.06],[-0.811,0.16],[-0.8,0.25],[-0.771,0.32],[-0.74,0.39],[-0.34,0.23],[-0.33,0.25],[-0.33,0.26],[-0.311,0.28],[-0.3,0.3],[-0.28,0.31],[-0.27,0.33],[-0.24,0.33],[-0.46,0.69],[-0.4,0.74],[-0.32,0.77],[-0.24,0.8],[-0.08,0.41],[-0.07,0.42],[-0.04,0.42],[-0.02,0.42],[0,0.42]],"v":[[-25.596,-17.63],[-25.495,-16.37],[-25.335,-15.12],[-25.125,-13.88],[-24.505,-11.45],[-23.655,-9.09],[-22.585,-6.82],[-21.306,-4.66],[-20.585,-3.63],[-19.806,-2.64],[-18.985,-1.68],[-18.115,-0.77],[-17.205,0.1],[-16.245,0.92],[-15.641,1.396],[-15.641,28.86],[0.01,44.51],[15.66,28.86],[15.66,1.381],[16.245,0.92],[17.205,0.1],[18.125,-0.77],[18.995,-1.68],[19.814,-2.64],[20.585,-3.63],[21.305,-4.66],[22.595,-6.82],[23.665,-9.09],[24.515,-11.45],[25.125,-13.88],[25.345,-15.12],[25.505,-16.37],[25.595,-17.63],[25.625,-18.89],[25.595,-20.15],[25.505,-21.41],[25.345,-22.66],[25.125,-23.9],[24.515,-26.33],[23.665,-28.69],[22.595,-30.96],[21.305,-33.11],[20.585,-34.14],[19.814,-35.14],[18.995,-36.09],[18.125,-37.01],[17.205,-37.88],[16.245,-38.7],[15.255,-39.47],[14.225,-40.19],[12.074,-41.48],[9.805,-42.55],[7.444,-43.4],[5.005,-44.01],[3.774,-44.23],[2.524,-44.39],[1.265,-44.48],[-1.255,-44.48],[-2.516,-44.39],[-3.766,-44.23],[-5.005,-44.01],[-7.436,-43.4],[-9.795,-42.55],[-12.065,-41.48],[-14.226,-40.19],[-15.255,-39.47],[-16.245,-38.7],[-17.205,-37.88],[-18.115,-37.01],[-18.985,-36.09],[-19.806,-35.14],[-20.585,-34.14],[-21.306,-33.11],[-22.585,-30.96],[-23.655,-28.69],[-24.505,-26.33],[-25.125,-23.9],[-25.335,-22.66],[-25.495,-21.41],[-25.596,-20.15],[-25.625,-18.89]],"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('90-lock-closed-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":[249.995,331.386],"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],[14.346,0],[0,0],[0,14.346],[0,0],[0,0],[-0.029,0],[-0.029,0],[0,0]],"o":[[0,14.346],[0,0],[-14.346,0],[0,0],[0,0],[0.029,0],[0.029,0],[0,0],[0,0]],"v":[[135.391,151.042],[109.375,177.058],[-109.374,177.058],[-135.391,151.042],[-135.391,-10.395],[-109.456,-10.395],[-109.369,-10.391],[-109.282,-10.395],[135.391,-10.395]],"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.644,0],[0,0],[0,0],[-48.809,0],[0,0],[-4.304,-45.367],[-8.61,0.821],[0.816,8.604],[21.928,20.01],[29.913,0],[0,0],[0,-66.067],[0,0],[0,0],[0,-8.643],[0,0],[-31.604,0],[0,0],[0,31.604],[0,0]],"o":[[0,0],[0,0],[0,-48.809],[0,0],[45.725,0],[0.816,8.604],[8.605,-0.816],[-2.795,-29.465],[-22.048,-20.119],[0,0],[-66.067,0],[0,0],[0,0],[-8.644,0],[0,0],[0,31.604],[0,0],[31.604,0],[0,0],[0,-8.643]],"v":[[151.041,-41.695],[-93.719,-41.695],[-93.719,-88.541],[-5.202,-177.058],[5.215,-177.058],[92.969,-97.48],[110.026,-83.378],[124.129,-100.436],[85.791,-177.159],[5.215,-208.358],[-5.202,-208.358],[-125.02,-88.541],[-125.02,-41.695],[-151.041,-41.695],[-166.691,-26.045],[-166.691,151.042],[-109.374,208.358],[109.375,208.358],[166.691,151.042],[166.691,-26.045]],"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('90-lock-closed-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":[249.997,250.002],"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":30,"op":332,"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.267],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[0]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":15.096,"s":[-18]},{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":23,"s":[14]},{"t":31,"s":[0]}],"ix":10},"p":{"a":1,"k":[{"i":{"x":0.267,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[249.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":11,"s":[192.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[273.997,333.333,0],"to":[0,0,0],"ti":[0,0,0]},{"t":29,"s":[249.997,333.333,0]}],"ix":2,"l":2},"a":{"a":0,"k":[249.997,333.333,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]],"o":[[0,0],[0,0]],"v":[[0,0],[0,0]],"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('90-lock-closed-outline').layer('Color & Stroke Change').effect('Primary')('Color');"},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":51.25,"ix":5},"lc":2,"lj":1,"ml":10,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[249.998,312.498],"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],[0,0]],"o":[[0,0],[0,0]],"v":[[0,-26.478],[0,26.478]],"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('90-lock-closed-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":[250.005,333.768],"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":2,"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],[-23.012,0],[0,0],[0,23.012],[0,0]],"o":[[0,0],[0,23.012],[0,0],[23.013,0],[0,0],[0,0]],"v":[[-151.041,-109.377],[-151.041,67.71],[-109.374,109.377],[109.374,109.377],[151.041,67.71],[151.041,-109.377]],"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('90-lock-closed-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":[249.997,333.333],"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 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"st":0,"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":[140.623,223.957,0],"ix":2,"l":2},"a":{"a":0,"k":[-109.375,83.332,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.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,20.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":9.059,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[110.108,40.71],[110.235,41.213],[6.068,-62.954],[-4.348,-62.954],[-108.515,41.213],[-109.375,83.332]],"c":false}]},{"t":13.587890625,"s":[{"i":[[0,0],[0,0],[57.53,0],[0,0],[0,-57.53],[0,0]],"o":[[0,0],[0,-57.53],[0,0],[-57.53,0],[0,0],[0,0]],"v":[[109.248,20.332],[109.375,20.835],[5.208,-83.332],[-5.208,-83.332],[-109.375,20.835],[-109.375,83.332]],"c":false}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":0,"k":0,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false},{"ty":"tm","s":{"a":0,"k":2.5,"ix":1},"e":{"a":0,"k":100,"ix":2},"o":{"a":0,"k":0,"ix":3},"m":1,"ix":3,"nm":"Trim Paths 2","mn":"ADBE Vector Filter - Trim","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('90-lock-closed-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":4,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":30,"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-Lock","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-Lock","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}}]},{"ty":5,"nm":"State-Morph-Lock-Unlock","np":3,"mn":"ADBE Slider Control","ix":6,"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-Intro-Unlock","np":3,"mn":"ADBE Slider Control","ix":7,"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-Unlock","np":3,"mn":"ADBE Slider Control","ix":8,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"in-lock","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-Lock')('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":41,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":0,"nm":"hover-lock","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-Lock')('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":41,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":0,"nm":"morph-lock-unlock","parent":3,"refId":"comp_2","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-Morph-Lock-Unlock')('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":41,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":0,"nm":"in-unlock","parent":3,"refId":"comp_3","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-Unlock')('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":41,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":0,"nm":"hover-unlock","parent":3,"refId":"comp_4","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-Unlock')('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":41,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/frontend/public/lotties/system-outline-96-groups.json b/frontend/public/lotties/system-outline-96-groups.json new file mode 100644 index 000000000..22638b692 --- /dev/null +++ b/frontend/public/lotties/system-outline-96-groups.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":60,"ip":0,"op":61,"w":500,"h":500,"nm":"96-groups-outline","ddd":0,"assets":[{"id":"comp_0","nm":"in-groups","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.003,260.41,0],"ix":2,"l":2},"a":{"a":0,"k":[250.003,260.41,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":[[8.644,0],[0,0],[0,8.643],[-8.644,0],[0,0],[24.064,0],[0,0],[0,8.643],[-8.644,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,-8.643],[0,0],[-2.61,-23.379],[0,0],[-8.644,0],[0,-8.643],[0,0],[43.092,0],[0,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-46.875,20.809],[30.935,20.809],[-15.625,-20.809],[-46.875,-20.809],[-62.526,-36.458],[-46.875,-52.108],[-15.625,-52.108],[62.526,26.042],[62.526,36.458]],"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('96-groups-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":[395.837,270.826],"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":[[8.644,0],[0,0],[0,8.643],[0,0],[-43.093,0],[0,0],[0,-8.643],[8.644,0],[0,0],[2.61,-23.379],[0,0],[0,-8.643]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[8.644,0],[0,8.643],[0,0],[-24.064,0],[0,0],[8.644,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-62.526,26.042],[15.625,-52.108],[46.875,-52.108],[62.526,-36.458],[46.875,-20.809],[15.625,-20.809],[-30.935,20.809],[46.875,20.809],[62.526,36.458]],"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('96-groups-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":[104.169,270.829],"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":2,"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":[[2.608,-23.381],[0,0],[24.066,0],[0,0]],"o":[[0,0],[-2.608,-23.381],[0,0],[-24.065,0]],"v":[[-93.435,20.81],[93.435,20.81],[46.874,-20.81],[-46.875,-20.81]],"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.644,0],[0,0],[0,8.643],[0,0],[-43.092,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[43.093,0],[0,0],[0,8.643]],"v":[[109.375,52.11],[-109.375,52.11],[-125.025,36.46],[-125.025,26.041],[-46.875,-52.11],[46.874,-52.11],[125.025,26.041],[125.025,36.46]],"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('96-groups-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,406.242],"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 3","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.733],[-3.19,67.733],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.733],[3.191,-67.733],[57.317,-13.607],[57.317,52.083]],"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('96-groups-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.003,265.62],"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 4","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.191,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[151.044,130.202],"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 5","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],[0,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.016,-13.607],[-26.016,13.608],[-3.19,36.434],[26.016,36.434],[26.016,-13.607],[3.192,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.192,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[343.753,130.202],"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 6","np":3,"cix":2,"bm":0,"ix":6,"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","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,406.242,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[0.761,0],[0,0],[0,-0.673],[0,0],[0,0],[0,0]],"o":[[0,0],[-0.673,0],[0,0],[0,0],[0,0],[0,-0.761]],"v":[[107.996,69.54],[-108.157,69.54],[-109.375,70.758],[-109.375,72.46],[109.375,72.46],[109.375,70.919]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":18,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-51.46],[-46.875,-51.46],[-109.375,11.04],[-109.375,34.46],[109.375,34.46],[109.375,11.04]],"c":true}]},{"t":35.9998693561873,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-36.46],[-46.875,-36.46],[-109.375,26.041],[-109.375,36.46],[109.375,36.46],[109.375,26.041]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.413,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[250.003,425.62,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":18,"s":[250.003,230.62,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[250.003,287.62,0],"to":[0,0,0],"ti":[0,0,0]},{"t":52.9998954849498,"s":[250.003,265.62,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":1,"s":[{"i":[[1.198,0],[0,0],[0,-1.195],[0,0],[-0.643,0],[0,0],[0,0]],"o":[[0,0],[-1.195,0],[0,0],[0,0.643],[0,0],[0,0],[0,-1.198]],"v":[[39.497,47.416],[-39.503,47.416],[-41.667,49.58],[-41.667,50.92],[-40.503,52.084],[41.667,52.084],[41.667,49.586]],"c":true}]},{"t":18.0000261287625,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[104.17,270.829,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[-4.222,0],[0,0]],"o":[[0,0],[0,0],[0,-4.222],[0,0],[0,0]],"v":[[47.01,112.459],[-46.741,112.459],[-46.741,111.171],[-39.111,103.541],[47.01,103.541]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,-6.958],[15.625,-69.459],[46.875,-69.459]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"c":false}]},{"t":55.9998954849498,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"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('96-groups-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":4,"op":60,"st":3.79933110367893,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.413,"y":1},"o":{"x":0.167,"y":0.167},"t":4,"s":[151.044,324.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":21,"s":[151.044,95.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":39,"s":[151.044,140.202,0],"to":[0,0,0],"ti":[0,0,0]},{"t":55.9998954849498,"s":[151.044,130.202,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":4,"s":[{"i":[[0.393,0],[0,0],[0,-0.344],[0,0],[-0.434,0],[0,0],[0,0]],"o":[[0,0],[-0.344,0],[0,0],[0,0.434],[0,0],[0,0],[0,-0.393]],"v":[[40.956,50.416],[-41.044,50.416],[-41.667,51.039],[-41.667,51.298],[-40.881,52.084],[41.667,52.084],[41.667,51.127]],"c":true}]},{"t":21.0000261287625,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":4,"op":60,"st":3.79933110367893,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.413,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[343.753,329.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[343.753,95.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":43,"s":[343.753,141.202,0],"to":[0,0,0],"ti":[0,0,0]},{"t":59.9998954849498,"s":[343.753,130.202,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0.37,0],[0,0],[0,-0.001],[0,0],[-0.572,0],[0,0],[0,0]],"o":[[0,0],[-0.504,0],[0,0],[0,0.002],[0,0],[0,0],[0,-0.001]],"v":[[40.997,51.798],[-40.753,51.798],[-41.667,51.8],[-41.667,52.081],[-40.631,52.084],[41.667,52.084],[41.667,51.799]],"c":true}]},{"t":25.0000261287625,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":8,"op":60,"st":7.79933110367893,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[395.838,270.826,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.413,"y":1},"o":{"x":0.167,"y":0.167},"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0.948,0],[0,0]],"o":[[0,0],[0,0],[0,-0.948],[0,0],[0,0]],"v":[[-46.913,113.459],[46.838,113.459],[46.8,112.254],[45.087,110.541],[-46.95,110.541]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.588,-7.958],[-15.912,-70.459],[-47.162,-70.459]],"c":false}]},{"t":42.9998693561873,"s":[{"i":[[0,0],[0,0],[0,0],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.875,26.042],[-15.625,-36.459],[-46.875,-36.459]],"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('96-groups-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":8,"op":60,"st":7.79933110367893,"bm":0}]},{"id":"comp_1","nm":"hover-groups","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.003,260.41,0],"ix":2,"l":2},"a":{"a":0,"k":[250.003,260.41,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":[[8.644,0],[0,0],[0,8.643],[-8.644,0],[0,0],[24.064,0],[0,0],[0,8.643],[-8.644,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,-8.643],[0,0],[-2.61,-23.379],[0,0],[-8.644,0],[0,-8.643],[0,0],[43.092,0],[0,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-46.875,20.809],[30.935,20.809],[-15.625,-20.809],[-46.875,-20.809],[-62.526,-36.458],[-46.875,-52.108],[-15.625,-52.108],[62.526,26.042],[62.526,36.458]],"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('96-groups-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":[395.837,270.826],"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":[[8.644,0],[0,0],[0,8.643],[0,0],[-43.093,0],[0,0],[0,-8.643],[8.644,0],[0,0],[2.61,-23.379],[0,0],[0,-8.643]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[8.644,0],[0,8.643],[0,0],[-24.064,0],[0,0],[8.644,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-62.526,26.042],[15.625,-52.108],[46.875,-52.108],[62.526,-36.458],[46.875,-20.809],[15.625,-20.809],[-30.935,20.809],[46.875,20.809],[62.526,36.458]],"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('96-groups-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":[104.169,270.829],"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":2,"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":[[2.608,-23.381],[0,0],[24.066,0],[0,0]],"o":[[0,0],[-2.608,-23.381],[0,0],[-24.065,0]],"v":[[-93.435,20.81],[93.435,20.81],[46.874,-20.81],[-46.875,-20.81]],"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.644,0],[0,0],[0,8.643],[0,0],[-43.092,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[43.093,0],[0,0],[0,8.643]],"v":[[109.375,52.11],[-109.375,52.11],[-125.025,36.46],[-125.025,26.041],[-46.875,-52.11],[46.874,-52.11],[125.025,26.041],[125.025,36.46]],"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('96-groups-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,406.242],"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 3","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.733],[-3.19,67.733],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.733],[3.191,-67.733],[57.317,-13.607],[57.317,52.083]],"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('96-groups-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.003,265.62],"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 4","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.191,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[151.044,130.202],"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 5","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],[0,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.016,-13.607],[-26.016,13.608],[-3.19,36.434],[26.016,36.434],[26.016,-13.607],[3.192,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.192,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[343.753,130.202],"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 6","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":1,"st":-60,"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.003,260.41,0],"ix":2,"l":2},"a":{"a":0,"k":[250.003,260.41,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":[[8.644,0],[0,0],[0,8.643],[-8.644,0],[0,0],[24.064,0],[0,0],[0,8.643],[-8.644,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,-8.643],[0,0],[-2.61,-23.379],[0,0],[-8.644,0],[0,-8.643],[0,0],[43.092,0],[0,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-46.875,20.809],[30.935,20.809],[-15.625,-20.809],[-46.875,-20.809],[-62.526,-36.458],[-46.875,-52.108],[-15.625,-52.108],[62.526,26.042],[62.526,36.458]],"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('96-groups-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":[395.837,270.826],"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":[[8.644,0],[0,0],[0,8.643],[0,0],[-43.093,0],[0,0],[0,-8.643],[8.644,0],[0,0],[2.61,-23.379],[0,0],[0,-8.643]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[8.644,0],[0,8.643],[0,0],[-24.064,0],[0,0],[8.644,0],[0,8.643]],"v":[[46.875,52.108],[-46.875,52.108],[-62.526,36.458],[-62.526,26.042],[15.625,-52.108],[46.875,-52.108],[62.526,-36.458],[46.875,-20.809],[15.625,-20.809],[-30.935,20.809],[46.875,20.809],[62.526,36.458]],"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('96-groups-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":[104.169,270.829],"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":2,"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":[[2.608,-23.381],[0,0],[24.066,0],[0,0]],"o":[[0,0],[-2.608,-23.381],[0,0],[-24.065,0]],"v":[[-93.435,20.81],[93.435,20.81],[46.874,-20.81],[-46.875,-20.81]],"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.644,0],[0,0],[0,8.643],[0,0],[-43.092,0],[0,0],[0,-43.092],[0,0]],"o":[[0,0],[-8.644,0],[0,0],[0,-43.092],[0,0],[43.093,0],[0,0],[0,8.643]],"v":[[109.375,52.11],[-109.375,52.11],[-125.025,36.46],[-125.025,26.041],[-46.875,-52.11],[46.874,-52.11],[125.025,26.041],[125.025,36.46]],"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('96-groups-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,406.242],"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 3","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.733],[-3.19,67.733],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.733],[3.191,-67.733],[57.317,-13.607],[57.317,52.083]],"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('96-groups-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.003,265.62],"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 4","np":3,"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,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.017,-13.607],[-26.017,13.608],[-3.19,36.434],[26.017,36.434],[26.017,-13.607],[3.191,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.191,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[151.044,130.202],"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 5","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],[0,-12.586],[0,0],[-12.587,0],[0,0],[0,0],[12.586,0]],"o":[[-12.587,0],[0,0],[0,12.586],[0,0],[0,0],[0,-12.586],[0,0]],"v":[[-3.19,-36.434],[-26.016,-13.607],[-26.016,13.608],[-3.19,36.434],[26.016,36.434],[26.016,-13.607],[3.192,-36.434]],"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.644,0],[0,0],[0,29.845],[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0]],"o":[[0,0],[-29.846,0],[0,0],[0,-29.846],[0,0],[29.845,0],[0,0],[0,8.643]],"v":[[41.667,67.734],[-3.19,67.734],[-57.317,13.608],[-57.317,-13.607],[-3.19,-67.734],[3.192,-67.734],[57.317,-13.607],[57.317,52.084]],"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('96-groups-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":[343.753,130.202],"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 6","np":3,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false}],"ip":60,"op":300,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,406.242,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.667,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-36.46],[-46.875,-36.46],[-109.375,26.041],[-109.375,36.46],[109.375,36.46],[109.375,26.041]],"c":true}]},{"i":{"x":0.413,"y":1},"o":{"x":0.333,"y":0},"t":14,"s":[{"i":[[22.97,0],[0,0],[0,-22.939],[0,0],[0,0],[0,0]],"o":[[0,0],[-22.94,0],[0,0],[0,0],[0,0],[0,-22.969]],"v":[[67.784,-10.067],[-67.839,-10.067],[-109.375,31.469],[-109.375,47.459],[109.375,47.459],[109.375,31.524]],"c":true}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30.001,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-51.46],[-46.875,-51.46],[-109.375,11.04],[-109.375,34.46],[109.375,34.46],[109.375,11.04]],"c":true}]},{"t":42.3432796822742,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-36.46],[-46.875,-36.46],[-109.375,26.041],[-109.375,36.46],[109.375,36.46],[109.375,26.041]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[250.003,265.62,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.572,"y":1},"o":{"x":0.333,"y":0},"t":14,"s":[250.003,341.327,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":30.001,"s":[250.003,230.62,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":42.343,"s":[250.003,287.62,0],"to":[0,0,0],"ti":[0,0,0]},{"t":54.0001045150502,"s":[250.003,265.62,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.413,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"c":true}]},{"t":30.0005748327759,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[104.17,270.829,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.667,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"c":false}]},{"i":{"x":0.413,"y":1},"o":{"x":0.333,"y":0},"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[-24.197,0],[0,0]],"o":[[0,0],[0,0],[0,-24.198],[0,0],[0,0]],"v":[[46.921,62.457],[-46.829,62.457],[-46.829,33.453],[-3.099,-10.277],[46.921,-10.277]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":33.001,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,-6.958],[15.625,-69.459],[46.875,-69.459]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45.343,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"c":false}]},{"t":57.0001045150502,"s":[{"i":[[0,0],[0,0],[0,0],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"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('96-groups-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":3.79933110367893,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[151.044,130.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.572,"y":1},"o":{"x":0.333,"y":0},"t":17,"s":[151.044,207.541,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":33.001,"s":[151.044,95.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":45.343,"s":[151.044,140.202,0],"to":[0,0,0],"ti":[0,0,0]},{"t":57.0001045150502,"s":[151.044,130.202,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.413,"y":1},"o":{"x":0.167,"y":0},"t":0,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"c":true}]},{"t":33.0005748327759,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":3.79933110367893,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[343.753,130.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.572,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[343.753,209.252,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[343.753,95.202,0],"to":[0,0,0],"ti":[0,0,0]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":48.343,"s":[343.753,141.202,0],"to":[0,0,0],"ti":[0,0,0]},{"t":59.9998954849498,"s":[343.753,130.202,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.413,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"c":true}]},{"t":36.0003658026756,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":7.79933110367893,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[395.838,270.826,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.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.875,26.042],[-15.625,-36.459],[-46.875,-36.459]],"c":false}]},{"i":{"x":0.413,"y":1},"o":{"x":0.333,"y":0},"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[23.077,0],[0,0]],"o":[[0,0],[0,0],[0,-23.078],[0,0],[0,0]],"v":[[-46.888,62.799],[46.862,62.799],[46.661,33.165],[4.955,-8.541],[-47.09,-8.541]],"c":false}]},{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.588,-7.958],[-15.912,-70.459],[-47.162,-70.459]],"c":false}]},{"t":48.3430706521739,"s":[{"i":[[0,0],[0,0],[0,0],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.875,26.042],[-15.625,-36.459],[-46.875,-36.459]],"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('96-groups-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":7.79933110367893,"bm":0}]},{"id":"comp_2","nm":"morph-group-single","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.002,249.974,0],"ix":2,"l":2},"a":{"a":0,"k":[250,249.999,0],"ix":1,"l":2},"s":{"a":0,"k":[2083,2083,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0.96],[0,0],[-0.96,0],[0,0],[0,-0.97]],"o":[[0,0],[-0.96,0],[0,0],[0,-0.96],[0,0],[0.96,0],[0,0]],"v":[[2,2.75],[-0.25,2.75],[-2,1],[-2,-1],[-0.25,-2.75],[0.25,-2.75],[2,-1]],"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":[[1.79,0],[0,0],[0,-1.79],[0,0],[-1.79,0],[0,0],[0,0.41],[0,0]],"o":[[0,0],[-1.79,0],[0,0],[0,1.79],[0,0],[0.41,0],[0,0],[0,-1.79]],"v":[[0.25,-4.25],[-0.25,-4.25],[-3.5,-1],[-3.5,1],[-0.25,4.25],[2.75,4.25],[3.5,3.5],[3.5,-1]],"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('96-groups-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,247.25],"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},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[1.38,-1.6],[1.78,0],[0,0],[0.8,-1.53],[0.04,1.99],[-1.57,1.64],[-2.27,0.05],[-0.07,0],[-1.6,-1.52],[-0.05,-2.27]],"o":[[-0.81,-1.52],[0,0],[-1.78,0],[-1.29,-1.49],[-0.06,-2.27],[1.57,-1.64],[0.07,0],[2.19,0],[1.64,1.57],[0.05,2.11]],"v":[[6.43,5.551],[2.25,3.011],[-2.25,3.011],[-6.43,5.561],[-8.49,0.211],[-6.15,-5.859],[-0.2,-8.489],[0.01,-8.489],[5.87,-6.139],[8.5,-0.189]],"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":[[1.87,-0.05],[1.55,1.25],[-1.37,0],[0,0],[-0.46,-1.25]],"o":[[-2.01,0.05],[0.46,-1.26],[0,0],[1.37,0],[-1.45,1.16]],"v":[[0.21,8.501],[-5.28,6.651],[-2.24,4.511],[2.26,4.511],[5.3,6.641]],"c":true},"ix":2},"nm":"Path 2","mn":"ADBE Vector Shape - Group","hd":false},{"ind":2,"ty":"sh","ix":3,"ks":{"a":0,"k":{"i":[[1.93,1.84],[2.67,-0.06],[1.84,-1.93],[-0.06,-2.67],[-1.93,-1.84],[-2.58,0],[-0.08,0],[-1.84,1.93],[0.06,2.67]],"o":[[-1.94,-1.84],[-2.67,0.06],[-1.84,1.94],[0.06,2.67],[1.88,1.79],[0.08,0],[2.67,-0.06],[1.84,-1.93],[-0.07,-2.67]],"v":[[6.9,-7.239],[-0.24,-9.999],[-7.24,-6.899],[-10,0.241],[-6.9,7.241],[-0.01,10.001],[0.24,10.001],[7.24,6.901],[10,-0.239]],"c":true},"ix":2},"nm":"Path 3","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('96-groups-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,249.999],"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":4,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"tr","p":{"a":0,"k":[250,249.999],"ix":2},"a":{"a":0,"k":[250,249.999],"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":60,"op":300,"st":0,"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":-180,"ix":10},"p":{"a":0,"k":[250.004,250.003,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.24,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[-1.15,-47.582],[93.245,-2.254],[2.254,93.245],[-34.998,0.428],[-42.245,0.014],[-31.103,-0.386]],"o":[[2.254,93.245],[-93.245,2.254],[-1.233,-51],[28.99,-0.354],[45.664,-0.015],[32.41,0.402]],"v":[[168.908,-72],[4.153,100.917],[-168.764,-63.838],[-113.49,-192.393],[-4.009,-192.982],[114.626,-192.381]],"c":true}]},{"t":60,"s":[{"i":[[-1.312,-54.294],[106.399,-2.572],[2.572,106.399],[-39.935,36.311],[-48.204,1.165],[-35.491,-32.769]],"o":[[2.572,106.399],[-106.399,2.572],[-1.407,-58.194],[33.08,-30.077],[52.105,-1.259],[36.981,34.145]],"v":[[192.652,-4.656],[4.656,192.652],[-192.652,4.656],[-129.581,-142.64],[-4.656,-192.652],[130.713,-141.6]],"c":true}]}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.24],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[39]},{"t":60,"s":[0]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.24],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":1,"s":[60]},{"t":60,"s":[100]}],"ix":2},"o":{"a":0,"k":94,"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","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('96-groups-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":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":1,"op":60,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.004,406.242,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.833,"y":0.901},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[34.518,0],[0,0],[0,-34.517],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[-34.518,0],[0,0],[0,0],[0,0],[0,0],[0,-34.517]],"v":[[46.875,-36.46],[-46.875,-36.46],[-109.375,26.041],[-109.375,36.46],[4.181,36.46],[109.375,36.46],[109.375,26.041]],"c":true}]},{"i":{"x":0.24,"y":1},"o":{"x":0.167,"y":0.099},"t":16.172,"s":[{"i":[[34.557,0],[0,0],[0,-32.321],[0,0],[-73.674,0],[0,0],[0,0]],"o":[[0,0],[-38.202,0],[0,0],[0,0],[73.326,0],[0,0],[-0.721,-36.266]],"v":[[46.867,-48.997],[-47.017,-48.997],[-114.395,14.67],[-114.437,21.691],[3.671,36.366],[114.339,21.681],[114.381,14.661]],"c":true}]},{"t":59.9997909698997,"s":[{"i":[[34.646,0],[0,0],[0,-27.281],[0,0],[-90.002,0],[0,0],[0,0]],"o":[[0,0],[-46.659,0],[0,0],[0,0],[81.998,0],[0,0],[-2.376,-40.281]],"v":[[46.851,-77.775],[-47.344,-77.775],[-125.918,-11.43],[-126.056,-12.211],[2.498,36.152],[125.734,-12.242],[125.872,-11.461]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[250.003,265.62,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.24,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[{"i":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"c":true}]},{"t":59.9997909698997,"s":[{"i":[[29.22,0],[0,0],[0,-29.221],[0,0],[-29.22,0],[0,0],[0,0]],"o":[[0,0],[-29.22,0],[0,0],[0,29.22],[0,0],[0,0],[0,-29.221]],"v":[[4.583,-145.62],[-4.192,-145.62],[-57.101,-92.711],[-57.101,-52.287],[-4.192,0.62],[57.49,0.62],[57.49,-92.711]],"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('96-groups-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":0.79933110367893,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.24,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[104.17,270.829,0],"to":[-42.5,0,0],"ti":[42.5,0,0]},{"t":59.9999477424749,"s":[-150.83,270.829,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],[-34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[46.875,36.459],[-46.875,36.459],[-46.875,26.042],[15.625,-36.459],[46.875,-36.459]],"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('96-groups-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":3.79933110367893,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":".primary.design","cl":"primary design","parent":5,"sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[46.875,-140.626,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":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":3.79933110367893,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":".primary.design","cl":"primary design","sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.24,"y":1},"o":{"x":0.333,"y":0},"t":1,"s":[395.838,270.826,0],"to":[41.333,0,0],"ti":[-41.333,0,0]},{"t":59.9998954849498,"s":[643.838,270.826,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],[34.583,0],[0,0]],"o":[[0,0],[0,0],[0,-34.584],[0,0],[0,0]],"v":[[-46.875,36.459],[46.875,36.459],[46.875,26.042],[-15.625,-36.459],[-46.875,-36.459]],"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('96-groups-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":7.79933110367893,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":".primary.design","cl":"primary design","parent":7,"sr":0.20066889632107,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[-52.084,-140.624,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":[[21.249,0],[0,0],[0,-21.251],[0,0],[-21.249,0],[0,0],[0,0]],"o":[[0,0],[-21.249,0],[0,0],[0,21.249],[0,0],[0,0],[0,-21.251]],"v":[[3.192,-52.084],[-3.19,-52.084],[-41.667,-13.607],[-41.667,13.608],[-3.19,52.084],[41.667,52.084],[41.667,-13.607]],"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('96-groups-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":7.79933110367893,"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}}]},{"ty":5,"nm":"State-Morph","np":3,"mn":"ADBE Slider Control","ix":6,"en":1,"ef":[{"ty":0,"nm":"Slider","mn":"ADBE Slider Control-0001","ix":1,"v":{"a":0,"k":0,"ix":1}}]}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":0,"nm":"in-groups","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-groups","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},{"ddd":0,"ind":6,"ty":0,"nm":"morph-group-single","parent":3,"refId":"comp_2","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-Morph')('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/scripts/start.sh b/frontend/scripts/start.sh index fea97eb6b..1db867e15 100644 --- a/frontend/scripts/start.sh +++ b/frontend/scripts/start.sh @@ -2,6 +2,8 @@ scripts/replace-variable.sh "$BAKED_NEXT_PUBLIC_POSTHOG_API_KEY" "$NEXT_PUBLIC_POSTHOG_API_KEY" +scripts/replace-variable.sh "$BAKED_NEXT_PUBLIC_INTERCOM_ID" "$NEXT_PUBLIC_INTERCOM_ID" + if [ "$TELEMETRY_ENABLED" != "false" ]; then echo "Telemetry is enabled" scripts/set-telemetry.sh true diff --git a/frontend/src/components/analytics/posthog.ts b/frontend/src/components/analytics/posthog.ts index 29208a795..b6f3e4341 100644 --- a/frontend/src/components/analytics/posthog.ts +++ b/frontend/src/components/analytics/posthog.ts @@ -6,7 +6,7 @@ import { ENV, POSTHOG_API_KEY, POSTHOG_HOST } from '../utilities/config'; export const initPostHog = () => { // @ts-ignore - console.log("Init Infisical") + console.log("Hi there 👋") try { if (typeof window !== 'undefined') { // @ts-ignore diff --git a/frontend/src/components/basic/EventFilter.tsx b/frontend/src/components/basic/EventFilter.tsx index 02a6705c6..7c3a9dc25 100644 --- a/frontend/src/components/basic/EventFilter.tsx +++ b/frontend/src/components/basic/EventFilter.tsx @@ -1,5 +1,5 @@ import React, { Fragment } from 'react'; -import { useTranslation } from 'next-i18next'; +import { useTranslation } from 'react-i18next'; import { faAngleDown, faEye, @@ -45,16 +45,16 @@ const EventFilter = ({ selected, select }: ListBoxProps): JSX.Element => { const { t } = useTranslation(); return ( - +
- + {selected !== '' ? ( -

{t(`activity:event.${selected}`)}

+

{t(`activity.event.${selected}`)}

) : ( -

{String(t('common:select-event'))}

+

{String(t('common.select-event'))}

)} {selected !== '' ? ( - select('')} /> + select('')} /> ) : ( )} @@ -65,12 +65,12 @@ const EventFilter = ({ selected, select }: ListBoxProps): JSX.Element => { leaveFrom="opacity-100" leaveTo="opacity-0" > - + {eventOptions.map((event, id) => ( @@ -79,7 +79,7 @@ const EventFilter = ({ selected, select }: ListBoxProps): JSX.Element => { className={`block truncate ${isSelected ? 'font-semibold' : 'font-normal'}`} > {' '} - {t(`activity:event.${event.name}`)} + {t(`activity.event.${event.name}`)} )} diff --git a/frontend/src/components/basic/InputField.tsx b/frontend/src/components/basic/InputField.tsx index a8ad953a4..df6dd1424 100644 --- a/frontend/src/components/basic/InputField.tsx +++ b/frontend/src/components/basic/InputField.tsx @@ -61,22 +61,6 @@ const InputField = ({

{label}

- {/* {label === "Password" && router.asPath !== "/login" && ( -
- - - The password should contain at least 8 - characters including at least 1 lowercase - character, uppercase character, number, and a - special character. - -
- )} */}
{ () => [ { href: `/dashboard/${workspaceMapping[workspaceSelected as any]}`, - title: t('nav:menu.secrets'), + title: t('nav.menu.secrets'), emoji: }, { href: `/users/${workspaceMapping[workspaceSelected as any]}`, - title: t('nav:menu.members'), + title: t('nav.menu.members'), emoji: }, { href: `/integrations/${workspaceMapping[workspaceSelected as any]}`, - title: t('nav:menu.integrations'), + title: t('nav.menu.integrations'), emoji: }, { @@ -167,7 +167,7 @@ const Layout = ({ children }: LayoutProps) => { }, { href: `/settings/project/${workspaceMapping[workspaceSelected as any]}`, - title: t('nav:menu.project-settings'), + title: t('nav.menu.project-settings'), emoji: } ], @@ -176,6 +176,7 @@ const Layout = ({ children }: LayoutProps) => { useEffect(() => { // Put a user in a workspace if they're not in one yet + const putUserInWorkSpace = async () => { if (tempLocalStorage('orgData.id') === '') { const userOrgs = await getOrganizations(); @@ -255,7 +256,7 @@ const Layout = ({ children }: LayoutProps) => {
- {t('nav:menu.project')} + {t('nav.menu.project')}
{Object.keys(workspaceMapping).length > 0 ? ( {

- {` ${t('common:no-mobile')} `} + {` ${t('common.no-mobile')} `}

diff --git a/frontend/src/components/basic/buttons/Button.tsx b/frontend/src/components/basic/buttons/Button.tsx index 5941b5437..461d160bb 100644 --- a/frontend/src/components/basic/buttons/Button.tsx +++ b/frontend/src/components/basic/buttons/Button.tsx @@ -53,11 +53,11 @@ const Button = ({ 'group m-auto md:m-0 inline-block rounded-md duration-200', // Setting background colors and hover modes - color === 'mineshaft' && activityStatus && 'bg-mineshaft-700 hover:bg-primary', + color === 'mineshaft' && activityStatus && 'bg-mineshaft-800 border border-mineshaft-600 hover:bg-primary/[0.15] hover:border-primary/60', color === 'mineshaft' && !activityStatus && 'bg-mineshaft', - (color === 'primary' || !color) && activityStatus && 'bg-primary hover:opacity-80', + (color === 'primary' || !color) && activityStatus && 'bg-primary border border-primary-400 opacity-80 hover:opacity-100', (color === 'primary' || !color) && !activityStatus && 'bg-primary', - color === 'red' && 'bg-red', + color === 'red' && 'bg-red-800 border border-red', // Changing the opacity when active vs when not activityStatus ? 'opacity-100 cursor-pointer' : 'opacity-40', @@ -74,11 +74,11 @@ const Button = ({ 'relative font-medium flex items-center', // Setting the text color for the text and icon - color === 'mineshaft' && 'text-gray-400', + color === 'mineshaft' && 'text-bunker-200', color !== 'mineshaft' && color !== 'red' && color !== 'none' && 'text-black', color === 'red' && 'text-gray-200', color === 'none' && 'text-gray-200 text-xl', - activityStatus && color !== 'red' && color !== 'none' ? 'group-hover:text-black' : '', + activityStatus && color !== 'red' && color !== 'mineshaft' && color !== 'none' ? 'group-hover:text-black' : '', size === 'icon' && 'flex items-center justify-center' ); diff --git a/frontend/src/components/basic/dialog/ActivateBotDialog.tsx b/frontend/src/components/basic/dialog/ActivateBotDialog.tsx index 521053d92..4f69f5296 100644 --- a/frontend/src/components/basic/dialog/ActivateBotDialog.tsx +++ b/frontend/src/components/basic/dialog/ActivateBotDialog.tsx @@ -1,5 +1,5 @@ import { Fragment } from 'react'; -import { useTranslation } from 'next-i18next'; +import { useTranslation } from 'react-i18next'; import { Dialog, Transition } from '@headlessui/react'; import Button from '../buttons/Button'; @@ -34,10 +34,9 @@ const ActivateBotDialog = ({ try { // type check if (!selectedIntegrationOption) return; - + // start integration or probe for PAT integrationOptionPress(selectedIntegrationOption); - } catch (err) { console.log(err); } @@ -71,20 +70,20 @@ const ActivateBotDialog = ({ leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > - + - {t('integrations:grant-access-to-secrets')} + {t('integrations.grant-access-to-secrets')}

- {t('integrations:why-infisical-needs-access')} + {t('integrations.why-infisical-needs-access')}

diff --git a/frontend/src/components/basic/dialog/AddApiKeyDialog.tsx b/frontend/src/components/basic/dialog/AddApiKeyDialog.tsx index 67f0c1f1f..5c2e26246 100644 --- a/frontend/src/components/basic/dialog/AddApiKeyDialog.tsx +++ b/frontend/src/components/basic/dialog/AddApiKeyDialog.tsx @@ -1,5 +1,5 @@ import { Fragment, useState } from 'react'; -import { useTranslation } from 'next-i18next'; +import { useTranslation } from 'react-i18next'; import { faCheck, faCopy } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { Dialog, Transition } from '@headlessui/react'; @@ -15,7 +15,7 @@ const expiryMapping = { '7 days': 604800, '1 month': 2592000, '6 months': 15552000, - '12 months': 31104000, + '12 months': 31104000 }; type Props = { @@ -27,12 +27,7 @@ type Props = { }; // TODO: convert to TS -const AddApiKeyDialog = ({ - isOpen, - closeModal, - apiKeys, - setApiKeys, -}: Props) => { +const AddApiKeyDialog = ({ isOpen, closeModal, apiKeys, setApiKeys }: Props) => { const [apiKey, setApiKey] = useState(''); const [apiKeyName, setApiKeyName] = useState(''); const [apiKeyExpiresIn, setApiKeyExpiresIn] = useState('1 day'); @@ -42,7 +37,7 @@ const AddApiKeyDialog = ({ const generateAPIKey = async () => { const newApiKey = await addAPIKey({ name: apiKeyName, - expiresIn: expiryMapping[apiKeyExpiresIn as keyof typeof expiryMapping], + expiresIn: expiryMapping[apiKeyExpiresIn as keyof typeof expiryMapping] }); setApiKeys([...apiKeys, newApiKey.apiKeyData]); @@ -73,143 +68,130 @@ const AddApiKeyDialog = ({ }; return ( -
+
- + -
+
-
-
+
+
{apiKey === '' ? ( - + - {t('section-api-key:add-dialog.title')} + {t('section.api-key.add-dialog.title')} -
-
-

- {t('section-api-key:add-dialog.description')} +

+
+

+ {t('section.api-key.add-dialog.description')}

-
+
-
+
-
-
+
+
) : ( - + - {t('section-api-key:add-dialog.copy-service-token')} + {t('section.api-key.add-dialog.copy-service-token')} -
-
-

- {t( - 'section-api-key:add-dialog.copy-service-token-description' - )} +

+
+

+ {t('section.api-key.add-dialog.copy-service-token-description')}

-
-
+
+
-
+ id="apiKey" + className="invisible w-full min-w-full bg-white/0 py-2 px-2 text-gray-400 outline-none" + /> +
{apiKey}
-
+
- - {t('common:click-to-copy')} + + {t('common.click-to-copy')}
-
+
diff --git a/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx b/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx index dddcfa30f..63535f2be 100644 --- a/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx +++ b/frontend/src/components/basic/dialog/AddIncidentContactDialog.tsx @@ -1,5 +1,5 @@ import { Fragment, useState } from 'react'; -import { useTranslation } from 'next-i18next'; +import { useTranslation } from 'react-i18next'; import { Dialog, Transition } from '@headlessui/react'; import addIncidentContact from '@app/pages/api/organization/addIncidentContact'; @@ -18,7 +18,7 @@ const AddIncidentContactDialog = ({ isOpen, closeModal, incidentContacts, - setIncidentContacts, + setIncidentContacts }: Props) => { const [incidentContactEmail, setIncidentContactEmail] = useState(''); const { t } = useTranslation(); @@ -29,69 +29,61 @@ const AddIncidentContactDialog = ({ ? incidentContacts.concat([incidentContactEmail]) : [incidentContactEmail] ); - addIncidentContact( - localStorage.getItem('orgData.id') as string, - incidentContactEmail - ); + addIncidentContact(localStorage.getItem('orgData.id') as string, incidentContactEmail); closeModal(); }; return (
- + -
+
-
-
+
+
- - - {t('section-incident:add-dialog.title')} + + + {t('section.incident.add-dialog.title')} -
-

- {t('section-incident:add-dialog.description')} +

+

+ {t('section.incident.add-dialog.description')}

-
+
-
+
diff --git a/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx b/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx index 43b55cd25..aceeb9db9 100644 --- a/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx +++ b/frontend/src/components/basic/dialog/AddProjectMemberDialog.tsx @@ -1,6 +1,6 @@ import { Fragment } from 'react'; +import { Trans, useTranslation } from 'react-i18next'; import { useRouter } from 'next/router'; -import { Trans, useTranslation } from 'next-i18next'; import { Dialog, Transition } from '@headlessui/react'; import Button from '../buttons/Button'; @@ -21,7 +21,7 @@ const AddProjectMemberDialog = ({ submitModal, data, email, - setEmail, + setEmail }: Props) => { const router = useRouter(); const { t } = useTranslation(); @@ -53,31 +53,31 @@ const AddProjectMemberDialog = ({ leaveFrom="opacity-100 scale-100" leaveTo="opacity-0 scale-95" > - + {data?.length > 0 ? ( - {t('section-members:add-dialog.add-member-to-project')} + {t('section.members.add-dialog.add-member-to-project')} ) : ( - {t('section-members:add-dialog.already-all-invited')} + {t('section.members.add-dialog.already-all-invited')} )}
{data?.length > 0 ? (

- {t('section-members:add-dialog.user-will-email')} + {t('section.members.add-dialog.user-will-email')}

) : (

- {t('section-members:add-dialog.add-user-org-first')} + {t('section.members.add-dialog.add-user-org-first')}

)}
{data?.length > 0 && ( - + )}
{data?.length > 0 ? ( -
+
@@ -124,7 +129,7 @@ const AddProjectMemberDialog = ({
) : ( - + - {t('section-token:add-dialog.copy-service-token')} + {t('section.token.add-dialog.copy-service-token')} -
-
-

- {t( - 'section-token:add-dialog.copy-service-token-description' - )} +

+
+

+ {t('section.token.add-dialog.copy-service-token-description')}

-
-
+
+
-
+ id="serviceToken" + className="invisible w-full min-w-full bg-white/0 py-2 px-2 text-gray-400 outline-none" + /> +
{serviceToken}
-
+
- - {t('common:click-to-copy')} + + {t('common.click-to-copy')}
-
+
diff --git a/frontend/src/components/basic/table/ProjectUsersTable.tsx b/frontend/src/components/basic/table/ProjectUsersTable.tsx index aea49e8e0..0f6df98d3 100644 --- a/frontend/src/components/basic/table/ProjectUsersTable.tsx +++ b/frontend/src/components/basic/table/ProjectUsersTable.tsx @@ -25,6 +25,7 @@ type Props = { changeData: (users: any[]) => void; myUser: string; filter: string; + isUserListLoading: boolean; }; type EnvironmentProps = { @@ -38,7 +39,7 @@ type EnvironmentProps = { * @param {*} props * @returns */ -const ProjectUsersTable = ({ userData, changeData, myUser, filter }: Props) => { +const ProjectUsersTable = ({ userData, changeData, myUser, filter, isUserListLoading }: Props) => { const [roleSelected, setRoleSelected] = useState( Array(userData?.length).fill(userData.map((user) => user.role)) ); @@ -205,7 +206,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter }: Props) => { }; return ( -
+
{ text="You can change user permissions if you switch to Infisical's Professional plan." /> - + @@ -231,7 +232,7 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter }: Props) => { - {userData?.filter( + {!isUserListLoading && userData?.filter( (user) => user.firstName?.toLowerCase().includes(filter) || user.lastName?.toLowerCase().includes(filter) || @@ -245,14 +246,14 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter }: Props) => { user.email?.toLowerCase().includes(filter) ) .map((row, index) => ( - - + - - ))} + {isUserListLoading && <> + + + }
NAME EMAIL
+
{row.firstName} {row.lastName} + {row.email} +
@@ -391,6 +392,10 @@ const ProjectUsersTable = ({ userData, changeData, myUser, filter }: Props) => {
diff --git a/frontend/src/components/billing/Plan.tsx b/frontend/src/components/billing/Plan.tsx index 692157923..2e8a47d2c 100644 --- a/frontend/src/components/billing/Plan.tsx +++ b/frontend/src/components/billing/Plan.tsx @@ -20,8 +20,8 @@ interface Props { export default function Plan({ plan }: Props) { return (
@@ -41,13 +41,13 @@ export default function Plan({ plan }: Props) { <> {plan.buttonTextMain === 'Schedule a Demo' ? ( -
+
{plan.buttonTextMain}
) : (

CURRENT PLAN

diff --git a/frontend/src/components/dashboard/CommentField.tsx b/frontend/src/components/dashboard/CommentField.tsx index 3308fdf1b..cd1ebc5ce 100644 --- a/frontend/src/components/dashboard/CommentField.tsx +++ b/frontend/src/components/dashboard/CommentField.tsx @@ -1,4 +1,4 @@ -import { useTranslation } from 'next-i18next'; +import { useTranslation } from 'react-i18next'; /** * This is the text field where people can add comments to particular secrets. @@ -16,9 +16,9 @@ const CommentField = ({ return (
-

{t('dashboard:sidebar.comments')}

+

{t('dashboard.sidebar.comments')}